using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using UnityEngine.Playables; // !!读写存档 using UnityEngine.SceneManagement; using System.Runtime.Serialization.Formatters.Binary; using System.IO; using LitJson; using System; //控制选中取消角色与角色的移动 public class GameManager : MonoBehaviour { public static GameManager instance; public GameObject menuUI; // 调出菜单 public float speed = 3.0f; // 镜头移动速度 public Character selected; // 记录选中的棋子 bool menuActive = false; // 是否显示菜单 bool exploreMode = false; // true时为探索模式,false时为战斗模式 public TMP_Text cellCost; // 显示鼠标所在单元格消耗行动力 public TMP_Text cellDamage; // 显示鼠标所在单元格造成的伤害 public TMP_Text characterHealth; // 显示鼠标所在角色当前生命值 public TMP_Text characterPoise; // 显示鼠标所在角色当前韧性值 public GameObject[] pieces; // 记录所有的棋子 public int[] groupCount; // 记录敌我双方棋子数量,groupCount[0]为友方,groupCount[1]为敌方 public int currentGroup = 0; // 当前的回合是哪一方的,0是友军,1是敌方 float horizontal; // 移动镜头 float vertical; // 移动镜头 public GameObject turnObject; // 回合UI public GameObject turnText; public TMP_Text DEX; public TMP_Text SAN; public TMP_Text VIG; public TMP_Text DEF; public TMP_Text STR; public TMP_Text INT; public TMP_Text CurrentHealth; public TMP_Text MaxHealth; public TMP_Text CurrentPoise; public TMP_Text MaxPoise; public TMP_Text CurrentMana; public TMP_Text MaxMana; public GameObject detailInformation; int enemyNumber; // 关卡中敌人总数 Character maincharacter; // 记录主角 public GameObject myBag; // 背包 bool isOpen; // 背包是否打开 public GameObject gameSettlement; // 结算界面 bool settlementFlag; // 是否需要结算界面 // 加点界面 public GameObject strAdd; public GameObject dexAdd; public GameObject sanAdd; public GameObject inteAdd; public GameObject defAdd; public GameObject vigAdd; public TMP_Text IsUsingSkill; // 背包 public Inventory myInventory; //控制摄像机移动范围 Rigidbody2D rigidbody2d; //过场动画 public enum GameMode { Normal, GamePlay, DialogueMovement } public GameMode gameMode; private PlayableDirector playableDirector; void Start() { SearchPieces(); SetCount(); SetExploreMode(); rigidbody2d = GetComponent(); if (GetExploreMode()) { settlementFlag = false; // 初始状态中无敌人时不需要结算界面 enemyNumber = 0; // 初始状态敌人数量为0 } else { settlementFlag = true; // 初始状态中有敌人时需要结算界面 enemyNumber = groupCount[1]; // 记录初始状态关卡中敌人总数 } if(UIManager.instance.openingStatus) gameMode = GameMode.GamePlay; else FinishedCG(); } private void Awake() { if(instance == null) instance = this; else if(instance != this) Destroy(gameObject); //DontDestroyOnLoad(gameObject); } public void FinishedCG() { gameMode = GameMode.Normal; RefreshCharacterUIs(); if(selected != null) selected.Cancel(); } public void ResumeTimeline() { gameMode = GameMode.GamePlay; playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(1d); //Debug.Log(UIManager.instance.name); UIManager.instance.ToggleSpaceBar(false); UIManager.instance.ToggleDialogueBox(false); } public void PauseTimeline(PlayableDirector director) { //Debug.Log(UIManager.instance.name); playableDirector = director; gameMode = GameMode.DialogueMovement; playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0d); UIManager.instance.ToggleSpaceBar(true); } void Update() { if(gameMode == GameMode.DialogueMovement) { if(Input.GetKeyDown("space")) { ResumeTimeline(); } } if(!menuActive) { if(GameManager.instance.gameMode == GameMode.Normal) { CheckIsUsingSkill(); ShowSettlement(); ShowTurn(); // 不显示菜单时先判断是否显示敌我回合 ShowBag(); // 不显示菜单时可以打开背包 // 选中角色时,镜头移动到角色上,方向键控制角色走动 if (selected != null) { // 取消选择 if(Input.GetMouseButtonDown(1)) { selected.Cancel(); return; } MoveCharacter(); // 选中角色在lookDirection方向上与NPC对话 if (exploreMode && Input.GetKeyDown(KeyCode.F)) selected.Dialogue(); // 选中角色在lookDirection方向上进入下一场景 if (exploreMode && selected == maincharacter) selected.EnterNextScene(); // 选中角色时按f捡起物品 if (Input.GetKeyDown("f")) selected.Pickup(); if(!exploreMode) { // 选中角色时可切换武器 if(Input.GetKeyDown("c")) selected.GetNextWeapon(); if(Input.GetKeyDown("e")) selected.weaponManager.SetWeaponsGUI(); if(Input.GetKeyDown("z")) { selected.skillManager.SetSkillsGUI(); bool value = !selected.skillManager.GetGameObjectValue(); //selected.weaponManager.gameObject.SetActive(value); } if(Input.GetKeyDown("x") && !selected.GetIsUsingSkill()) { selected.Attack(); } } } } } CallMenu(); } private void FixedUpdate() { if(!menuActive && selected == null) MoveCamera(); //未选中角色时,方向键控制镜头移动 } // 移动镜头 void MoveCamera() { horizontal = Input.GetAxis("Horizontal"); vertical = Input.GetAxis("Vertical"); Vector2 position = rigidbody2d.position; position.x += speed*horizontal*Time.deltaTime; position.y += speed*vertical*Time.deltaTime; rigidbody2d.MovePosition(position); } // 检测当前是在使用技能还是武器 void CheckIsUsingSkill() { if(selected == null) { IsUsingSkill.text = "---"; return; } if(selected.GetIsUsingSkill()) IsUsingSkill.text = "技能"; else IsUsingSkill.text = "武器"; } // 移动角色 void MoveCharacter() { transform.position = selected.transform.position; // 角色走动 if(Input.GetKeyDown("up")) { StartCoroutine(selected.Move(Vector2.up)); } if(Input.GetKeyDown("down")) { StartCoroutine(selected.Move(Vector2.down)); } if(Input.GetKeyDown("left")) { StartCoroutine(selected.Move(Vector2.left)); } if(Input.GetKeyDown("right")) { StartCoroutine(selected.Move(Vector2.right)); } // 角色转向 if(Input.GetKeyDown("w")) { selected.Turn(Vector2.up); } if(Input.GetKeyDown("s")) { selected.Turn(Vector2.down); } if(Input.GetKeyDown("a")) { selected.Turn(Vector2.left); } if(Input.GetKeyDown("d")) { selected.Turn(Vector2.right); } } // 呼出菜单 void CallMenu() { if(Input.GetKeyDown("escape")) { menuActive = !menuActive; menuUI.SetActive(menuActive); } } // 改变选中的棋子 public void SetSelected(Character character) { selected = character; } // 返回选中的棋子 public Character GetSelected() { return selected; } // 回合结束 public void TurnEnd() { //if(exploreMode) return; if(selected != null) selected.Cancel(); //int count = 0; if(currentGroup == 0) StartCoroutine(ApplyAIInTurn()); } IEnumerator ApplyAIInTurn() { currentGroup = 1; // AI行动 foreach (var piece in pieces) { AI character = piece.GetComponent(); if(piece.GetComponent().groupNumber == currentGroup) { character.ReSet(); character.buffManager.TurnEnd(); //Debug.Log("Start Time : " + Time.time); yield return StartCoroutine(character.ApplyAI()); //Debug.Log("End Time : " + Time.time); } //Debug.Log("count = " + count); } // 轮换至我方回合 currentGroup = 0; foreach (var piece in pieces) { if(piece.GetComponent().groupNumber == currentGroup) { piece.GetComponent().ReSet(); piece.GetComponent().buffManager.TurnEnd(); } } yield return null; } // 搜寻棋子 public void SearchPieces() { pieces = GameObject.FindGameObjectsWithTag("Pieces"); foreach (var piece in pieces) { if(piece.GetComponent().id == 0) { maincharacter = piece.GetComponent(); break; } } } // 数敌我双方棋子数 void SetCount() { groupCount = new int[3]; foreach (var piece in pieces) { Character character = piece.GetComponent(); groupCount[character.groupNumber] ++ ; //Debug.Log("gruopCount[" + character.groupNumber + "] = " + groupCount[character.groupNumber]); } } public bool GetExploreMode() { return exploreMode; } // 当敌人数量为0时,状态切换为探索模式 public void SetExploreMode() { if(groupCount[1] == 0) { if(selected != null) selected.Cancel(); exploreMode = true; //Debug.Log("exploreMode"); currentGroup = 0; foreach (var piece in pieces) { piece.GetComponent().buffManager.RemoveAllBuffs(); piece.GetComponent().ReSet(); } } } // 战斗结算 void MakeSettlement() { for (int i = 0; i < enemyNumber; i++) { maincharacter.money += 10; maincharacter.exp += 10; while (maincharacter.exp >= maincharacter.levelUp[maincharacter.level - 1]) { maincharacter.exp -= maincharacter.levelUp[maincharacter.level - 1]; maincharacter.level++; maincharacter.points += 5; } } } // 显示结算界面 void ShowSettlement() { if (settlementFlag) // 初始状态有敌人才需要结算 { if (exploreMode) // 战斗模式结束时显示结算界面 { MakeSettlement(); // 击杀所有敌人后获得经验和金钱 gameSettlement.SetActive(true); // 是否显示加点系统 if(maincharacter.points > 0) { strAdd.SetActive(true); dexAdd.SetActive(true); sanAdd.SetActive(true); inteAdd.SetActive(true); defAdd.SetActive(true); vigAdd.SetActive(true); } settlementFlag = false; // 此场景中不再需要结算界面 } } } void ShowTurn() // 显示战斗UI { if (exploreMode) turnObject.SetActive(false); else { if (currentGroup != 0) turnText.GetComponent().text = "敌方回合"; else turnText.GetComponent().text = "我方回合"; turnObject.SetActive(true); } } void ShowBag() // 是否显示背包 { isOpen = myBag.activeSelf; // 防止鼠标点击退出背包后按两次I才能再次打开 if(Input.GetKeyDown("i")) // 按I键打开背包 { isOpen = !isOpen; myBag.SetActive(isOpen); InventoryManager.RefreshItem(); } } public void ChangeCellInformation(int x, int y) { cellCost.text = x.ToString(); cellDamage.text = y.ToString(); } public void ChangeCharaterInformation(int x, int y) { characterHealth.text = x.ToString(); characterPoise.text = y.ToString(); } public void CheckDetailInformation(int str,int inte, int dex, int san,int vig, int def, int currentHealth, int maxHealth, int currentPoise, int maxPoise, int currentMana, int maxMana) { STR.text = str.ToString(); INT.text = inte.ToString(); DEX.text = dex.ToString(); SAN.text = san.ToString(); VIG.text = vig.ToString(); DEF.text = def.ToString(); CurrentHealth.text = currentHealth.ToString(); MaxHealth.text = maxHealth.ToString(); CurrentPoise.text = currentPoise.ToString(); MaxPoise.text = maxPoise.ToString(); CurrentMana.text = currentMana.ToString(); MaxMana.text = maxMana.ToString(); detailInformation.SetActive(true); //Debug.Log("!!"); } public void RefreshCharacterUIs() { foreach(var piece in pieces) { Character character = piece.GetComponent(); character.RefreshAllPointsBars(); } } // 保存数据 private Save CreateSaveGameObject() { Save save = new Save(); // 保存当前场景号 save.curSceneNumber = SceneManager.GetActiveScene().buildIndex; // 保存每个棋子 foreach(GameObject piece in pieces) { if(piece != null) { Character character = piece.GetComponent(); // 保存棋子的信息 save.characterId.Add(character.id); save.characterGroupNumber.Add(character.groupNumber); save.characterHealth.Add(character.GetCurrentHealth()); save.characterMana.Add(character.GetCurrentMana()); save.characterMovement.Add(character.GetCurrentMovement()); save.characterLevel.Add(character.level); save.characterPoint.Add(character.points); save.characterMoney.Add(character.money); save.characterExp.Add(character.exp); save.characterStr.Add(character.str); save.characterDex.Add(character.dex); save.characterSan.Add(character.san); save.characterInte.Add(character.inte); save.characterDef.Add(character.def); save.characterVig.Add(character.vig); // 保存棋子所拥有武器的信息 save.weaponMax.Add(character.weaponManager.maximum); for(int i = 0; i < character.weaponManager.maximum; i++) { Weapon weapon = character.weaponManager.weapons[i]; if(weapon.name == "knife") save.weaponType.Add(0); if(weapon.name == "sword") save.weaponType.Add(1); if(weapon.name == "greatsword") save.weaponType.Add(2); if(weapon.name == "lance") save.weaponType.Add(3); save.weaponLevel.Add(weapon.level); } // 保存棋子的位置 save.positionsX.Add(Convert.ToInt32(piece.transform.position[0])); save.positionsY.Add(Convert.ToInt32(piece.transform.position[1])); } } // 保存地图上的物品 GameObject[] items; items = GameObject.FindGameObjectsWithTag("Item"); foreach(GameObject item in items) { if(item.name == "Crystal") save.itemType.Add(0); if(item.name == "Health") save.itemType.Add(1); if(item.name == "Mana") save.itemType.Add(2); } // 保存是否需要进行结算 save.settlement = settlementFlag; return save; } // IEnumerator LoadScene(Save save) // { // SceneManager.LoadScene(save.curSceneNumber); // yield return null; // } // private IEnumerator SetGame(Save save) private void SetGame(Save save) { // 读取场景 // yield return StartCoroutine(LoadScene(save)); // yield return null; // SceneManager.LoadScene(save.curSceneNumber); GameObject[] pieces_; pieces_ = GameObject.FindGameObjectsWithTag("Pieces"); // 读取每个棋子 foreach(GameObject piece in pieces_) { int temp = 0; // 储存读取save.weapons与save.weaponLevel列表的下表 bool flag = false; // 判断棋子是否还存在 Character character = piece.GetComponent(); for(int i = 0; i < save.characterId.Count; i++) { if(character.id == save.characterId[i] && character.groupNumber == save.characterGroupNumber[i]) { // 读取棋子的信息 character.ChangeHealth(save.characterHealth[i] - character.GetMaxHealth()); character.ChangeMana(save.characterMana[i]); character.ChangeMovement(save.characterMovement[i] - character.GetMaxMovement()); character.level = save.characterLevel[i]; character.points = save.characterPoint[i]; character.money = save.characterMoney[i]; character.exp = save.characterExp[i]; character.str = save.characterStr[i]; character.dex = save.characterDex[i]; character.san = save.characterSan[i]; character.inte = save.characterInte[i]; character.def = save.characterDef[i]; character.vig = save.characterVig[i]; // 读取棋子所拥有武器的信息 character.weaponManager.maximum = save.weaponMax[i]; character.weaponManager.weapons = new Weapon[9]; for(int j = 0; j < character.weaponManager.maximum; j++) { if(save.weaponType[temp] == 0) { character.weaponManager.transform.Find("knife").GetComponent().valid = true; character.weaponManager.weapons[j] = character.weaponManager.transform.Find("knife").GetComponent(); } if(save.weaponType[temp] == 1) { character.weaponManager.transform.Find("sword").GetComponent().valid = true; character.weaponManager.weapons[j] = character.weaponManager.transform.Find("sword").GetComponent(); } if(save.weaponType[temp] == 2) { character.weaponManager.transform.Find("greatsword").GetComponent().valid = true; character.weaponManager.weapons[j] = character.weaponManager.transform.Find("greatsword").GetComponent(); } if(save.weaponType[temp] == 3) { character.weaponManager.transform.Find("lance").GetComponent().valid = true; character.weaponManager.weapons[j] = character.weaponManager.transform.Find("lance").GetComponent(); } character.weaponManager.weapons[j].level = save.weaponLevel[temp]; temp++; } // 读取棋子的位置 RaycastHit2D hit = Physics2D.Raycast(piece.transform.position, Vector2.up, 1.0f, LayerMask.GetMask("Cells")); hit.collider.GetComponent().SetOccupied(false); hit.collider.GetComponent().SetCurrentCharacter(null); piece.transform.position = new Vector2(save.positionsX[i], save.positionsY[i]); hit = Physics2D.Raycast(piece.transform.position, Vector2.up, 1.0f, LayerMask.GetMask("Cells")); hit.collider.GetComponent().SetOccupied(true); hit.collider.GetComponent().SetCurrentCharacter(character); flag = true; } else { temp += save.weaponMax[i]; } } // 若不存在则将血量置为0 if(!flag) character.ChangeHealth(0- character.GetMaxHealth()); } // 读取地图上的物品 GameObject[] items; items = GameObject.FindGameObjectsWithTag("Item"); foreach(GameObject item in items) { bool flag = false; // 判断物品是否还存在 for(int i = 0; i < save.itemType.Count; i++) { if(item.name == "Crystal" && save.itemType[i] == 0) flag = true; if(item.name == "Health" && save.itemType[i] == 1) flag = true; if(item.name == "Mana" && save.itemType[i] == 2) flag = true; } // 若不存在则摧毁物品 if(!flag) { RaycastHit2D hit = Physics2D.Raycast(item.transform.position, Vector2.up, 1.0f, LayerMask.GetMask("Cells")); hit.collider.GetComponent().SetOccupied(false); Destroy(item); } } // 读取是否需要进行结算 settlementFlag = save.settlement; } // Json方法存档 private void SaveByJson() { if(!Directory.Exists(Application.dataPath + "/StreamingFile")) Directory.CreateDirectory(Application.dataPath + "/StreamingFile"); // 存储角色、武器和地图数据 Save save = CreateSaveGameObject(); string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json"; string saveJsonStr = JsonMapper.ToJson(save); StreamWriter sw = new StreamWriter(filePath); sw.Write(saveJsonStr); sw.Close(); // 存储背包数据 filePath = Application.dataPath + "/StreamingFile" + "/MyInventory.txt"; BinaryFormatter bf = new BinaryFormatter(); FileStream file = File.Create(filePath); var saveJsonVar = JsonUtility.ToJson(myInventory); bf.Serialize(file, saveJsonVar); file.Close(); Debug.Log("保存成功"); } // Json方法读档 private void LoadByJson() { // 检测文件路径 if(!Directory.Exists(Application.dataPath + "/StreamingFile")) { Debug.Log("文件路径不存在"); return; } // 读取角色、武器和地图数据 string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json"; if(File.Exists(filePath)) { StreamReader sr = new StreamReader(filePath); string jsonStr = sr.ReadToEnd(); sr.Close(); Save save = JsonMapper.ToObject(jsonStr); // StartCoroutine(SetGame(save)); SetGame(save); } else Debug.Log("文件不存在"); // 读取背包数据 filePath = Application.dataPath + "/StreamingFile" + "/MyInventory.txt"; BinaryFormatter bf = new BinaryFormatter(); if(File.Exists(filePath)) { FileStream file = File.Open(filePath, FileMode.Open); JsonUtility.FromJsonOverwrite((string)bf.Deserialize(file), myInventory); file.Close(); Debug.Log("读档成功"); } else Debug.Log("文件不存在"); } // 保存游戏 public void SaveGame() { SaveByJson(); } // 加载游戏 public void LoadGame() { LoadByJson(); } }