using System; using System.Collections; using System.Collections.Generic; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines; using Common; using DragonLi.Core; using Mirror; using UnityEngine; using UnityEngine.PlayerLoop; using XPlugin.Data.JsonLiteDB; using static XPlugin.Data.JsonLiteDB.JsonLiteDB; using LitJson; using Pathfinding; using DarkTonic.MasterAudio; using NaughtyAttributes; using UnityEngine.UIElements; using Random = UnityEngine.Random; /// /// 游戏状态 /// public enum GameState { None = 0, Playing = 1, /// /// 胜利 /// Victory = 2, /// /// 失败 /// Failur = 3, Settle=4, /// /// 准备阶段 /// Wave=5, /// /// 冲锋阶段 /// EndEvent, } public enum GameEnemyEventType { None=0,//普通事件 Snipe=1,//狙击事件 Mortar=2,//迫击炮事件 MachineGun=3,//机关枪事件 SubmachineGun=4,//冲锋枪事件 Grenade=5,//手榴弹事件 Biochemical=6,//生化兵事件 Tank=7,//坦克兵事件 Bomber=8,//轰炸机事件 HelpNpc=9,//拯救平民事件 BulletUp=10,//子弹拾取事件 CleanUp=11,//清场事件 LastGame=12,//最终冲锋事件 } public enum GameMode { OnePlayer=0, TwoPlayers=1, } public class GameManager : NetworkBehaviour { public static GameManager Ins { get; private set; } #region 预制体 public GameObject DoorPre; public GameObject itemPropPre; public GameObject mortarBulletPre; public GameObject gqBulletPre; public GameObject gqMuzzleBulletPre; // 炮塔预制体集合 //public GameObject[] TowerPres; // 怪物预制集合 public GameObject[] EnemyPres; public GameObject[] playerAiPres; public GameObject playerEndAiPres; public GameObject explosionPre; public GameObject enemyGrenadePre; public GameObject enemyGasBombPre; public GameObject enemyEndAiPre; public GameObject enemyPlanePre; public GameObject[] playerNpcPre; // 怪物ui预制体 public GameObject EnemyUIPre; #endregion // json数据库 private JsonLiteDB DB; // 怪物信息集合 //public Dictionary EnemyInfos = new Dictionary(); public Dictionary PlayerAiInfos = new Dictionary(); // 炮塔信息集合 public Dictionary> TowerInfos = new Dictionary>(); // 枪械信息集合 //public Dictionary GunInfos = new Dictionary(); // 子弹信息集合 public Dictionary BulletInfos = new Dictionary(); public Dictionary AiInfos = new Dictionary(); public Dictionary RoundInfos = new Dictionary(); // 剧情信息 public Dictionary CombatUnitInfos = new Dictionary(); private List curGunPropList = new List(); public Dictionary players = new Dictionary(); public GameMode gameMode = GameMode.OnePlayer; /// /// 敌人自增 /// private int enemyIndex = 0; /// /// 所有敌人 /// public Dictionary EnemyList = new Dictionary(); public Dictionary PlayerAiList = new Dictionary(); /// /// 所有敌人UI /// public Dictionary EnemyUIList = new Dictionary(); /// /// 所有炮塔 /// public Dictionary TowerList = new Dictionary(); public Dictionary> TowerList2 = new Dictionary>(); public Dictionary SettleInfos = new Dictionary(); //public List curEnemyList = new List(); [SyncVar] public bool isStart; /// /// 波次自增 /// [SyncVar] public int roundIndex = 0; // 游玩结束时间 [NonSerialized] [SyncVar] public long vistEnd = 0; // 总游玩时长 private int vistAllTime = (int)(60 * 12); [SyncVar] public string settleData = ""; [SyncVar] public GameState gameState = GameState.None; [SoundGroup] public string JointIn; [SoundGroup] public string roundSound; public int roundWaveTime; public int curRoundWaveTime; //添加 [Header("魔力队长角色")] public GameObject player; public GameObject aiCharacterPre;//AI角色预制体 private GameObject aiCharacter;//AI角色实例 private bool isAIIntroductionComplete = false; //修改处:添加创建AI角色的方法 public void GamePlay() { CreateAICharacter(); } private void CreateAICharacter() { //检查是否已经存在AI角色 if (aiCharacter != null) { Debug.Log("AI角色已经存在,不再创建新的"); return; } if (aiCharacterPre != null) { Debug.Log("创建AI角色"); //获取第一个玩家 Transform player = players[0].transform ; if (player == null) { Debug.LogError("找不到玩家,无法创建AI角色"); return; } //在玩家前方创建AI角色 Vector3 spawnPosition = player.transform.position + player.transform.forward * 3f; spawnPosition.y = 0f; // 固定Y坐标为0 aiCharacter = Instantiate(aiCharacterPre, spawnPosition, Quaternion.identity); //获取AIController并启动开场白 AIController aiController = aiCharacter.GetComponent(); if (aiController != null) { //注册AI介绍完成回调 aiController.OnIntroductionComplete += StartGameAfterIntroduction; //添加延迟,确保所有组件已经完成初始化 StartCoroutine(DelayedStartIntroduction(aiController)); } else { Debug.LogError("AI预制体中的AIController组件丢失"); } } else { Debug.LogError("AI预制体没有在GameManager分配!"); } } private IEnumerator DelayedStartIntroduction(AIController aiController) { yield return new WaitForSeconds(0.1f); // 短暂延迟 aiController.StartIntroduction(); } public void StartGameAfterIntroduction() { isAIIntroductionComplete = true; GameStart(); } void Awake() { Ins = this; } void Start() { if (isClient) { isStart = false; CreateDoor(); } } /// /// 创建门 /// public void CreateDoor() { UpdateConf(); if (!isServer) return; GameObject door = Instantiate(DoorPre); door.transform.position = GameLocal.Ins.doorPos.position.ReflectVectorXOZ(); NetworkServer.Spawn(door); } /// /// 创建初回合 /// public void CreateFirstRound() { RpcShowHUD(); roundIndex = 0; PlaySound2DRPC("1.0"); // CoroutineTaskManager.Instance.WaitSecondTodo(() => // { // PlaySound2DRPC("1.1"); // }, 10f); CreatePlayerAi(); //SetGameState(GameState.Wave); RpcMessageRound(); } /// /// 创建下一回合 /// public void CreateNextRound() { roundIndex++; roundWaveTime = 3; curRoundWaveTime = 1; RpcMessageRound(); } [Server] public void GameStart() { gameState = GameState.Playing; gameMode = players.Count <= 1 ? GameMode.OnePlayer : GameMode.TwoPlayers; vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime; isStart = true; ChangeBgmRpc(0); AstarPath.active.Scan(); CreateFirstRound(); // 延迟1s后给所有人发放武器 CoroutineTaskManager.Instance.WaitSecondTodo(() => { GivePistol(GunType.Pistol); }, 1f); CoroutineTaskManager.Instance.WaitSecondTodo(() => { //GameOver(GameState.Settle); StartSpecialEvent(GameEnemyEventType.CleanUp); }, vistAllTime); } [ClientRpc] public void GivePistol(GunType type) { Debug.Log("创建武器中..."); GameLocal.Ins.self.PickUpGun(type, -999); } [Server] public void SetGameState(GameState state) { gameState = state; } //1.游戏时间到 //2.所有怪物被消灭 //3.玩家被消灭 //以上都要跳出结算 [Server] public void GameOver() { RpcShow(); DamageAllEnemy(); isStart = false; PlaySound2DRPC("1.60"); } [Server] public void PlayEndEvent() { Debug.LogError("开启End事件"); gameState = GameState.EndEvent; GivePistol(GunType.MeleeWeapon); foreach (var item in PlayerAiList.Values) { item.EndEvent(); } PlaySound2DRPC("1.61"); OpenDoor(); for (int i = 0; i < 7; i++) { Transform[] targetPos = GameLocal.Ins.enemyEndPos; GameObject enemy = Instantiate(enemyEndAiPre); NetworkServer.Spawn(enemy); int posId = i / 3; enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position; enemy.transform.eulerAngles = targetPos[posId].eulerAngles; enemyIndex++; Enemy enemyScript = enemy.GetComponent(); enemyScript.OnSpawn(enemyIndex, 3, 1, GameLocal.Ins.pkPos.position); enemyScript.ai.maxSpeed = 2; EnemyList.Add(enemyIndex, enemyScript); GameObject playerAi = Instantiate(playerEndAiPres); NetworkServer.Spawn(playerAi); playerAi.transform.position = GameLocal.Ins.endPlayerStartPos.position; playerAi.transform.eulerAngles = AiInfos[1].EulerAngles; PlayerAI playerAI = playerAi.GetComponent(); playerAI.OnSpawn(i + 2, PlayerAIType.EndPlayerAi, 1, enemy); playerAI.ai.maxSpeed = 2; PlayerAiList.Add(i + 2, playerAI); } curRoundEnemyCount = EnemyList.Count; } [ClientRpc] public void OpenDoor() { GameLocal.Ins.OpenDoor(); } [ClientRpc] public void RpcShowWin(bool isBlue) { } [ClientRpc] public void RpcShow() { SettlePanel.Show(); } /// /// 下一波进攻开始 /// [Server] public void RpcMessageRound() { if (!isStart) return; CoroutineTaskManager.Instance.WaitSecondTodo(() => { if (!isStart || gameState == GameState.EndEvent) return; PlaySound2DRPC("1.4"); }, curRoundWaveTime); CoroutineTaskManager.Instance.WaitSecondTodo(() => { if (!isStart || gameState == GameState.EndEvent) return; GetRoundEnemy(); SetGameState(GameState.Playing); }, roundWaveTime); } [ClientRpc] public void ShowHudRoundTime() { DragonLi.Core.EventDispatcher.TriggerEvent("NewWaveStart", roundIndex); } [ClientRpc] public void ChangeBgmRpc(int i) { GameLocal.Ins.BGMState.StateChange(i); } public int curRoundEnemyCount; /// /// 创建敌方单位 /// [Server] IEnumerator CreateEnemy(RoundInfo info) { curRoundEnemyCount = info.EnemyList.Count; for (int i = 0; i < info.EnemyList.Count; i++) { int enemyId = info.EnemyList[i]; bool isUerInfoAngles = (EnemyType)enemyId == EnemyType.Mortar; Transform[] targetPos = GameLocal.Ins.enemyEndPos; GameObject enemy = Instantiate(EnemyPres[enemyId - 3]); NetworkServer.Spawn(enemy); int posId = i / 3; int posX = i % 3 == 0 ? 0 : i % 3 == 1 ? 1 : -1; if (isUerInfoAngles) posX = 0; switch ((EnemyType)enemyId) { case EnemyType.Ordinary: case EnemyType.Sniper: break; case EnemyType.Mortar: targetPos = GameLocal.Ins.mortarPos; break; } enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position; enemy.transform.eulerAngles = isUerInfoAngles ? AiInfos[i + 3].EulerAngles : targetPos[posId].eulerAngles; enemyIndex++; Enemy enemyScript = enemy.GetComponent(); Vector3 endPos = targetPos[posId].position + new Vector3(0, 0, posX); if (enemyScript.type == EnemyType.Riflemen) { endPos = GameLocal.Ins.riflemenPos.position; } enemyScript.OnSpawn(enemyIndex, info.EnemyList[i], 1, endPos); EnemyList.Add(enemyIndex, enemyScript); yield return new WaitForSeconds(0.5f); } } /// /// 创建辅助AI /// public void CreatePlayerAi() { for (int i = 0; i < 2; i++) { GameObject playerAi = Instantiate(playerAiPres[i]); NetworkServer.Spawn(playerAi); playerAi.transform.position = GameLocal.Ins.playerAiPos[i].position; playerAi.transform.eulerAngles = AiInfos[i + 1].EulerAngles; PlayerAI enemyScript = playerAi.GetComponent(); enemyScript.OnSpawn(i, (PlayerAIType)i, 1, GameLocal.Ins.playerAiEndPos[i].gameObject); PlayerAiList.Add(i, enemyScript); } // else if(gameMode == GameMode.TwoPlayers) // { // GameObject playerAi = Instantiate(playerAiPres[0]); // NetworkServer.Spawn(playerAi); // playerAi.transform.position = GameLocal.Ins.playerAiPos[0].position; // playerAi.transform.eulerAngles = AiInfos[1].EulerAngles; // PlayerAI enemyScript = playerAi.GetComponent(); // enemyScript.OnSpawn(0,0, 1,GameLocal.Ins.playerAiEndPos[0].gameObject); // PlayerAiList.Add(0, enemyScript); // } } #region 创造敌人道具 [Server] public void CreateExplosion(Vector3 pos, EnemyType type) { if (!isServer) return; var ex = Instantiate(explosionPre, pos, Quaternion.identity); NetworkServer.Spawn(ex); ex.GetComponent().Init(type); } public void CreateGrenade(Vector3 startPos) { if (!isServer) return; var ex = Instantiate(enemyGrenadePre, startPos, Quaternion.identity); NetworkServer.Spawn(ex); float x = Random.Range(-3, 3); float z = Random.Range(-3, 3); ex.GetComponent().Init(startPos, GameLocal.Ins.endMortarPos.position + new Vector3(x, 0, z)); } public void CreateGasBomb(Vector3 startPos) { if (!isServer) return; var ex = Instantiate(enemyGasBombPre, startPos, Quaternion.identity); NetworkServer.Spawn(ex); float x = Random.Range(-3, 3); float z = Random.Range(-3, 3); ex.GetComponent().Init(startPos, GameLocal.Ins.endMortarPos.position + new Vector3(x, 0, z)); } public void CreateEnemyPlane(Transform startPos) { if (!isServer) return; var ex = Instantiate(enemyPlanePre, startPos.position, Quaternion.identity); NetworkServer.Spawn(ex); } public void CreateItemProp(Transform pos) { if (!isStart) return; var item = Instantiate(itemPropPre); NetworkServer.Spawn(item); item.transform.position = new Vector3(pos.position.x, 0.5f, pos.position.z); item.GetComponent().SetItemProp(ItemPropType.Hp); } #endregion public List GetRoundEnemy() { List curEnemyList = new List(); int curRoundIndex = roundIndex >= RoundInfos.Count ? Random.Range(1, RoundInfos.Count) : roundIndex; var roundInfo = RoundInfos[curRoundIndex]; // curRoundIndex=5; // roundInfo= RoundInfos[curRoundIndex]; StartEvent(roundInfo); if (roundIndex % 5 == 0 && roundIndex != 0) { CoroutineTaskManager.Instance.WaitSecondTodo(() => { StartSpecialEvent(GameEnemyEventType.HelpNpc); }, 5); } return curEnemyList; } public GameEnemyEventType curEnemyEventType; public void StartEvent(RoundInfo info) { curEnemyEventType = (GameEnemyEventType)info.Belong; StartCoroutine(CreateEnemy(info)); switch (curEnemyEventType) { case GameEnemyEventType.SubmachineGun: case GameEnemyEventType.None: CoroutineTaskManager.Instance.WaitSecondTodo(() => { Debug.LogError("播放音效:1.10"); PlayerAiList[0].PlaySound3DRPC("1.10", true); EnemyShowOutline(EnemyType.Ordinary); EnemyShowOutline(EnemyType.Charge); }, 10); break; case GameEnemyEventType.Snipe: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.14", true); }, 5); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.15", true); EnemyShowOutline(EnemyType.Sniper); }, 7); break; case GameEnemyEventType.Mortar: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.20", true); StartCoroutine(CreateMortarBullet()); }, 7); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.21", true); EnemyShowOutline(EnemyType.Mortar); }, 10); break; case GameEnemyEventType.MachineGun: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.24", true); StartCoroutine(CreateGQBullet()); }, 7); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.25", true); EnemyShowOutline(EnemyType.Riflemen); }, 10); break; case GameEnemyEventType.Grenade: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.35", true); }, 5); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.38", true); EnemyShowOutline(EnemyType.Grenade); }, 7); break; case GameEnemyEventType.Biochemical: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.40", true); }, 5); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.42", true); EnemyShowOutline(EnemyType.Virus); }, 7); break; case GameEnemyEventType.Bomber: CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.56", true); EnemyShowOutline(EnemyType.Commander); EnemyShowOutline(EnemyType.Mortar); EnemyShowOutline(EnemyType.Grenade); EnemyShowOutline(EnemyType.Virus); EnemyShowOutline(EnemyType.Riflemen); StartCoroutine(CreateGQBullet()); StartCoroutine(CreateMortarBullet()); }, 10); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.59", true); }, 20); break; } } public void StartSpecialEvent(GameEnemyEventType type) { switch (type) { case GameEnemyEventType.HelpNpc: CreateNpc(); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayerAiList[0].PlaySound3DRPC("1.67", true); }, 5); break; case GameEnemyEventType.CleanUp: CreateEnemyEndBullet(); break; } } private void Update() { // if (Input.GetKeyDown(KeyCode.Space)) // { // StartSpecialEvent(GameEnemyEventType.HelpNpc); // CoroutineTaskManager.Instance.WaitSecondTodo(() => // { // StartSpecialEvent(GameEnemyEventType.CleanUp); // }, 5); // } } IEnumerator CreateMortarBullet() { Transform insPos = GameLocal.Ins.insMortarPos; Transform endPos = GameLocal.Ins.endMortarPos; bool isHaveMortar = IsHaveTypeEnemy(EnemyType.Mortar); while (isHaveMortar) { var item = Instantiate(mortarBulletPre); NetworkServer.Spawn(item); item.transform.position = insPos.position; int rangeIndexX = Random.Range(-5, 5); int rangeIndexZ = Random.Range(-2, 2); item.GetComponent().Init(insPos.position, endPos.position + new Vector3(rangeIndexX, 0, rangeIndexZ)); yield return new WaitForSeconds(AiInfos[(int)EnemyType.Mortar].FiringRate); isHaveMortar = IsHaveTypeEnemy(EnemyType.Mortar); } } IEnumerator CreateGQBullet() { Transform insPos = GameLocal.Ins.gQPos; Vector3 endPos = GameLocal.Ins.riflemenEndPos.position; bool isHaveMortar = IsHaveTypeEnemy(EnemyType.Riflemen); while (isHaveMortar) { var item = Instantiate(gqBulletPre); NetworkServer.Spawn(item); item.transform.position = insPos.position; int rangeIndexZ = Random.Range(-2, 2); item.GetComponent().OnSpawn(endPos + new Vector3(rangeIndexZ, 0, rangeIndexZ), 20); var itemMuzzle = Instantiate(gqMuzzleBulletPre); NetworkServer.Spawn(itemMuzzle); itemMuzzle.transform.position = insPos.position; CoroutineTaskManager.Instance.WaitSecondTodo(() => { NetworkServer.Destroy(itemMuzzle.gameObject); }, 1); yield return new WaitForSeconds(AiInfos[(int)EnemyType.Riflemen].FiringRate); isHaveMortar = IsHaveTypeEnemy(EnemyType.Riflemen); } } [ClientRpc] public void OpenEndBullet() { GameLocal.Ins.OpenEndBullet(); } [ClientRpc] public void DownEndBullet() { GameLocal.Ins.DownEndBullet(); } public List NpcEnemyList = new List(); public void CreateNpc() { if (!isStart) return; for (int posId = 0; posId < 2; posId++) // npcPos[0] 和 npcPos[1] { List npcList = new List(); // === 生成 3 个 NPC === for (int i = 0; i < 3; i++) { int id = Random.Range(0, playerNpcPre.Length); // 在 npcPos 附近生成,带随机偏移 Vector3 randomOffset = new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)); Vector3 npcPos = GameLocal.Ins.npcPos[posId].position + randomOffset; var npc = Instantiate(playerNpcPre[id], npcPos, Quaternion.identity); NetworkServer.Spawn(npc); npc.GetComponent().OnSpawn(i, GameLocal.Ins.npcEndPos.gameObject, false); npcList.Add(npc); } // === 敌人生成逻辑 === // NPC 的平均位置(大致在3个 NPC 中心点) Vector3 centerPos = Vector3.zero; foreach (var npc in npcList) centerPos += npc.transform.position; centerPos /= npcList.Count; // 前进方向 Vector3 forward = GameLocal.Ins.npcPos[posId].forward; // 敌人在前进方向的反方向(后面) Vector3 backOffset = -forward * 3f; // 敌人与NPC中心点的间隔,数值可调 for (int j = 0; j < 2; j++) { // 敌人横向展开 Vector3 sideOffset = Vector3.Cross(Vector3.up, forward).normalized * (j == 0 ? -1.5f : 1.5f); Vector3 enemyPos = centerPos + backOffset + sideOffset; var enemy = Instantiate(EnemyPres[0], enemyPos, Quaternion.identity); NetworkServer.Spawn(enemy); enemy.GetComponent().OnSpawn(-j, 3, -1, GameLocal.Ins.npcPos[posId].position); enemy.GetComponent().isOutLine = true; NpcEnemyList.Add(enemy.GetComponent()); } } } public void CreateEnemyEndBullet() { PlayerAiList[0].PlaySound3DRPC("1.65", true); OpenEndBullet(); CoroutineTaskManager.Instance.WaitSecondTodo(() => { foreach (var item in EnemyList.Values) { item.Die(null, transform); } foreach (var item in NpcEnemyList) { item.Die(null, transform); } }, 5); CoroutineTaskManager.Instance.WaitSecondTodo(() => { PlayEndEvent(); DownEndBullet(); }, 8); } public bool IsHaveTypeEnemy(EnemyType curType) { foreach (var enemy in EnemyList.Values) { if (enemy.type == curType) return true; } return false; } public void EnemyShowOutline(EnemyType type) { foreach (var enemy in EnemyList.Values) { if (enemy.type == type) { enemy.isOutLine = true; } } } /// /// 删除敌方单位 /// [Server] public void DeleteEnemy(int id, bool isNpcEnemy) { if (isNpcEnemy) { foreach (var item in NpcEnemyList) { if (item.id == id) { NpcEnemyList.Remove(item); NetworkServer.Destroy(item.gameObject); return; } } return; } GameObject enemy = EnemyList[id].gameObject; EnemyList.Remove(id); curRoundEnemyCount--; NetworkServer.Destroy(enemy); ChangePlayerAiCountdownTime(); if (curRoundEnemyCount <= 0) { CreateNextRound(); if (gameState == GameState.EndEvent) { gameState = GameState.Victory; GameOver(); } } } /// /// 痛击场上所有敌方单位 /// [Command(requiresAuthority = false)] public void DamageAllEnemy() { foreach (Enemy enemy in EnemyList.Values) { enemy.ApplyDamage(999999, null, null); } } /// /// 更新配置表 /// public void UpdateConf() { string text = Resources.Load("Data").text; if (text != null) { ParseGameJson(text); } } public void ParseGameJson(string text) { DB = new JsonLiteDB(); DB.Load(text); roundWaveTime = 15; curRoundWaveTime = 12; AiInfos.Clear(); RoundInfos.Clear(); TableReader infoReader = DB["AiInfo"].GetReader(); // EnemyInfos.Clear(); // while (infoReader.Read()) // { // EnemyInfo info = new EnemyInfo(infoReader); // EnemyInfos.Add((EnemyType)info.Type,info); // } // // infoReader = DB["TowersInfo"].GetReader(); // while (infoReader.Read()) // { // TowerInfo info = new TowerInfo(infoReader); // TowerInfos.TryGetValue((TowerType)info.Type, out Dictionary infoList); // if (infoList == null) // { // Dictionary list = new Dictionary(); // list.Add(info.Lvl, info); // TowerInfos.Add((TowerType)info.Type, list); // } // else // { // infoList.Add(info.Lvl, info); // } // } // infoReader = DB["GunsInfo"].GetReader(); // GunInfos.Clear(); // while (infoReader.Read()) // { // GunInfo info = new GunInfo(infoReader); // GunInfos.Add((GunType)info.Type,info); // } // // infoReader = DB["BulletsInfo"].GetReader(); // BulletInfos.Clear(); // while (infoReader.Read()) // { // BulletInfo info = new BulletInfo(infoReader); // BulletInfos.Add((BulletType)info.Type,info); // } infoReader = DB["AiInfo"].GetReader(); while (infoReader.Read()) { AiInfo info = new AiInfo(infoReader); AiInfos.Add(info.ID, info); } infoReader = DB["RoundInfo"].GetReader(); while (infoReader.Read()) { RoundInfo info = new RoundInfo(infoReader); RoundInfos.Add(info.ID, info); } // infoReader = DB["StoryProgressInfo"].GetReader(); // while (infoReader.Read()) // { // CombatUnitInfo info = new CombatUnitInfo(infoReader); // CombatUnitInfos.Add(info.Belong,info); // CombatUnitInfos.TryGetValue(info.Belong, out info); // } Debug.Log("游戏数值更新 -> complete"); } /// /// 获取范围内敌人 /// public int GetRangeEnemyId(Vector3 pos, float radius) { int res = -1; foreach (Enemy enemy in EnemyList.Values) { float dis = Vector3.Distance(enemy.transform.position, pos); if (dis <= radius) { radius = dis; res = enemy.id; break; } } return res; } /// /// 获取最近的Ai /// /// public GameObject GetPlayerAi(Transform curTransform) { if (PlayerAiList.Count == 0) return null; GameObject nearestPlayer = null; float minDistance = float.MaxValue; foreach (var player in PlayerAiList) { if (player.Value == null || player.Key <= 1 || player.Value.isGet) continue; // 计算XZ平面距离(使用你的 ReflectVectorXOZ 方法) float dis = Vector3.Distance( player.Value.transform.position.ReflectVectorXOZ(), curTransform.position.ReflectVectorXOZ() ); if (dis < minDistance) { minDistance = dis; player.Value.isGet = true; nearestPlayer = player.Value.gameObject; } } return nearestPlayer; } public GameObject GetPlayer(Transform curTransform) { if (players == null || players.Count == 0) return null; GameObject nearestPlayer = null; float minDistance = float.MaxValue; foreach (var player in players.Values) { if (player == null) continue; // 计算XZ平面距离(使用你的 ReflectVectorXOZ 方法) float dis = Vector3.Distance( player.transform.position.ReflectVectorXOZ(), curTransform.position.ReflectVectorXOZ() ); if (dis < minDistance) { minDistance = dis; nearestPlayer = player.gameObject; } } return nearestPlayer; } /// /// 获取最近敌人 /// /// public GameObject GetEnemy(Transform playerAi) { GameObject nearestPlayer = null; float minDis = 999; foreach (var enemy in EnemyList.Values) { if (enemy == null) continue; // 计算XZ平面距离(使用你的 ReflectVectorXOZ 方法) float dis = Vector3.Distance( enemy.transform.position.ReflectVectorXOZ(), playerAi.position.ReflectVectorXOZ() ); if (dis < minDis) { nearestPlayer = enemy.gameObject; minDis = dis; } } return nearestPlayer; } public void ChangePlayerAiCountdownTime() { foreach (var ai in PlayerAiList.Values) { ai.ChangeKillEnemyTime(); } } public Transform GetPlayerPos() { int rand = Random.Range(0, 100); if (players.Count >= 2) // 双人模式 { if (rand < 45) // 0-44 return players[0].transform; // 玩家A else if (rand < 90) // 45-89 return players[1].transform; // 玩家B else // 90-99 return PlayerAiList[0].transform; // 队友A } else // 单人模式 { if (rand < 60) // 0-59 return players[0].transform; // 玩家 else if (rand < 80) // 60-79 return PlayerAiList[0].transform; // 队友A else // 80-99 return PlayerAiList[1].transform; // 队友B } } [Server] public void CreateEnemyUI(Enemy enemy) { GameObject enemyUI = Instantiate(EnemyUIPre); NetworkServer.Spawn(enemyUI); EnemyUI enemyUIScript = enemyUI.GetComponent(); enemyUIScript.Init(enemy); EnemyUIList.Add(enemy.id, enemyUIScript); } [Server] public void DeleteEnemyUI(int id) { GameObject enemyUI = EnemyUIList[id].gameObject; EnemyUIList.Remove(id); NetworkServer.Destroy(enemyUI); } [ClientRpc] public void RpcShowHUD() { HUDPanel.Show(); } #region 空投道具 /// /// 修复炮塔 /// public void RepairTower() { } /// /// 进入联控 /// [Server] public void JoinControlTower(int playerIndex) { PlayJointMusic(); // 修改所有炮塔模式 foreach (Tower tower in TowerList.Values) { if (tower.controllerId == -1) { tower.controllerId = playerIndex; tower.mode = TowerMode.Joint; } } TriggerEvent("JoinControlStart", playerIndex); CoroutineTaskManager.Instance.WaitSecondTodo(() => { ChangeBgmRpc(0); foreach (Tower tower in TowerList.Values) { if (tower.mode == TowerMode.Joint) { tower.controllerId = playerIndex; tower.mode = tower.originalMode; } TriggerEvent("JoinControlEnd", playerIndex); } }, 30f); } #endregion [ClientRpc] public void TriggerEvent(string key, int param) { DragonLi.Core.EventDispatcher.TriggerEvent(key, param); } public void AddScore(string index, int damage) { if (SettleInfos.ContainsKey(index)) { SettleInfos[index].Score += damage; } string jsonStr = JsonMapper.ToJson(SettleInfos); settleData = jsonStr; } public void SetTitle(string index, string title) { if (SettleInfos.ContainsKey(index)) { SettleInfos[index].Title = title; } Debug.Log(SettleInfos); } public void SetPlayerName(string index) { if (SettleInfos.ContainsKey(index)) { SettleInfos[index].playerName = int.Parse(index); } } [Server] public void AddData(int playerIndex) { SettleInfos.Add(playerIndex.ToString(), new SettleInfo()); } public string SerializeSettleInfos() { return JsonUtility.ToJson(SettleInfos); } public bool IsHaveEnemy() { return EnemyList.Count > 0; } #region 工具 public string GetLessTimeStr() { string res = ""; if (isStart) { res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds)); } return res; } public int GetLessTimeSeconds() { return (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds); } // 时分秒 public string FormatTime(int totalSeconds) { int hours = totalSeconds / 3600; // string hh = hours < 10 ? "0" + hours : hours.ToString(); int minutes = (totalSeconds - hours * 3600) / 60; string mm = minutes < 10f ? "0" + minutes : minutes.ToString(); int seconds = totalSeconds - hours * 3600 - minutes * 60; string ss = seconds < 10 ? "0" + seconds : seconds.ToString(); return string.Format("{0}:{1}", mm, ss); } #endregion public void PlaySound2DRPC(string sound) { MasterAudio.PlaySound(sound); } [ClientRpc] public void PlaySound3DRPC(string sound, Transform tran, bool isStop) { if (isStop) MasterAudio.StopAllSoundsOfTransform(tran); MasterAudio.PlaySound3DAtTransform(sound, tran); } public void PlayJointMusic() { MasterAudio.PlaySound(JointIn); GameLocal.Ins.BGMState.StateChange(2); } }