using System.Collections.Generic; using System; using UnityEngine; using UnityEngine.Events; using System.Collections; using vnxbqy.UI; public class GAMgr : SingletonMonobehaviour { private List reAdjustPosList = new List(); public void AddReJustPosActor(GActor actor) { if (actor == null) { #if UNITY_EDITOR Debug.LogFormat("矫正坐标 => 要添加的目标是空的."); #endif return; } if (reAdjustPosList.Contains(actor)) { #if UNITY_EDITOR Debug.LogFormat("矫正坐标 => 已添加过目标: {0}/{1}", actor.GetType(), actor.ServerInstID); #endif return; } reAdjustPosList.Add(actor); } public void DoReAdjustPos() { var _model = ModelCenter.Instance.GetModel(); foreach (var actor in reAdjustPosList) { var _func = actor as GA_NpcFunc; if (_func != null) { bool _needHide = _func.NpcConfig.Show == 0; if (_model.NPCShowDic.ContainsKey(_func.NpcConfig.NPCID)) { if (_model.NPCShowDic[_func.NpcConfig.NPCID] == 1) { _needHide = false; } } if (_needHide) { continue; } } actor.AdjustPos((ushort)actor.ActorInfo.serverBornPos.x, (ushort)actor.ActorInfo.serverBornPos.y); } } public void ClearReJustActor() { if (reAdjustPosList.Count > 0) { reAdjustPosList.Clear(); } } private List m_BossSkillTipList = new List(); public Dictionary s_NpcID2BundleName = new Dictionary(); public Dictionary s_NpcID2Assetname = new Dictionary(); public event UnityAction OnGActorRequest; public event UnityAction OnGActorServerDie; public event UnityAction OnFightNpcRequest; public event UnityAction OnFightNpcRelease; // 由角色池生成的prefab列表. 用来卸载用的. public List needDestroyPrefabList = new List(); public List needDieList = new List(); public void AddNeedDestroyPrefab(GameObject go) { if (go && !needDestroyPrefabList.Contains(go)) { needDestroyPrefabList.Add(go); // Debug.LogFormat("添加需要销毁的对象: {0}", go.name); } //else //{ // Debug.LogFormat("X 无法添加需要销毁的对象: {0}", go.name); //} } public void RemoveNeedDestroyPrefab(GameObject go) { if (go && needDestroyPrefabList.Contains(go)) { needDestroyPrefabList.Remove(go); // Debug.LogFormat("移除想销毁的对象: {0}", go.name); } //else //{ // Debug.LogFormat("X 无法移除想销毁的对象: {0}", go.name); //} } // id池 private IDFactory m_ClientId; private IDFactory m_SimulateServerID; // 回收池 private Dictionary> m_Free; // 分组角色 private Dictionary> m_Group; // 分类型角色 private Dictionary> m_Type; // 所有对象 private List m_AllList; // 服务器id对应当前客户端角色id private Dictionary m_Sid2Cid; // 客户端id对应相应角色 private Dictionary m_Cid2GA; private List m_OffLineList; // 服务端通知的死亡目标对应的客户端id, // 这里为了处理可能出现的无法死亡现象,对每一只目标进行计时,强制其死亡 private List serverDeadList = new List(); private Dictionary serverDeadDict = new Dictionary(); public Dictionary atkOtherPlayerDict = new Dictionary(); public Dictionary otherPlayerAtkHeroDict = new Dictionary(); // 保证只初始化一次 private bool m_Inited = false; public void Init() { if (!m_Inited) { m_ClientId = new IDFactory(1); m_SimulateServerID = new IDFactory(900000); m_Free = new Dictionary>(); m_Group = new Dictionary>(); m_Type = new Dictionary>(); m_AllList = new List(); m_Sid2Cid = new Dictionary(); m_Cid2GA = new Dictionary(); m_OffLineList = new List(); m_Inited = true; SystemSetting.Instance.playerSyncCountChangeEvent += OnPlayerSyncCountChange; SystemSetting.Instance.OnSettingChanged += OnSettingChanged; SystemSetting.Instance.qualityLevelChangeEvent += OnQualityLevelChange; } } private void OnQualityLevelChange() { List _list = GetTypeList(E_ActorClassType.Pet); GA_Player _player = null; if (_list != null && _list.Count > 0) { //Debug.LogFormat("共有: {0} 只宠物", _petList.Count); foreach (var _pet in _list) { var _parentID = _pet.ActorInfo.ownerSID; if (_parentID == PlayerDatas.Instance.PlayerId) { continue; } _player = GetBySID(_parentID) as GA_Player; if (_player == null || !_player.ShowOrHide) { _pet.ShowOrHideModel(false); _pet.HideEffect(); //Debug.LogFormat("宠物: {0} 的拥有者: {1} 不可见, 这里隐藏.", _pet.ServerInstID, _parentID); continue; } var _index = BattleEffectPlayRule.Instance.GetIndex(_parentID); if (_index != -1 && _index < BattleEffectPlayRule.Instance.petLimit) { _pet.ShowOrHideModel(true); //Debug.LogFormat("宠物: {0} 的拥有者: {1} 在列表中且位于: {2}, 小于限制数量: {3}", _pet.ServerInstID, _parentID, _index, BattleEffectPlayRule.Instance.petLimit); } else { _pet.ShowOrHideModel(false); //Debug.LogFormat("宠物: {0} 的拥有者: {1} 在列表中且位于: {2}, 大于限制数量: {3}", _pet.ServerInstID, _parentID, _index, BattleEffectPlayRule.Instance.petLimit); } if (_index != -1 && _index < BattleEffectPlayRule.Instance.petEffectLimit) { _pet.ShowEffect(); } else { _pet.HideEffect(); } } } _list = GetTypeList(E_ActorClassType.Player); if (_list != null && _list.Count > 0) { //Debug.LogFormat("共有: {0} 只守护", _list.Count); foreach (var _chkPlayer in _list) { _player = _chkPlayer as GA_Player; if (_chkPlayer == null || !_chkPlayer.ShowOrHide) { _player.SwitchGuard(0); _player.HideHorseEffect(); //Debug.LogFormat("_list: {0} 的拥有者: {1} 不可见, 这里隐藏.", _chkPlayer.ServerInstID, _player.ServerInstID); continue; } var _index = BattleEffectPlayRule.Instance.GetIndex(_player.ServerInstID); if (_index != -1 && _index < BattleEffectPlayRule.Instance.petLimit) { _player.SwitchGuard((uint)_player.serverGuardId); //Debug.LogFormat("_list: {0} 的拥有者: {1} 在列表中且位于: {2}, 小于限制数量: {3}", _chkPlayer.ServerInstID, _player.ServerInstID, _index, BattleEffectPlayRule.Instance.petLimit); } else { _player.SwitchGuard(0); //Debug.LogFormat("_list: {0} 的拥有者: {1} 在列表中且位于: {2}, 大于限制数量: {3}", _chkPlayer.ServerInstID, _player.ServerInstID, _index, BattleEffectPlayRule.Instance.petLimit); } if (_index != -1 && _index < BattleEffectPlayRule.Instance.horseEffectLimit) { _player.ShowHorseEffect(); _player.ShowWeaponEffect(); _player.ShowSecondaryEffect(); //Debug.LogFormat("_list: {0} 的拥有者: {1} 在列表中且位于: {2}, 小于限制数量: {3}", _chkPlayer.ServerInstID, _player.ServerInstID, _index, BattleEffectPlayRule.Instance.petLimit); } else { _player.HideHorseEffect(); _player.HideWeaponEffect(); _player.HideSecondaryEffect(); //Debug.LogFormat("_list: {0} 的拥有者: {1} 在列表中且位于: {2}, 大于限制数量: {3}", _chkPlayer.ServerInstID, _player.ServerInstID, _index, BattleEffectPlayRule.Instance.petLimit); } } } } public void AddOffLinePlayer(uint sid) { if (m_OffLineList.Contains(sid)) { return; } m_OffLineList.Add(sid); } public void RemoveOffLinePlayer(uint sid) { if (m_OffLineList.Contains(sid)) { m_OffLineList.Remove(sid); } } public void ClearOffLinePlayer() { m_OffLineList.Clear(); } private float m_UpdateOffLineInterval; private List m_CacheList = new List(); private List m_ContaintList = new List(); private void UpdateOffLinePlayer() { if (m_OffLineList == null || m_OffLineList.Count == 0) { return; } if (Time.realtimeSinceStartup - m_UpdateOffLineInterval > 2) { m_CacheList.Clear(); m_ContaintList.Clear(); int _count = Mathf.Min(m_OffLineList.Count, 4); //Debug.LogFormat("此次将会有: {0} 个挂机者释放技能", _count); for (int i = 0; i < m_OffLineList.Count; ++i) { m_CacheList.Add(m_OffLineList[i]); } int _time = 0; while (m_ContaintList.Count < _count) { int _index = UnityEngine.Random.Range(0, m_CacheList.Count); m_ContaintList.Add(m_CacheList[_index]); //Debug.LogFormat("添加对象: {0}, 已添加: {1} 个", m_CacheList[_index], m_ContaintList.Count); m_CacheList.RemoveAt(_index); if (_time > _count) { //Debug.LogFormat("共添加了: {0} 个玩家", m_ContaintList.Count); break; } _time++; } GA_Player _player = null; for (int i = 0; i < m_ContaintList.Count; ++i) { _player = GetBySID(m_ContaintList[i]) as GA_Player; if (_player == null) { continue; } _player.UpdateOffLineAction(); } m_UpdateOffLineInterval = Time.realtimeSinceStartup; } } private void OnSettingChanged(SystemSwitch type, bool value) { //普通小怪关闭时最多显示4个 int defaultCnt = 4; int showCnt = 0; if (type == SystemSwitch.HideMonster) { List _nomrlNPCList = GetTypeList(E_ActorClassType.NpcFightNorm); GActorNpcFight _npcFight; if (_nomrlNPCList != null) { for (int i = 0; i < _nomrlNPCList.Count; ++i) { _npcFight = _nomrlNPCList[i] as GActorNpcFight; if (_npcFight == null || _npcFight is GA_Pet) { continue; } //此处的value时反的 if (value == true && showCnt < defaultCnt) { _npcFight.ShowOrHideModel(true); } else { _npcFight.ShowOrHideModel(!value); } showCnt++; } } } } private List m_CheckPlayerList = new List(); public void OnPlayerSyncCountChange() { int _limitCount = SystemSetting.Instance.GetPlayerSyncCount(); int _teamCount = 0; int _familyCount = 0; List _playerList = GetTypeList(E_ActorClassType.Player); if (_playerList == null) { return; } m_CheckPlayerList.Clear(); GA_Hero _hero = PlayerDatas.Instance.hero; GActorFight _player = null; int _curCount = _playerList.Count; for (int i = _curCount - 1; i >= 0; --i) { _player = GetTypeList(E_ActorClassType.Player)[i] as GActorFight; if (atkOtherPlayerDict.ContainsKey(_player.ServerInstID) || otherPlayerAtkHeroDict.ContainsKey(_player.ServerInstID)) { if (m_CheckPlayerList.Count >= _limitCount) { _player.ShowOrHideModel(false); } else { m_CheckPlayerList.Add(_player); _player.ShowOrHideModel(true); } } } _limitCount -= m_CheckPlayerList.Count; m_CheckPlayerList.Clear(); for (int i = _curCount - 1; i >= 0; --i) { _player = GetTypeList(E_ActorClassType.Player)[i] as GActorFight; if (_hero.ActorInfo.teamID != 0 && _player.ActorInfo.teamID == _hero.ActorInfo.teamID) { if (m_CheckPlayerList.Count >= _limitCount) { _player.ShowOrHideModel(false); } else { m_CheckPlayerList.Add(_player); _player.ShowOrHideModel(true); } } } _teamCount = m_CheckPlayerList.Count; m_CheckPlayerList.Clear(); for (int i = _curCount - 1; i >= 0; --i) { _player = GetTypeList(E_ActorClassType.Player)[i] as GActorFight; // 排除队友 if (_hero.ActorInfo.teamID != 0 && _player.ActorInfo.teamID == _hero.ActorInfo.teamID) { continue; } if (_hero.ActorInfo.familyID != 0 && _player.ActorInfo.familyID == _hero.ActorInfo.familyID) { if (m_CheckPlayerList.Count + _teamCount < _limitCount) { _player.ShowOrHideModel(true); m_CheckPlayerList.Add(_player); } else { _player.ShowOrHideModel(false); } } } _familyCount = m_CheckPlayerList.Count; m_CheckPlayerList.Clear(); //Debug.LogFormat("队友人数: {0}, 仙盟人数: {1}, 限制人数: {2}", _teamCount, _familyCount, _limitCount); _limitCount = _limitCount - _teamCount - _familyCount; //Debug.LogFormat("还需要判断的人数: {0}", _limitCount); for (int i = 0; i < _curCount; ++i) { _player = GetTypeList(E_ActorClassType.Player)[i] as GActorFight; if ((_hero.ActorInfo.familyID != 0 && _player.ActorInfo.familyID == _hero.ActorInfo.familyID) || (_hero.ActorInfo.teamID != 0 && _player.ActorInfo.teamID == _hero.ActorInfo.teamID) || atkOtherPlayerDict.ContainsKey(_player.ServerInstID) || otherPlayerAtkHeroDict.ContainsKey(_player.ServerInstID)) { continue; } m_CheckPlayerList.Add(_player); } //Debug.LogFormat("计算出的人数: {0}", m_CheckPlayerList.Count); if (m_CheckPlayerList.Count > 0) { m_CheckPlayerList.Sort((p1, p2) => { float _d1 = MathUtility.DistanceSqrtXZ(p1.Pos, _hero.Pos); float _d2 = MathUtility.DistanceSqrtXZ(p2.Pos, _hero.Pos); return _d1 < _d2 ? -1 : 1; }); for (int i = 0; i < m_CheckPlayerList.Count; ++i) { _player = m_CheckPlayerList[i] as GActorFight; if (i < _limitCount) { _player.ShowOrHideModel(true); } else { _player.ShowOrHideModel(false); } } } } public void UnInit() { ClearOffLinePlayer(); for (int i = m_AllList.Count - 1; i >= 0; --i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; // 玩家控制英雄不清理 if (m_AllList[i].ServerInstID == PlayerDatas.Instance.PlayerId) { continue; } m_Sid2Cid.Remove(m_AllList[i].ServerInstID); Release(m_AllList[i]); } // 对所有记录的资源进行销毁 for (int i = needDestroyPrefabList.Count - 1; i >= 0; --i) { if (i >= needDestroyPrefabList.Count) { continue; } if (needDestroyPrefabList[i] == null) { needDestroyPrefabList.RemoveAt(i); continue; } GameObjectPoolManager.Instance.Release(needDestroyPrefabList[i]); needDestroyPrefabList.RemoveAt(i); } m_ClientId.Clear(); m_SimulateServerID.Clear(); #if UNITY_EDITOR DebugUnInit(); #endif } public T RequestPlayer(uint serverInstID, E_ActorGroup group, GameNetPackBasic package) where T : GActor { byte _actorClassType = GetActorClassType(typeof(T)); GActor _actor = GetPoolActor(_actorClassType); if (_actor == null) { switch ((E_ActorClassType)_actorClassType) { case E_ActorClassType.Hero: _actor = new GA_Hero(); break; case E_ActorClassType.Player: _actor = new GA_Player(); break; case E_ActorClassType.PlayerXmzz: _actor = new GA_PlayerXMZZ(); break; case E_ActorClassType.PlayerZZ: _actor = new GA_NpcFightZZPlayer(); break; case E_ActorClassType.PlayerSgzcRobot: _actor = new GA_NpcFightSgzcZZ(); break; case E_ActorClassType.PVPClientPlayer: _actor = new GA_PVPClientPlayer(); break; case E_ActorClassType.ILClientPlayer: _actor = new GA_ILClientPlayer(); ArenaManager.iLClientPlayer = _actor as GA_ILClientPlayer; break; } } if (_actor != null) { if ((E_ActorClassType)_actorClassType == E_ActorClassType.Hero) { _actor.Init(serverInstID, 0, group, package); } else { _actor.Init(serverInstID, m_ClientId.Request(), group, package); } BuildManagerRelation(_actor, _actorClassType); if (OnGActorRequest != null) { OnGActorRequest(serverInstID); } } return _actor as T; } internal uint GetCIDBySID(uint serverInstID) { if (m_Sid2Cid.ContainsKey(serverInstID)) { return m_Sid2Cid[serverInstID]; } return 0; } public T RequestNpcNoFight(uint serverInstID, uint npcID, E_ActorGroup group, GameNetPackBasic package) where T : GActorNpcNoFight { byte _actorClassType = GetActorClassType(typeof(T)); GActorNpcNoFight _actor = GetPoolActor(_actorClassType) as GActorNpcNoFight; if (_actor == null) { switch ((E_ActorClassType)_actorClassType) { case E_ActorClassType.Guard: _actor = new GA_Guard(); break; case E_ActorClassType.NpcFunc: _actor = new GA_NpcFunc(); break; case E_ActorClassType.NpcCollect: _actor = new GA_NpcCollect(); break; case E_ActorClassType.NpcSummonFunc: _actor = new GA_NpcSummonFunc(); break; case E_ActorClassType.NpcTouchKilled: _actor = new GA_NpcTouchKilled(); break; } } if (_actor != null) { _actor.Init(serverInstID, m_ClientId.Request(), group, package); BuildManagerRelation(_actor, _actorClassType); } return _actor as T; } public T RequestNPCFight(uint serverInstID, uint npcID, E_ActorGroup group, GameNetPackBasic package) where T : GActorNpcFight { byte _actorClassType = GetActorClassType(typeof(T)); GActorNpcFight _actor = GetPoolActor(_actorClassType) as GActorNpcFight; if (_actor == null) { switch ((E_ActorClassType)_actorClassType) { case E_ActorClassType.Pet: _actor = new GA_Pet(); break; case E_ActorClassType.NpcFightNorm: _actor = new GA_NpcFightNorm(); break; case E_ActorClassType.NpcFightBoss: _actor = new GA_NpcFightBoss(); break; case E_ActorClassType.NpcClientFightBoss: _actor = new GA_NpcClientFightBoss(); break; case E_ActorClassType.NpcClientFightNorm: _actor = new GA_NpcClientFightBoss(); break; case E_ActorClassType.NpcFightVirtualPlayer: _actor = new GA_NpcFightVirtualPlayer(); break; case E_ActorClassType.NpcSummonFight: _actor = new GA_NpcSummonFight(); break; } } if (_actor != null) { _actor.Init(serverInstID, _actorClassType == (int)E_ActorClassType.Pet ? serverInstID : m_ClientId.Request(), group, package); BuildManagerRelation(_actor, _actorClassType); #if UNITY_EDITOR string _content = string.Format("GAMgr => 对角色 SID: {0}, CID: {1} 进行初始化", serverInstID, _actor.ClientInstID); RuntimeLogUtility.AddLog_Green(_content, serverInstID); #endif if (OnFightNpcRequest != null) { OnFightNpcRequest(npcID); } } return _actor as T; } public T ReqClntNoFightNpc(uint npcID, E_ActorGroup group) where T : GActorNpcNoFight { uint serverInstID = m_SimulateServerID.Request(); byte _actorClassType = GetActorClassType(typeof(T)); GActorNpcNoFight _actor = GetPoolActor(_actorClassType) as GActorNpcNoFight; if (_actor == null) { switch ((E_ActorClassType)_actorClassType) { case E_ActorClassType.NpcClientFunc: _actor = new GA_NpcClientFunc(); break; case E_ActorClassType.NpcClientCollect: _actor = new GA_NpcClientCollect(); break; } } if (_actor != null) { _actor.InitNpcConfig((int)npcID); _actor.Init(serverInstID, m_ClientId.Request(), group, null); BuildManagerRelation(_actor, _actorClassType); } return _actor as T; } public T ReqClntFightNpc(uint npcID, E_ActorGroup group) where T : GActorNpcFight { uint serverInstID = m_SimulateServerID.Request(); byte _actorClassType = GetActorClassType(typeof(T)); GActorNpcFight _actor = GetPoolActor(_actorClassType) as GActorNpcFight; if (_actor == null) { switch ((E_ActorClassType)_actorClassType) { case E_ActorClassType.NpcClientFightBoss: _actor = new GA_NpcClientFightBoss(); break; case E_ActorClassType.NpcClientFightNorm: _actor = new GA_NpcClientFightNorm(); break; } } if (_actor != null) { _actor.InitNpcConfig((int)npcID); _actor.Init(serverInstID, m_ClientId.Request(), group, null); BuildManagerRelation(_actor, _actorClassType); } return _actor as T; } public T ReqClntPlayer(GActorPlayerBase.PlayerInfo info, E_ActorGroup group) where T : GActorPlayerBase { uint serverInstID = m_SimulateServerID.Request(); byte _actorClassType = GetActorClassType(typeof(T)); GActorPlayerBase _actor = null; if ((E_ActorClassType)_actorClassType == E_ActorClassType.PVPClientPlayer) { _actor = GetPoolActor(_actorClassType) as GA_PVPClientPlayer; if (_actor == null) { _actor = new GA_PVPClientPlayer(); } if (_actor != null) { (_actor as GA_PVPClientPlayer).Init(serverInstID, m_ClientId.Request(), info, group); BuildManagerRelation(_actor, _actorClassType); } } else if ((E_ActorClassType)_actorClassType == E_ActorClassType.ILClientPlayer) { _actor = GetPoolActor(_actorClassType) as GA_ILClientPlayer; if (_actor == null) { _actor = new GA_ILClientPlayer(); ArenaManager.iLClientPlayer = _actor as GA_ILClientPlayer; } if (_actor != null) { (_actor as GA_ILClientPlayer).Init(serverInstID, m_ClientId.Request(), info, group); BuildManagerRelation(_actor, _actorClassType); } } else if ((E_ActorClassType)_actorClassType == E_ActorClassType.JiaPlayer) { _actor = GetPoolActor(_actorClassType) as GA_JiaPlayer; if (_actor == null) { _actor = new GA_JiaPlayer(); } if (_actor != null) { (_actor as GA_JiaPlayer).Init(serverInstID, m_ClientId.Request(), info, group); BuildManagerRelation(_actor, _actorClassType); } } else { _actor = GetPoolActor(_actorClassType) as GA_PlayerClient; if (_actor == null) { _actor = new GA_PlayerClient(); } if (_actor != null) { (_actor as GA_PlayerClient).Init(serverInstID, m_ClientId.Request(), info, group); BuildManagerRelation(_actor, _actorClassType); } } return _actor as T; } public void CreateBossTipReleaseHandler(int skillId) { BossSkillTip_JudgeSummon _handler = new BossSkillTip_JudgeSummon(skillId); m_BossSkillTipList.Add(_handler); } private GActor GetPoolActor(byte actorClassType) { GActor _actor = null; Stack _freeStack = null; if (m_Free.TryGetValue(actorClassType, out _freeStack)) { if (_freeStack.Count > 0) { _actor = _freeStack.Pop(); _actor.Root.SetParent(null); DontDestroyOnLoad(_actor.Root); } } return _actor; } public void ServerDieFail(uint serverInstID) { if (m_Sid2Cid.ContainsKey(serverInstID)) { m_Sid2Cid.Remove(serverInstID); } } /// /// 服务度死亡 /// 用于断开与客户端对象的关联 /// 以便新的服务端对象创建不会影响旧的客户端对象 /// /// 服务器对象ID public void ServerDie(uint serverInstID) { if (m_Sid2Cid.ContainsKey(serverInstID)) { //if (!serverDeadList.Contains(m_Sid2Cid[serverInstID])) //{ // serverDeadList.Add(m_Sid2Cid[serverInstID]); // serverDeadDict.Add(m_Sid2Cid[serverInstID], Time.realtimeSinceStartup); // Debug.LogFormat("死亡处理添加了: {0}", m_Sid2Cid[serverInstID]); //} m_Sid2Cid.Remove(serverInstID); if (OnGActorServerDie != null) { OnGActorServerDie(serverInstID); } #if UNITY_EDITOR string _content = string.Format("GAMgr => 对角色 SID: {0} 进行服务端死亡处理逻辑", serverInstID); RuntimeLogUtility.AddLog_Green(_content, serverInstID); #endif } } /// /// 释放 /// 释放的时机为真正需要从场景中移除 /// 一般为死亡结束,或者立即消失 /// * 此方法前, 应该已经解除了服务端ID与客户端的联系 /// /// public void Release(GActor actor) { #if UNITY_EDITOR string _content = string.Format("GAMgr => 对角色 SID: {0}, CID: {1} 进行了回收", actor.ServerInstID, actor.ClientInstID); if (actor is GActorNpcFight) { Debug.Log(_content); } RuntimeLogUtility.AddLog_Green(_content, actor.ServerInstID); #endif bool _needReSyncPlayerCount = false; if (PlayerDatas.Instance.hero != null && actor is GA_Player) { if (actor.ActorInfo.teamID == PlayerDatas.Instance.hero.ActorInfo.teamID || actor.ActorInfo.familyID == PlayerDatas.Instance.hero.ActorInfo.familyID) { _needReSyncPlayerCount = true; } } // 执行卸载 actor.UnInit(); // 对象回收 byte _actorClassType = GetActorClassType(actor.GetType()); Stack _stack = null; if (!m_Free.TryGetValue(_actorClassType, out _stack)) { _stack = new Stack(); m_Free.Add(_actorClassType, _stack); } if (m_Free[_actorClassType].Contains(actor)) { Debug.LogWarningFormat("执行角色回收, 对象已在回收池里了..."); } else { m_Free[_actorClassType].Push(actor); } actor.Pos = Constants.Special_Hide_Position; actor.Root.SetParent(transform); // 组列表移除 List _list = null; if (m_Group.TryGetValue((byte)actor.Group, out _list)) { if (_list.Contains(actor)) { _list.Remove(actor); } } // 类型列表移除 if (m_Type.TryGetValue(_actorClassType, out _list)) { if (_list.Contains(actor)) { _list.Remove(actor); } } // 全列表移除 if (m_AllList.Contains(actor)) { m_AllList.Remove(actor); } // id对象字典移除 if (m_Cid2GA.ContainsKey(actor.ClientInstID)) { m_Cid2GA.Remove(actor.ClientInstID); } var _npcfight = actor as GActorNpcFight; if (_npcfight != null) { if (OnFightNpcRelease != null) { OnFightNpcRelease((uint)_npcfight.NpcConfig.NPCID); } } if (_needReSyncPlayerCount) { OnPlayerSyncCountChange(); } } public void ReleaseAll() { for (int i = m_AllList.Count - 1; i >= 0; --i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; Release(m_AllList[i]); } serverDeadList.Clear(); #if UNITY_EDITOR DebugUnInit(); #endif } public GActor GetBySID(uint serverInstID) { if (m_Sid2Cid.ContainsKey(serverInstID)) { if (m_Cid2GA.ContainsKey(m_Sid2Cid[serverInstID])) { return m_Cid2GA[m_Sid2Cid[serverInstID]]; } } return null; } public GActor GetByCID(uint clientInstID) { if (m_Cid2GA.ContainsKey(clientInstID)) { return m_Cid2GA[clientInstID]; } return null; } public GActor GetCloserCollectNpc(Vector3 center) { List _list = GetTypeList(E_ActorClassType.NpcCollect); if (_list == null || _list.Count == 0) { return null; } _list.Sort((GActor a1, GActor a2) => { float _d1 = MathUtility.DistanceSqrtXZ(center, a1.Pos); float _d2 = MathUtility.DistanceSqrtXZ(center, a2.Pos); return _d1 < _d2 ? -1 : 1; }); return _list[0]; } public GActor GetCloserFightNpc(Vector3 center) { List _list = GetTypeList(E_ActorClassType.NpcFightNorm); if (_list == null || _list.Count == 0) { return null; } _list.Sort((GActor a1, GActor a2) => { float _d1 = MathUtility.DistanceSqrtXZ(center, a1.Pos); float _d2 = MathUtility.DistanceSqrtXZ(center, a2.Pos); return _d1 < _d2 ? -1 : 1; }); return _list[0]; } /// /// 获取离给定坐标最近的NPC对象 /// /// /// /// public GActor GetCloserNPC(Vector3 pos, int npcID = 0) { m_AllList.Sort((GActor a1, GActor a2) => { float _d1 = MathUtility.DistanceSqrtXZ(pos, a1.Pos); float _d2 = MathUtility.DistanceSqrtXZ(pos, a2.Pos); return _d1 < _d2 ? -1 : 1; }); NPCConfig _npcConfig = NPCConfig.Get(npcID); if (_npcConfig == null) { return null; } for (int i = 0; i < m_AllList.Count; ++i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) { continue; } if (m_AllList[i].ActorType != GameObjType.gotNPC) { continue; } if (m_AllList[i].ActorInfo == null) { continue; } if (m_AllList[i].ActorInfo.serverDie) { continue; } if (_npcConfig.NPCType == (int)E_NpcType.Fight) { GActorNpcFight _fight = m_AllList[i] as GActorNpcFight; if (_fight != null && _fight.ActorInfo != null && !_fight.ActorInfo.serverDie) { if (npcID == 0) { return _fight; } else if (_fight.NpcConfig != null && _fight.NpcConfig.NPCID == npcID) { return _fight; } } } else { GActorNpcNoFight _noFight = m_AllList[i] as GActorNpcNoFight; if (_noFight != null) { if (_noFight.NpcConfig != null && _noFight.NpcConfig.NPCID == npcID) { return _noFight; } } } } return null; } public List GetGroupList(E_ActorGroup group) { if (m_Group.ContainsKey((byte)group)) { return m_Group[(byte)group]; } return null; } public List GetTypeList(E_ActorClassType type) { List _list = null; if (m_Type.TryGetValue((byte)type, out _list)) { return _list; } return null; } public GActorFight GetGroupCloestTarget(Vector3 chkPos, E_ActorGroup group) { List _enemyList = GetGroupList(group); if (_enemyList != null && _enemyList.Count > 0) { _enemyList.Sort((GActor a1, GActor a2) => { float _d1 = MathUtility.DistanceSqrtXZ(a1.Pos, chkPos); float _d2 = MathUtility.DistanceSqrtXZ(a2.Pos, chkPos); if (_d1 < _d2) { return -1; } else if (_d1 > _d2) { return 1; } return 0; }); return _enemyList[0] as GActorFight; } return null; } public List GetAll() { return m_AllList; } public void DoUpdate() { for (int i = m_AllList.Count - 1; i >= 0; --i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; m_AllList[i].Update(); } UpdateOffLinePlayer(); } public void DoLateUpdate() { for (int i = m_AllList.Count - 1; i >= 0; --i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; m_AllList[i].LateUpdate(); } } public List _removeIdList = new List(); public void DoFixedUpdate() { for (int i = m_AllList.Count - 1; i >= 0; --i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; m_AllList[i].FixedUpdate(); } for (int i = m_BossSkillTipList.Count - 1; i >= 0; --i) { if (m_BossSkillTipList[i] == null) { m_BossSkillTipList.RemoveAt(i); continue; } m_BossSkillTipList[i].Update(); if (m_BossSkillTipList[i].IsFinished) { m_BossSkillTipList.RemoveAt(i); } } _removeIdList.Clear(); foreach (uint _id in otherPlayerAtkHeroDict.Keys) { if (Time.realtimeSinceStartup - otherPlayerAtkHeroDict[_id] > 2f) { _removeIdList.Add(_id); } } for (int i = 0; i < _removeIdList.Count; ++i) { if (otherPlayerAtkHeroDict.ContainsKey(_removeIdList[i])) { GA_Hero.CallOnStopBeAttacked(_removeIdList[i]); otherPlayerAtkHeroDict.Remove(_removeIdList[i]); } } _removeIdList.Clear(); foreach (uint _id in atkOtherPlayerDict.Keys) { if (Time.realtimeSinceStartup - atkOtherPlayerDict[_id] > 2f) { _removeIdList.Add(_id); } } for (int i = 0; i < _removeIdList.Count; ++i) { if (atkOtherPlayerDict.ContainsKey(_removeIdList[i])) { atkOtherPlayerDict.Remove(_removeIdList[i]); } } //if (serverDeadList.Count > 0) //{ // GActor _deadActor = null; // for (int i = serverDeadList.Count - 1; i >= 0; --i) // { // if (!serverDeadDict.ContainsKey(serverDeadList[i])) // { // Debug.LogFormat("死亡字典里没有: {0}", serverDeadList[i]); // serverDeadList.RemoveAt(i); // continue; // } // if (Time.realtimeSinceStartup - serverDeadDict[serverDeadList[i]] > 1) // { // _deadActor = GetByCID(serverDeadList[i]); // if (_deadActor != null) // { // _deadActor.Die(); // } // Debug.LogFormat("死亡处理了: {0}", serverDeadList[i]); // serverDeadDict.Remove(serverDeadList[i]); // serverDeadList.RemoveAt(i); // } // } //} } public void DoDelayDie(GActorFight target) { StartCoroutine(DelayDie(target)); } public IEnumerator DelayDie(GActorFight target) { float _delayTime = Time.realtimeSinceStartup; while (Time.realtimeSinceStartup - _delayTime < 3) { yield return null; } if (!target.ActorInfo.serverDie) { //Debug.LogFormat("目标为: {0} 未死亡", target.ClientInstID); yield break; } // Debug.Log("将要判断的目标为: " + target.ClientInstID); foreach (var _cid in m_Sid2Cid.Values) { if (_cid == target.ClientInstID) { // Debug.LogFormat("目标为: {0} 存在于列表中", target.ClientInstID); yield break; } } byte _actorClassType = GetActorClassType(target.GetType()); Stack _stack = null; if (m_Free.TryGetValue(_actorClassType, out _stack)) { if (!_stack.Contains(target)) { Release(target); // Debug.LogFormat("不在空闲, 移除: {0}", target.ClientInstID); } } else { Release(target); // Debug.LogFormat("直接移除: {0}", target.ClientInstID); } } private void BuildManagerRelation(GActor _actor, byte _actorClassType) { // 加入组 List _list = null; if (!m_Group.TryGetValue((byte)_actor.Group, out _list)) { _list = new List(); m_Group.Add((byte)_actor.Group, _list); } _list.Add(_actor); // 加入类型 if (!m_Type.TryGetValue(_actorClassType, out _list)) { _list = new List(); m_Type.Add(_actorClassType, _list); } _list.Add(_actor); // 所有 m_AllList.Add(_actor); #if UNITY_EDITOR if (m_Sid2Cid.ContainsKey(_actor.ServerInstID)) { Debug.LogErrorFormat("创建服务端对象: {0} 的时候, 发现客户端已存在此ID.", _actor.ServerInstID); } if (m_Cid2GA.ContainsKey(_actor.ClientInstID)) { Debug.LogErrorFormat("创建客户端对象: {0} 的时候, 发现客户端已存在此ID.", _actor.ClientInstID); } #endif // id对应关系确定 m_Sid2Cid[_actor.ServerInstID] = _actor.ClientInstID; m_Cid2GA[_actor.ClientInstID] = _actor; } private byte GetActorClassType(Type _type) { if (_type == typeof(GA_Hero)) { return (byte)E_ActorClassType.Hero; } else if (_type == typeof(GA_NpcFightNorm)) { return (byte)E_ActorClassType.NpcFightNorm; } else if (_type == typeof(GA_NpcFightBoss)) { return (byte)E_ActorClassType.NpcFightBoss; } else if (_type == typeof(GA_Guard)) { return (byte)E_ActorClassType.Guard; } else if (_type == typeof(GA_Player)) { return (byte)E_ActorClassType.Player; } else if (_type == typeof(GA_NpcSummonFunc)) { return (byte)E_ActorClassType.NpcSummonFunc; } else if (_type == typeof(GA_NpcFunc)) { return (byte)E_ActorClassType.NpcFunc; } else if (_type == typeof(GA_Pet)) { return (byte)E_ActorClassType.Pet; } else if (_type == typeof(GA_NpcCollect)) { return (byte)E_ActorClassType.NpcCollect; } else if (_type == typeof(GA_NpcTouchKilled)) { return (byte)E_ActorClassType.NpcTouchKilled; } else if (_type == typeof(GA_NpcClientFightNorm)) { return (byte)E_ActorClassType.NpcClientFightNorm; } else if (_type == typeof(GA_NpcClientFightBoss)) { return (byte)E_ActorClassType.NpcClientFightBoss; } else if (_type == typeof(GA_NpcClientFunc)) { return (byte)E_ActorClassType.NpcClientFunc; } else if (_type == typeof(GA_NpcFightVirtualPlayer)) { return (byte)E_ActorClassType.NpcFightVirtualPlayer; } else if (_type == typeof(GA_NpcSummonFight)) { return (byte)E_ActorClassType.NpcSummonFight; } else if (_type == typeof(GA_PlayerXMZZ)) { return (byte)E_ActorClassType.PlayerXmzz; } else if (_type == typeof(GA_PlayerClient)) { return (byte)E_ActorClassType.ClientPlayer; } else if (_type == typeof(GA_NpcFightZZPlayer)) { return (byte)E_ActorClassType.PlayerZZ; } else if (_type == typeof(GA_NpcFightSgzcZZ)) { return (byte)E_ActorClassType.PlayerSgzcRobot; } else if (_type == typeof(GA_PVPClientPlayer)) { return (byte)E_ActorClassType.PVPClientPlayer; } else if (_type == typeof(GA_ILClientPlayer)) { return (byte)E_ActorClassType.ILClientPlayer; } else if (_type == typeof(GA_NpcClientCollect)) { return (byte)E_ActorClassType.NpcClientCollect; } else if (_type == typeof(GA_JiaPlayer)) { return (byte)E_ActorClassType.JiaPlayer; } return (byte)E_ActorClassType.UnDefine; } /// /// 默认由主角发起的寻找目标逻辑 /// /// 检测点 /// 检测半径 /// 检测角度 /// 是否锁定NPCID /// public GActorFight FindAtkTarget(Vector3 chkPos, float r, float angle = 360, int lockNpcID = -1) { GA_Hero _hero = PlayerDatas.Instance.hero; // 如果在安全区则直接返回空 if (MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.RebornSafe) || MapArea.IsInMapArea(_hero.CurMapArea, MapArea.E_Type.Safe)) { return null; } GActorFight _actor = null; // 判断模式, 是否优先搜索其他玩家目标对象 // 全体模式, 强制模式 需要对玩家进行预先判断 if ((E_AttackMode)PlayerDatas.Instance.baseData.AttackMode == E_AttackMode.All || (E_AttackMode)PlayerDatas.Instance.baseData.AttackMode == E_AttackMode.Family || PlayerDatas.Instance.maliciousAtkPlayer.Count > 0 || ClientCrossServerOneVsOne.isClientCrossServerOneVsOne || ArenaManager.isArenaClient) { List _list = GetGroupList(E_ActorGroup.Player); DoFindTarget(_list, chkPos, r, ref _actor, angle, lockNpcID); } // 没有找到可攻击目标, 开始找BossNpc if (_actor == null) { List _list = GetTypeList(E_ActorClassType.NpcFightBoss); DoFindTarget(_list, chkPos, r, ref _actor, angle, lockNpcID); } // 没有找到可攻击目标, 开始找客户端BossNpc if (_actor == null) { List _list = GetTypeList(E_ActorClassType.NpcClientFightBoss); DoFindTarget(_list, chkPos, r, ref _actor, angle, lockNpcID); } // 没有找到可攻击目标, 开始找Npc if (_actor == null) { List _list = GetTypeList(E_ActorClassType.NpcFightNorm); DoFindTarget(_list, chkPos, r, ref _actor, angle, lockNpcID); } // 没有找到可攻击目标, 开始找客户端Npc if (_actor == null) { List _list = GetTypeList(E_ActorClassType.NpcClientFightNorm); DoFindTarget(_list, chkPos, r, ref _actor, angle, lockNpcID); } return _actor; } private void DoFindTarget(List list, Vector3 chkPos, float r, ref GActorFight target, float angle = 360, int lockNpcID = -1) { GA_Hero _hero = PlayerDatas.Instance.hero; if (list == null || list.Count == 0) { target = null; return; } // 先将列表所有对象进行从近到远排序 list.Sort((GActor a1, GActor a2) => { float _chk1 = MathUtility.DistanceSqrtXZ(chkPos, a1.Pos); float _chk2 = MathUtility.DistanceSqrtXZ(chkPos, a2.Pos); return _chk1 < _chk2 ? -1 : 1; }); GActorFight _other; IOtherSelectable _selectable; Vector3 _targetDir; float _chkAngle; float _chkDistSqrt; int _index = -1; for (int i = 0; i < list.Count; ++i) { if (list[i].ActorInfo.serverDie) { continue; } _other = list[i] as GActorFight; if (_other == null || !_other.CanAtked()) { continue; } _selectable = list[i] as IOtherSelectable; if (_selectable != null && !_selectable.CanBeSelected()) { continue; } if (lockNpcID > 0) { GActorNpcFight _npc = list[i] as GActorNpcFight; if (_npc == null || _npc.NpcConfig.NPCID != lockNpcID) { continue; } } // 判断距离 _chkDistSqrt = MathUtility.DistanceSqrtXZ(_other.Pos, chkPos); if (_chkDistSqrt > Mathf.Pow(r, 2)) { continue; } // 判断方向 _targetDir = MathUtility.ForwardXZ(list[i].Pos, chkPos);//(list[i].Pos - chkPos).normalized; _chkAngle = Vector3.Angle(_targetDir, _hero.destForward); if (_chkAngle <= angle * .5f) { _index = i; break; } } if (_index >= 0) { target = list[_index] as GActorFight; } else { target = null; } } #if UNITY_EDITOR /// /// 检测是否没有卸载干净的情况 /// private void DebugUnInit() { if (m_AllList.Count > 0) { Debug.LogWarningFormat("卸载后发现 m_AllList 还有 {0} 个对象", m_AllList.Count); for (int i = 0; i < m_AllList.Count; ++i) { if (i >= m_AllList.Count) { //其他地方做了协程删除,可能导致此处错误 continue; } if (m_AllList[i] == null) continue; if (m_AllList[i].Root != null) { Debug.LogWarningFormat(" |-- " + m_AllList[i].Root.name); } } } if (m_Cid2GA.Count > 0) { Debug.LogWarningFormat("卸载后发现 m_Cid2GA 还有 {0} 个对象", m_Cid2GA.Count); } foreach (var _group in m_Group.Keys) { if (m_Group[_group] != null && m_Group[_group].Count > 0) { Debug.LogWarningFormat("卸载后发现组: {0} 还有 {1} 个对象", (E_ActorGroup)_group, m_Group[_group].Count); } } foreach (var _type in m_Type.Keys) { if (m_Type[_type] != null && m_Type[_type].Count > 0) { Debug.LogWarningFormat("卸载后发现类别: {0} 还有 {1} 个对象", (E_ActorClassType)_type, m_Type[_type].Count); } } } #endif }