725 lines
25 KiB
C#
725 lines
25 KiB
C#
|
/********************************************************************************
|
|||
|
* 文件名: ObjManager.cs
|
|||
|
* 全路径: \Script\Obj\ObjManager.cs
|
|||
|
* 创建人: 李嘉
|
|||
|
* 创建时间:2013-10-25
|
|||
|
*
|
|||
|
* 功能说明:游戏逻辑Obj管理器,对游戏中所有Obj提供创建,移除和管理
|
|||
|
* 修改记录:
|
|||
|
* //2013-11-18 修改list结构为Dictionary结构,
|
|||
|
*********************************************************************************/
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using Games.GlobeDefine;
|
|||
|
using Games.LogicObj;
|
|||
|
using GCGame.Table;
|
|||
|
using Module.Log;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
public class OtherPlayerVisibility
|
|||
|
{
|
|||
|
public readonly Obj_OtherPlayer character;
|
|||
|
public readonly Collider collider;
|
|||
|
public bool isHide;
|
|||
|
|
|||
|
public OtherPlayerVisibility(Obj_OtherPlayer character, bool isHide)
|
|||
|
{
|
|||
|
this.character = character;
|
|||
|
collider = character.GetComponent<Collider>();
|
|||
|
this.isHide = isHide;
|
|||
|
}
|
|||
|
|
|||
|
public void SetHide(bool hide)
|
|||
|
{
|
|||
|
if (isHide != hide)
|
|||
|
{
|
|||
|
isHide = hide;
|
|||
|
if (collider != null)
|
|||
|
collider.enabled = !isHide;
|
|||
|
character.SetHideByMask(GetHideMask(isHide));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static int GetHideMask(bool hide)
|
|||
|
{
|
|||
|
return hide ? int.MaxValue : PlayerPreferenceData.OtherPlayerHideMask;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 死亡Npc延迟回收装置
|
|||
|
/// </summary>
|
|||
|
// Npc死亡后,如果收到死亡删除协议,客户端将延迟回收Npc
|
|||
|
public class DeadNpcObjHolder
|
|||
|
{
|
|||
|
private readonly List<DeadNpcData> _npcData = new List<DeadNpcData>();
|
|||
|
|
|||
|
public DeadNpcObjHolder()
|
|||
|
{
|
|||
|
GameManager.AddLateUpdate(OnLateUpdate, GameManager.deadNpcUpdateOrder);
|
|||
|
}
|
|||
|
|
|||
|
public void Destroy()
|
|||
|
{
|
|||
|
GameManager.RemoveLateUpdate(OnLateUpdate, GameManager.deadNpcUpdateOrder);
|
|||
|
}
|
|||
|
|
|||
|
public bool TryAddObj(Obj obj)
|
|||
|
{
|
|||
|
var objNpc = obj as Obj_NPC;
|
|||
|
if (objNpc != null &&
|
|||
|
objNpc.IsDie() &&
|
|||
|
objNpc.ModelNode.model != null &&
|
|||
|
objNpc.ObjEffectLogic != null &&
|
|||
|
objNpc.BaseAttr != null)
|
|||
|
{
|
|||
|
var roleBaseAttr = TableManager.GetRoleBaseAttrByID(objNpc.BaseAttr.RoleBaseID, 0);
|
|||
|
if (roleBaseAttr != null && roleBaseAttr.CharModelID > GlobeVar.INVALID_ID &&
|
|||
|
(roleBaseAttr.RampType == 2 || roleBaseAttr.RampType == 3))
|
|||
|
{
|
|||
|
var charModel = TableManager.GetCharModelByID(roleBaseAttr.CharModelID, 0);
|
|||
|
if (charModel != null && charModel.DieShadetime > 0f)
|
|||
|
{
|
|||
|
var effectTable = TableManager.GetEffectByID(GlobeVar.deathEffectId, 0);
|
|||
|
if (effectTable != null)
|
|||
|
{
|
|||
|
objNpc.ObjEffectLogic.PlaySpecialEffect(effectTable, charModel.DieShadetime);
|
|||
|
_npcData.Add(new DeadNpcData(objNpc, Time.realtimeSinceStartup + charModel.DieShadetime));
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public void Clear()
|
|||
|
{
|
|||
|
for (var i = 0; i < _npcData.Count; i++)
|
|||
|
if (_npcData[i].objNpc != null)
|
|||
|
_npcData[i].objNpc.DestroyObj();
|
|||
|
_npcData.Clear();
|
|||
|
}
|
|||
|
|
|||
|
private void OnLateUpdate()
|
|||
|
{
|
|||
|
for (var i = _npcData.Count - 1; i >= 0; i--)
|
|||
|
if (_npcData[i].removeTime < Time.realtimeSinceStartup)
|
|||
|
{
|
|||
|
var npcData = _npcData[i];
|
|||
|
_npcData.RemoveAt(i);
|
|||
|
if (npcData.objNpc != null)
|
|||
|
npcData.objNpc.DestroyObj();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private struct DeadNpcData
|
|||
|
{
|
|||
|
public readonly Obj_NPC objNpc;
|
|||
|
public readonly float removeTime;
|
|||
|
|
|||
|
public DeadNpcData(Obj_NPC objNpc, float removeTime)
|
|||
|
{
|
|||
|
this.objNpc = objNpc;
|
|||
|
this.removeTime = removeTime;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class ObjManager : Singleton<ObjManager>
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 在角色创建前,收到的特效数据将会统一保存在这里
|
|||
|
/// </summary>
|
|||
|
private readonly List<ObjEffectCache> _effectCacheList = new List<ObjEffectCache>();
|
|||
|
|
|||
|
// OtherPlayer隐藏逻辑
|
|||
|
// 创建时,如果当前服务器创建角色小于限制,记录数据并创建Obj;否则只记录数据不创建。
|
|||
|
// 删除时,删除数据,如果角色有Obj,则为最早无Obj数据创建Obj。
|
|||
|
// 暂时没有限制数值改变时,处理主动删除和主动创建
|
|||
|
private readonly List<OtherPlayerVisibility> _otherList = new List<OtherPlayerVisibility>();
|
|||
|
|
|||
|
// 当前客户端带ServerId的Obj池,使用Obj(场景中)名字(唯一)索引,对应Obj的数据
|
|||
|
//动态的,注意使用上限
|
|||
|
public readonly Dictionary<int, Obj> ObjPools = new Dictionary<int, Obj>();
|
|||
|
|
|||
|
// 采集物等无ServerId物体的保存位置
|
|||
|
public readonly Dictionary<string, Obj> otherObjPools = new Dictionary<string, Obj>();
|
|||
|
|
|||
|
// 死亡Npc的延迟回收器
|
|||
|
public readonly DeadNpcObjHolder deadNpcObjHolder = new DeadNpcObjHolder();
|
|||
|
|
|||
|
//怪物归属缓存
|
|||
|
public List<int> m_Belongs = new List<int>();
|
|||
|
|
|||
|
//当前客户端主角色
|
|||
|
public Obj_MainPlayer MainPlayer { get; private set; }
|
|||
|
|
|||
|
public void AddPoolObj(Obj obj)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Obj contain;
|
|||
|
if (ObjPools.TryGetValue(obj.ServerID, out contain))
|
|||
|
{
|
|||
|
// 试图第二次创建一个物体,直接忽略
|
|||
|
if (contain != obj)
|
|||
|
{
|
|||
|
// 重复创建ServerId相同的物体,报错,然后按之前逻辑摧毁物体
|
|||
|
LogModule.ErrorLog(string.Format("试图创建ServerId重复的物体{0}", obj.ServerID));
|
|||
|
if (contain != null)
|
|||
|
contain.DestroyObj();
|
|||
|
ObjPools[obj.ServerID] = obj;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ObjPools.Add(obj.ServerID, obj);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogModule.ErrorLog(string.Format("ObjManager AddObj {0} Error: ", obj.ServerID) + ex);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public ObjManager()
|
|||
|
{
|
|||
|
PlayerPreferenceData.ShowOtherPlayerCount.onSettingUpdate += RefreshOtherPlayerCount;
|
|||
|
}
|
|||
|
|
|||
|
public void RemoveMainPlayer()
|
|||
|
{
|
|||
|
MainPlayer = null;
|
|||
|
}
|
|||
|
|
|||
|
public bool RemovePoolObj(int serverId, bool isDead)
|
|||
|
{
|
|||
|
var result = false;
|
|||
|
// 注:存在其他玩家Obj未建立,但是数据存在的情况
|
|||
|
RemoveHidePlayerByServerId(serverId);
|
|||
|
GetEffectCache(serverId, ListGetMode.remove);
|
|||
|
Obj obj;
|
|||
|
if (ObjPools.TryGetValue(serverId, out obj))
|
|||
|
{
|
|||
|
ObjPools.Remove(serverId);
|
|||
|
if (!deadNpcObjHolder.TryAddObj(obj))
|
|||
|
DestroyObj(obj);
|
|||
|
result = true;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
// 已经不再维护这个接口!
|
|||
|
//public bool RemovePoolObj(Obj removeObj)
|
|||
|
//{
|
|||
|
// var result = false;
|
|||
|
// // 注:存在其他玩家Obj未建立,但是数据存在的情况
|
|||
|
// RemoveHidePlayerByServerId(removeObj.ServerID);
|
|||
|
// GetEffectCache(removeObj.ServerID, ListGetMode.remove);
|
|||
|
// Obj obj;
|
|||
|
// if (ObjPools.TryGetValue(removeObj.ServerID, out obj))
|
|||
|
// {
|
|||
|
// if (removeObj != obj)
|
|||
|
// {
|
|||
|
// LogModule.ErrorLog(string.Format("试图移除ServerId为{0}的物体,但是实际ObjManager中存的是另一个物体!", removeObj.ServerID));
|
|||
|
// DestroyObj(obj);
|
|||
|
// }
|
|||
|
// ObjPools.Remove(removeObj.ServerID);
|
|||
|
// DestroyObj(removeObj);
|
|||
|
// result = true;
|
|||
|
// }
|
|||
|
// return result;
|
|||
|
//}
|
|||
|
|
|||
|
public ObjEffectCache GetEffectCache(int serverId, ListGetMode mode)
|
|||
|
{
|
|||
|
ObjEffectCache result = null;
|
|||
|
for (var i = 0; i < _effectCacheList.Count; i++)
|
|||
|
if (_effectCacheList[i].serverId == serverId)
|
|||
|
{
|
|||
|
result = _effectCacheList[i];
|
|||
|
if (mode == ListGetMode.remove)
|
|||
|
_effectCacheList.RemoveAt(i);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (mode == ListGetMode.create && result == null)
|
|||
|
{
|
|||
|
result = new ObjEffectCache(serverId);
|
|||
|
_effectCacheList.Add(result);
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
private void DestroyObj(Obj obj)
|
|||
|
{
|
|||
|
if (obj != null)
|
|||
|
obj.DestroyObj();
|
|||
|
}
|
|||
|
|
|||
|
private void RemoveHidePlayerByServerId(int serverId)
|
|||
|
{
|
|||
|
// 注:存在其他玩家Obj未建立,但是数据存在的情况
|
|||
|
// 删除一个其他玩家后,重新监视是否拥有足够的其他玩家。注:其他玩家排序正常应该是严格队列,前面部分都有Obj,后面部分都没有Obj
|
|||
|
var playerIndex = _otherList.FindIndex(a => a.character.ServerID == serverId);
|
|||
|
if (playerIndex >= 0)
|
|||
|
{
|
|||
|
var otherPlayer = _otherList[playerIndex];
|
|||
|
_otherList.RemoveAt(playerIndex);
|
|||
|
if (!otherPlayer.isHide && !IsOtherFull())
|
|||
|
{
|
|||
|
if (MainPlayer != null)
|
|||
|
{
|
|||
|
OtherPlayerVisibility visibility = null;
|
|||
|
var minDistSqr = float.PositiveInfinity;
|
|||
|
for (var i = 0; i < _otherList.Count; i++)
|
|||
|
if (_otherList[i].isHide)
|
|||
|
{
|
|||
|
var distSqr = (_otherList[i].character.Position - MainPlayer.Position).sqrMagnitude;
|
|||
|
if (distSqr < minDistSqr)
|
|||
|
{
|
|||
|
visibility = _otherList[i];
|
|||
|
minDistSqr = distSqr;
|
|||
|
}
|
|||
|
}
|
|||
|
if (visibility != null)
|
|||
|
visibility.SetHide(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void CleanSceneObj(bool isCleanMainPlayer = false)
|
|||
|
{
|
|||
|
foreach (var otherObj in otherObjPools.Values)
|
|||
|
if (otherObj != null)
|
|||
|
otherObj.DestroyObj();
|
|||
|
otherObjPools.Clear();
|
|||
|
if (isCleanMainPlayer)
|
|||
|
MainPlayer = null;
|
|||
|
foreach (var obj in ObjPools.Values)
|
|||
|
// 不删除主角时,不摧毁主角的Obj,清空字典后再将主角Obj添加回去
|
|||
|
if (MainPlayer == null || obj != MainPlayer)
|
|||
|
DestroyObj(obj);
|
|||
|
ObjPools.Clear();
|
|||
|
deadNpcObjHolder.Clear();
|
|||
|
if (!isCleanMainPlayer && MainPlayer != null)
|
|||
|
AddPoolObj(MainPlayer);
|
|||
|
_otherList.Clear();
|
|||
|
_effectCacheList.Clear();
|
|||
|
}
|
|||
|
|
|||
|
public bool IsOtherFull()
|
|||
|
{
|
|||
|
var count = 0;
|
|||
|
for (var i = 0; i < _otherList.Count; i++)
|
|||
|
if (!_otherList[i].isHide)
|
|||
|
count++;
|
|||
|
return count >= PlayerPreferenceData.ShowOtherPlayerCount;
|
|||
|
}
|
|||
|
|
|||
|
//如果先创建NPC后创建主角的话,NPC名字颜色等会表现异常,服务器大爷说他们是先发的创建的主角的协议的,没办法客户端这边先处理一下吧
|
|||
|
public void OnCreateMainPlayer()
|
|||
|
{
|
|||
|
var valus = new List<Obj>(ObjPools.Values);
|
|||
|
for (var i = 0; i < valus.Count; i++)
|
|||
|
{
|
|||
|
var Character = valus[i] as Obj_Character;
|
|||
|
if (Character != null)
|
|||
|
Character.OptForceChange();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void SetMainPlayer(ObjParent player)
|
|||
|
{
|
|||
|
var mainPlayer = player as Obj_MainPlayer;
|
|||
|
if (mainPlayer != null)
|
|||
|
MainPlayer = mainPlayer;
|
|||
|
}
|
|||
|
|
|||
|
public ObjParent NewCharacterObj(GameDefine_Globe.OBJ_TYPE type, ObjParent_Init_Data initData)
|
|||
|
{
|
|||
|
ObjParent newObj = null;
|
|||
|
// 注:非服务器记录的Obj在读盘期间应该正常响应
|
|||
|
if (NeedCreate(initData as Obj_Init_Data))
|
|||
|
switch (type)
|
|||
|
{
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER:
|
|||
|
{
|
|||
|
if (MainPlayer == null)
|
|||
|
{
|
|||
|
MainPlayer = ObjParent.Create<Obj_MainPlayer>(initData, "Prefab/Model/PlayerRoot");
|
|||
|
newObj = MainPlayer;
|
|||
|
if (MainPlayer != null)
|
|||
|
{
|
|||
|
//Object.DontDestroyOnLoad(MainPlayer.gameObject);
|
|||
|
//m_bBeginAsycCreateMainPlayer = true;
|
|||
|
AddPoolObj(MainPlayer);
|
|||
|
OnCreateMainPlayer();
|
|||
|
ApplyCachedEffect(MainPlayer, GlobeVar.INVALID_ID);
|
|||
|
ApplyCachedEffect(MainPlayer);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MainPlayer.Init(initData);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_NPC:
|
|||
|
{
|
|||
|
if (initData is Obj_Init_Data)
|
|||
|
newObj = CreateCharacter<Obj_NPC>(initData, "Prefab/Model/NPCRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_FELLOW:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_Fellow>(initData, "Prefab/Model/FellowRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER:
|
|||
|
{
|
|||
|
var otherPlayerData = initData as Obj_Player_Init_Data;
|
|||
|
if (otherPlayerData != null)
|
|||
|
{
|
|||
|
var isHide = IsOtherFull();
|
|||
|
otherPlayerData.m_hideMask = OtherPlayerVisibility.GetHideMask(isHide);
|
|||
|
var otherPlayer = CreateOtherPlayer(otherPlayerData);
|
|||
|
var visibilityData = new OtherPlayerVisibility(otherPlayer, isHide);
|
|||
|
_otherList.Add(visibilityData);
|
|||
|
newObj = otherPlayer;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_ZOMBIE_PLAYER:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_ZombieUser>(initData, "Prefab/Model/OtherPlayerRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_DROP_ITEM:
|
|||
|
{
|
|||
|
newObj = ObjParent.Create<Obj_DropItem>(initData, "Prefab/Model/DropItemInfo");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_GHARRY:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_GuildGharry>(initData, "Prefab/Model/FellowRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_WEDDINGCAR:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_WeddingCar>(initData, "Prefab/Model/NPCRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_CHILD:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_Child>(initData, "Prefab/Model/NPCRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_SNARE:
|
|||
|
{
|
|||
|
newObj = ObjParent.Create<Obj_Snare>(initData, "Prefab/Model/SnareRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_COLLECTITEM:
|
|||
|
{
|
|||
|
newObj = ObjParent.Create<Obj_CollectItem>(initData, "Prefab/Model/CollectItemRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_TELEPORTPOINT:
|
|||
|
{
|
|||
|
newObj = ObjParent.Create<Obj_TeleportPoint>(initData, "Prefab/Model/Teleport");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_JUMPPOINT:
|
|||
|
{
|
|||
|
newObj = ObjParent.Create<Obj_JumpPoint>(initData, "Prefab/Model/Jump");
|
|||
|
}
|
|||
|
break;
|
|||
|
case GameDefine_Globe.OBJ_TYPE.OBJ_CLIENTNPC:
|
|||
|
{
|
|||
|
newObj = CreateCharacter<Obj_ClientNPC>(initData, "Prefab/Model/NPCRoot");
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return newObj;
|
|||
|
}
|
|||
|
|
|||
|
//根据ServerID来查找Obj
|
|||
|
public Obj FindObjInScene(int nServerID)
|
|||
|
{
|
|||
|
Obj result;
|
|||
|
ObjPools.TryGetValue(nServerID, out result);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
//根据ServerID来查找Obj_Character
|
|||
|
public Obj_Character FindObjCharacterInScene(int nServerID)
|
|||
|
{
|
|||
|
return FindObjInScene(nServerID) as Obj_Character;
|
|||
|
}
|
|||
|
|
|||
|
public Obj_OtherPlayer FindOtherPlayerByGuid(ulong guid)
|
|||
|
{
|
|||
|
if (MainPlayer != null && MainPlayer.GUID == guid)
|
|||
|
return MainPlayer;
|
|||
|
var visibility = _otherList.Find(a => a.character.GUID == guid);
|
|||
|
return visibility == null ? null : visibility.character;
|
|||
|
}
|
|||
|
|
|||
|
//根据Obj_Character的BaseAttr中的RoleID来查找NPC
|
|||
|
//遍历,不推荐反复使用
|
|||
|
public Obj_Character FindObjCharacterInSceneByRoleID(int roleID, bool bIsAlive = true,bool isNearest = false)
|
|||
|
{
|
|||
|
Obj_Character objTarget = null;
|
|||
|
float distance = -1;
|
|||
|
foreach (var obj in ObjPools.Values)
|
|||
|
{
|
|||
|
var objChar = obj as Obj_NPC;
|
|||
|
if (objChar && objChar.BaseAttr != null && objChar.BaseAttr.RoleBaseID == roleID)
|
|||
|
{
|
|||
|
//是否要寻找非死亡目标
|
|||
|
if (bIsAlive && objChar.IsDie())
|
|||
|
continue;
|
|||
|
if(isNearest==false)
|
|||
|
return objChar;
|
|||
|
else
|
|||
|
{
|
|||
|
float dis = Vector3.Distance(Singleton<ObjManager>.Instance.MainPlayer .Position, objChar.Position);
|
|||
|
if (distance == -1 || dis < distance)
|
|||
|
{
|
|||
|
distance = dis;
|
|||
|
objTarget = objChar;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return objTarget;
|
|||
|
}
|
|||
|
|
|||
|
//根据Obj_Character的BaseAttr中的名字来查找NPC
|
|||
|
//遍历,不推荐反复使用
|
|||
|
public Obj_Character FindObjCharacterInSceneByName(string szBaseAttrName, bool bIsAlive = true)
|
|||
|
{
|
|||
|
Obj_Character objTarget = null;
|
|||
|
var minDistanceSqr = 8f * 8f;
|
|||
|
foreach (var obj in ObjPools.Values)
|
|||
|
{
|
|||
|
var objChar = obj as Obj_NPC;
|
|||
|
if (objChar == null)
|
|||
|
continue;
|
|||
|
string roleName = objChar.BaseAttr.RoleName;
|
|||
|
if (objChar.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_NPC && objChar.BaseAttr.RoleData != null && string.IsNullOrEmpty(objChar.BaseAttr.RoleData.Name) == false)
|
|||
|
roleName = objChar.BaseAttr.RoleData.Name;
|
|||
|
|
|||
|
if (objChar && objChar.BaseAttr != null && string.Equals(roleName, szBaseAttrName,
|
|||
|
StringComparison.InvariantCulture))
|
|||
|
{
|
|||
|
//是否要寻找非死亡目标
|
|||
|
if (bIsAlive && objChar.IsDie())
|
|||
|
continue;
|
|||
|
var nType = Reputation.GetObjReputionType(objChar);
|
|||
|
if (nType == CharacterDefine.REPUTATION_TYPE.REPUTATION_INVALID
|
|||
|
|| nType == CharacterDefine.REPUTATION_TYPE.REPUTATION_FRIEND)
|
|||
|
{
|
|||
|
objTarget = objChar;
|
|||
|
break;
|
|||
|
}
|
|||
|
if (MainPlayer != null)
|
|||
|
{
|
|||
|
var distanceSqr = (MainPlayer.Position - objChar.Position).sqrMagnitude;
|
|||
|
if (distanceSqr < minDistanceSqr)
|
|||
|
{
|
|||
|
minDistanceSqr = distanceSqr;
|
|||
|
objTarget = objChar;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return objTarget;
|
|||
|
}
|
|||
|
|
|||
|
//查找某个玩家
|
|||
|
public Obj_OtherPlayer FindOtherPlayerInScene(ulong guid)
|
|||
|
{
|
|||
|
return FindOtherPlayerByGuid(guid);
|
|||
|
}
|
|||
|
|
|||
|
public bool NeedCreate(Obj_Init_Data initData)
|
|||
|
{
|
|||
|
var result = true;
|
|||
|
if (initData != null)
|
|||
|
{
|
|||
|
var obj = FindObjCharacterInScene(initData.m_ServerID);
|
|||
|
if (obj != null)
|
|||
|
{
|
|||
|
obj.Init(initData);
|
|||
|
result = false;
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public void AddPoolOtherGameObj(string name, Obj obj)
|
|||
|
{
|
|||
|
if (!otherObjPools.ContainsKey(name))
|
|||
|
otherObjPools.Add(name, obj);
|
|||
|
else
|
|||
|
LogModule.ErrorLog("ObjManager AddPoolOtherGameObj already contain obj:" + name);
|
|||
|
}
|
|||
|
|
|||
|
//根据Gameobject的Name在非Obj池查找
|
|||
|
public Obj FindOtherGameObj(string strName)
|
|||
|
{
|
|||
|
Obj result;
|
|||
|
otherObjPools.TryGetValue(strName, out result);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateHideMask(int hideMask)
|
|||
|
{
|
|||
|
for (var i = 0; i < _otherList.Count; i++)
|
|||
|
if (!_otherList[i].isHide && _otherList[i].character != null)
|
|||
|
_otherList[i].character.SetHideByMask(hideMask);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 强制刷新其他玩家数目
|
|||
|
/// </summary>
|
|||
|
public void RefreshOtherPlayerCount(int current)
|
|||
|
{
|
|||
|
int previous = 0;
|
|||
|
for (var i = 0; i < _otherList.Count; i++)
|
|||
|
if (!_otherList[i].isHide && _otherList[i].character != null)
|
|||
|
previous++;
|
|||
|
var delta = current - previous;
|
|||
|
if (delta > 0)
|
|||
|
{
|
|||
|
for (var i = 0; i < _otherList.Count; i++)
|
|||
|
{
|
|||
|
if (_otherList[i].isHide && _otherList[i].character != null)
|
|||
|
{
|
|||
|
_otherList[i].SetHide(false);
|
|||
|
delta--;
|
|||
|
if (delta <= 0)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
for (var i = _otherList.Count - 1; i >= 0; i--)
|
|||
|
{
|
|||
|
if (!_otherList[i].isHide && _otherList[i].character != null)
|
|||
|
{
|
|||
|
_otherList[i].SetHide(true);
|
|||
|
delta++;
|
|||
|
if (delta >= 0)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private Obj_OtherPlayer CreateOtherPlayer(ObjParent_Init_Data initData)
|
|||
|
{
|
|||
|
return CreateCharacter<Obj_OtherPlayer>(initData, "Prefab/Model/OtherPlayerRoot");
|
|||
|
}
|
|||
|
|
|||
|
private T CreateCharacter<T>(ObjParent_Init_Data initData, string prefabPath) where T : Obj_Character
|
|||
|
{
|
|||
|
var character = ObjParent.Create<T>(initData, prefabPath);
|
|||
|
ApplyCachedEffect(character);
|
|||
|
return character;
|
|||
|
}
|
|||
|
|
|||
|
private void ApplyCachedEffect(Obj_Character character, int? serverId = null)
|
|||
|
{
|
|||
|
var id = serverId ?? character.ServerID;
|
|||
|
var cache = GetEffectCache(id, ListGetMode.remove);
|
|||
|
if (cache != null)
|
|||
|
{
|
|||
|
if (cache.shieldCache != null)
|
|||
|
character.CreateShield(cache.shieldCache);
|
|||
|
for (var i = 0; i < cache.effectList.Count; i++)
|
|||
|
{
|
|||
|
var effect = cache.effectList[i];
|
|||
|
character.PlayEffect(effect.effectId, time: effect.startTime, handle: effect.handle);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 在没有完整的数据层之前,暂时使用这个数据来处理一些Obj协议接收顺序问题
|
|||
|
/// </summary>
|
|||
|
public class ObjEffectCache
|
|||
|
{
|
|||
|
public readonly List<ObjEffectCacheData> effectList = new List<ObjEffectCacheData>();
|
|||
|
public readonly int serverId;
|
|||
|
|
|||
|
public ObjEffectCache(int serverId)
|
|||
|
{
|
|||
|
this.serverId = serverId;
|
|||
|
}
|
|||
|
|
|||
|
public ObjShieldData shieldCache { get; private set; }
|
|||
|
|
|||
|
public void AddEffect(int effectId, int? handle = null)
|
|||
|
{
|
|||
|
if (effectId > GlobeVar.INVALID_ID)
|
|||
|
{
|
|||
|
var effect = new ObjEffectCacheData(effectId, handle, Time.time);
|
|||
|
effectList.Add(effect);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void RemoveEffect(int effectId)
|
|||
|
{
|
|||
|
for (var i = effectList.Count - 1; i >= 0; i--)
|
|||
|
if (effectList[i].effectId == effectId)
|
|||
|
effectList.RemoveAt(i);
|
|||
|
}
|
|||
|
|
|||
|
public void RemoveEffectByHandle(int handle)
|
|||
|
{
|
|||
|
for (var i = effectList.Count - 1; i >= 0; i--)
|
|||
|
if (effectList[i].handle != null && effectList[i].handle.Value == handle)
|
|||
|
effectList.RemoveAt(i);
|
|||
|
}
|
|||
|
|
|||
|
public void AddShield(ObjShieldData shieldData)
|
|||
|
{
|
|||
|
shieldCache = shieldData;
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateShield(long handle, long health)
|
|||
|
{
|
|||
|
if (shieldCache != null && shieldCache.handle == handle)
|
|||
|
shieldCache.health = health;
|
|||
|
}
|
|||
|
|
|||
|
public void RemoveShield(int handle)
|
|||
|
{
|
|||
|
if (shieldCache != null && shieldCache.handle == handle)
|
|||
|
shieldCache = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class ObjEffectCacheData
|
|||
|
{
|
|||
|
public readonly int effectId;
|
|||
|
public readonly int? handle;
|
|||
|
public readonly float startTime;
|
|||
|
|
|||
|
public ObjEffectCacheData(int effectId, int? handle, float startTime)
|
|||
|
{
|
|||
|
this.effectId = effectId;
|
|||
|
this.handle = handle;
|
|||
|
this.startTime = startTime;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|