Interface
8 use synergy to control the monster's life cycle
Synergetic process
Timing, labor law, getting off work on time
Each has its own countermeasures
void Update() { timer += Time.deltaTime; if (timer > spawnTime) { timer = 0; //01 SpawnEnemy(); StartCoroutine(RandomSpawnTime()); } } IEnumerator RandomSpawnTime() { yield return new WaitForSeconds(Random.Range(1f,5f)); SpawnEnemy(); }
9 control the monster's death
Co process control generates death time, and min death time > Max generates events
But at present, the enemy is generated from the grid. When I come out and leave the house, I accelerate to rush to the player. When I meet the player, the player will lose blood and the enemy will destroy himself.
Therefore, only co process generation is used
10 set the rotation of the pistol
Correspondence between rotation axis and setting axis number
Rotating that position is equivalent to "turning on the motorcycle". The rotation of the handle is like the rotation of the x red axis; The rotation of the wheel is like the lifting and pressing of the muzzle of a gun
Observe the direction limit of the gun before operation
Explain the origin of that pile of multiplication and addition and subtraction
void RotateMuzzle()//Rotating muzzle { rotateXAxis = Input.mousePosition.y / Screen.height * maxYDir;//Up and down rotateYAxis = Input.mousePosition.x / Screen.width * maxXDir;//about *** rotateXAxis = -((Mathf.Clamp(rotateXAxis, minYDir, maxYDir))*4-20); rotateYAxis = (Mathf.Clamp(rotateYAxis, minXDir, maxXDir) -35)*2;*** transform.eulerAngles = new Vector3(rotateXAxis, rotateYAxis, 0f); }
17 making menu UI
Grid layout group = = grid of ngui
27 create a Save class
Summarize the labels you have encountered so far
[System.Serializable]//Class details [SerializeField] //Object details [Tooltip("")]//Tips, editors and codes all have tips [HideInInspector]//Editor hidden
Save class
[System.Serializable] public class SaveGame : MonoBehaviour { public List<int> enemyPosList=new List<int>(); public List<int> enemyTypeList=new List<int>(); public int score; public int killCount;
call
public SaveGame SaveGame()//Save the enemy's type, position, score and kill count { SaveGame saveGame = new SaveGame(); foreach(GameObject go in enemyObjectList) { saveGame.enemyTypeList.Add(go.GetComponent<Enemy>().type); saveGame.enemyPosList.Add(enemyObjectList.IndexOf(go)); } list1 = saveGame.enemyTypeList;//Print list2 = saveGame.enemyPosList; a1 =saveGame.score = Player._instance.score; a2=saveGame.killCount = Player._instance.killCount; return saveGame; }
output
28 save game (binary method)
(problem) saving Transform, Vector3, etc. is not supported
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMember
A small pit encountered in Unity serialization
The video is a Jiugong grid, and the position remains unchanged, so the index value is used. I need to record the transformation (at least position and rotation) in the way of flying
The four data types, scores and kill counts are all integers. Only Transform can't do it. Position can't do it. I haven't tried. The following structure is used to record position.
The structure is used to process Vector3 on the Internet. So split the Transform into three parts POS, rotate and scale (I won't)
At present, only position Vector3 is recorded, which is represented by structure
technological process
The previous save class modification
[Serializable] public class SaveGame { public List<int> enemyTypeList = new List<int>(); public List<Vector3Serializer> enemyPosList = new List<Vector3Serializer>(); public int score; public int killCount; }
Enemy
[Serializable]public struct Vector3Serializer { public float x; public float y; public float z; public void Fill(Vector3 v3) { x = v3.x; y = v3.y; z = v3.z; } public Vector3 V3 { get { return new Vector3(x, y, z); } } } public class Enemy : MonoBehaviour { ... public Vector3Serializer pos;
EnemyController
public SaveGame SaveGame()//Save the enemy's type, position, score and kill count { SaveGame save = new SaveGame(); foreach(GameObject go in enemyObjectList) { Enemy enemy = go.GetComponent<Enemy>(); //type save.enemyTypeList.Add(enemy.type); //Position assignment, in the form of structure go.GetComponent<Enemy>().pos.Fill(go.transform.position); save.enemyPosList.Add(enemy.pos); save.score = enemy.score; save.killCount = enemy.score; } return save; }
UI code, file flow
StreamingFile is a new folder created under the root directory of Unity. I don't know if it will automatically help us create it. After all, bybin1 Txt didn't exist at first
Save again to overwrite
FileStream feels like a inserted "funnel". SaveGame is oil and BinaryFormatter is to "pour oil"
void SaveByBin() { BinaryFormatter binaryFormatter = new BinaryFormatter(); FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/ByBin1.txt"); SaveGame save = EnemyController._instance.SaveGame(); binaryFormatter.Serialize(fileStream, save); fileStream.Close(); }
result
29 read game (binary method)
UIController
BinaryFormatter "flips" data from FileStream to SaveGame
SaveGame LoadByBin() { BinaryFormatter binaryFormatter = new BinaryFormatter(); FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/ByBin1.txt", FileMode.Open); SaveGame save = (SaveGame)binaryFormatter.Deserialize(fileStream); fileStream.Close(); return save; } public void LoadGame() { ResetGame();//Clear set 0 SaveGame save= LoadByBin();//File reading EnemyController._instance.LoadGame(save);//enemy Player._instance.LoadGame(save);//Kill count, score scoreText.text = save.score.ToString(); killCountText.text = save.killCount.ToString(); }
EnemyController
public void LoadGame(SaveGame save) { for (int i = 0; i < save.enemyTypeList.Count; i++) { GameObject go = Instantiate( enemyPrefabList[save.enemyTypeList[i]] ); go.transform.position = save.enemyPosList[i].V3; enemyObjectList.Add(go); } }
Make code snippets
It's meaningless if you can't reuse it. The style is in xml format
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>SaveLoadByBin</Title> <Shortcut>SaveLoadByBin</Shortcut> <Description>Binary Reading Archive</Description> <Author>user name</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> <SnippetType>SurroundsWith</SnippetType> </SnippetTypes> </Header> <Snippet> <Code Language="csharp"><![CDATA[ [Serializable] public class SaveGame { public List<int> enemyTypeList = new List<int>(); public List<Vector3Serializer> enemyPosList = new List<Vector3Serializer>(); public int score; public int killCount; } void SaveByBin() { BinaryFormatter binaryFormatter = new BinaryFormatter(); FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/ByBin1.txt"); SaveGame save = EnemyController._instance.SaveGame(); binaryFormatter.Serialize(fileStream, save); fileStream.Close(); } SaveGame LoadByBin() { BinaryFormatter binaryFormatter = new BinaryFormatter(); FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/ByBin1.txt", FileMode.Open); SaveGame save = (SaveGame)binaryFormatter.Deserialize(fileStream); fileStream.Close(); return save; } ]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
30-31 save game (JSON)
phenomenon
After archiving, unity will not be refreshed automatically in time. It needs to be refreshed manually. At first, I thought it was unsuccessful or the speed was too slow
Binary does not support Vector3, so use structure. Now json does not support Vector3 and structure does not support Vector3
01 split list < vector3 > into list < int >, list < int >, list < int > and store x, y and Z respectively
02 store x,y,z in every three places in a list, and so on
Adopt 2, because json is also a string of data together, waiting to be cut
So I gave up the previous structure
JsonException: Max allowed object depth reached while trying to export from type System.Single
jsonData does not support float, so double is used
JsonException: Max allowed object depth reached while trying to export from type System.Single
restructure
The part of data read and saved before is put into UIC controller, and it is taken out and put into the new GameController
Save class
[Serializable] public class SaveGame { public List<int> enemyTypeList = new List<int>(); public List<double> enemyXYZList = new List<double>(); public int score; public int killCount; }
GameController
void SaveByJson(SaveGame save, string path) { string str = JsonMapper.ToJson(save); StreamWriter streamWriter = new StreamWriter(Application.dataPath + path); streamWriter.Write(str); streamWriter.Close(); } SaveGame LoadByJson(string path) { StreamReader streamreader = new StreamReader(Application.dataPath + path);//Read data and convert it into data stream JsonReader json = new JsonReader(streamreader);//Then convert it into json data SaveGame save = JsonMapper.ToObject<SaveGame>(json);//read streamreader.Close(); return save; } public void SaveGame() { print("Save the game!"); SaveGame save = EnemyController._instance.SaveGame(); SaveByJson(save, "/StreamingFile" + "/ByJson.json"); if (File.Exists(Application.dataPath + "/StreamingFile" + "/ByJson.json")) { UIController._instance.ShowMessage("Saved successfully!"); } } public void LoadGame() { ResetGame();//Clear set 0 //SaveGame save= LoadByBin("/StreamingFile" + "/ByBin.txt");// File reading SaveGame save = LoadByJson("/StreamingFile" + "/ByJson.json");//File reading //SaveGame save= LoadByXml();// File reading EnemyController._instance.LoadGame(save);//enemy Player._instance.LoadGame(save);//Kill count, score UIController._instance.SetRecordUI(save.score, save.killCount); }
EnemyController
Called by LoadGame of UI
public SaveGame SaveGame()//Save the enemy's type, position, score and kill count { SaveGame save = new SaveGame(); foreach(GameObject go in enemyObjectList) { Enemy enemy = go.GetComponent<Enemy>(); //type save.enemyTypeList.Add(enemy.type); //Position assignment Vector3 pos= go.transform.position; save.enemyXYZList.Add(pos.x); save.enemyXYZList.Add(pos.y); save.enemyXYZList.Add(pos.z); enemyObjectXYZList = save.enemyXYZList;//Print and see this.enemyTypeList = save.enemyTypeList;//Print and see save.score = Player._instance.score; save.killCount = Player._instance.score; } UIController._instance.ShowMessage("Storage complete"); return save; } public void LoadGame(SaveGame save) { for (int i = 0; i < save.enemyTypeList.Count; i++) { GameObject go = Instantiate( enemyPrefabList[save.enemyTypeList[i]] ); int j = i * 3;//012 345 678 ...... go.transform.position = new Vector3((float)save.enemyXYZList[j], (float)save.enemyXYZList[j+1], (float)save.enemyXYZList[j+2]); enemyObjectList.Add(go); } }
result
There are 3 enemies in the archive, 2, 3 and 2 respectively. The position is vector3 (- 12.699999092651, 14.9000015258789, 8.44331550598145), and so on
{ "enemyTypeList": [2, 3, 2], "enemyXYZList": [**-12.6999998092651, 14.9000015258789, 8.4433155059814**5, -0.200000002980232, 29.0, 15.3022012710571, -0.400000005960464, 1.40000081062317, 22.9358730316162], "score": 10, "killCount": 10 }
32-33 save game (XML)
(question) can be printed, but there is only the last one in the file
Put variables outside the loop, resulting in only one
Save class
Although it was written earlier, it is the benchmark for writing, reading and archiving. I'm still writing it. It is suggested that all the code be made into code fragments
[Serializable] public class SaveGame { public List<int> enemyTypeList = new List<int>(); public List<double> enemyXYZList = new List<double>(); public int score; public int killCount; }
Save, GameController
public void SaveGame() { print("Save the game!"); SaveGame save = EnemyController._instance.SaveGame(); SaveByXml(save, "/StreamingFile" + "/ByXml.txt"); if (File.Exists(Application.dataPath + "/StreamingFile" + "/ByXml.txt")) { UIController._instance.ShowMessage("Saved successfully!"); } } void SaveByXml(SaveGame save, string path) { XmlDocument xmlDoc = new XmlDocument(); XmlElement root = xmlDoc.CreateElement("save"); root.SetAttribute("name","SaveFile1"); for (int i = 0; i < save.enemyTypeList.Count; i++) { XmlElement target = xmlDoc.CreateElement("target"); //Type and location XmlElement type = xmlDoc.CreateElement("type"); XmlElement x = xmlDoc.CreateElement("x"); XmlElement y = xmlDoc.CreateElement("y"); XmlElement z = xmlDoc.CreateElement("z"); type.InnerText = save.enemyTypeList[i].ToString(); int j = i * 3; x.InnerText = save.enemyXYZList[j].ToString(); y.InnerText = save.enemyXYZList[j+1].ToString(); z.InnerText = save.enemyXYZList[j+2].ToString(); print(type.InnerText+","+x.InnerText+ "," + y.InnerText+ "," + z.InnerText);//Print and see target.AppendChild(type); target.AppendChild(x); target.AppendChild(y); target.AppendChild(z); root.AppendChild(target); }
Load GameController
public void LoadGame() { SaveGame save= LoadByXml("/StreamingFile" + "/ByXml.txt");//File reading EnemyController._instance.LoadGame(save);//enemy Player._instance.LoadGame(save);//Kill count, score UIController._instance.SetRecordUI(save.score, save.killCount); } SaveGame LoadByXml(string path) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(Application.dataPath+path); SaveGame save = new SaveGame(); // XmlNodeList targetList = xmlDoc.GetElementsByTagName("target"); for (int i = 0; i < targetList.Count; i++) { int type = int.Parse(targetList[i].ChildNodes[0].InnerText); double x = double.Parse(targetList[i].ChildNodes[1].InnerText); double y = double.Parse(targetList[i].ChildNodes[2].InnerText); double z = double.Parse(targetList[i].ChildNodes[3].InnerText); save.enemyTypeList.Add(type); save.enemyXYZList.Add(x); save.enemyXYZList.Add(y); save.enemyXYZList.Add(z); } // int score = int.Parse(xmlDoc.GetElementsByTagName("score")[0].InnerText); int killCount = int.Parse(xmlDoc.GetElementsByTagName("killCount")[0].InnerText); save.score = score; save.killCount = killCount; return save; }
result
Continue the screen operation of the game, and the screenshot description is of little significance (only moving pictures)