mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-07 16:45:10 +00:00
ACSystem
ACSystem
This commit is contained in:
3
Assets/TEngine/Scripts/Runtime/Actor.meta
Normal file
3
Assets/TEngine/Scripts/Runtime/Actor.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 334a6fb5ca0d4c62b3f3fdf9b32d37ab
|
||||
timeCreated: 1663555394
|
3
Assets/TEngine/Scripts/Runtime/Actor/ActorComponent.meta
Normal file
3
Assets/TEngine/Scripts/Runtime/Actor/ActorComponent.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6731a6b3e0ce4882b9ef2c5a890684ea
|
||||
timeCreated: 1663559772
|
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public class ActorAttribute
|
||||
{
|
||||
private class AttrChangeHandler
|
||||
{
|
||||
public Delegate Handle;
|
||||
|
||||
public void AddDelegate(Delegate handler)
|
||||
{
|
||||
Handle = Delegate.Combine(Handle, handler);
|
||||
}
|
||||
|
||||
public void RmvDelegate(Delegate handler)
|
||||
{
|
||||
Handle = Delegate.Remove(Handle, handler);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<int, object> _dictAttr = new Dictionary<int, object>();
|
||||
private readonly Dictionary<int, AttrChangeHandler> _attrChangedListener = new Dictionary<int, AttrChangeHandler>();
|
||||
|
||||
public void ClearAttribute(int attrId)
|
||||
{
|
||||
_dictAttr.Remove((int)attrId);
|
||||
}
|
||||
|
||||
public void SetAttribute<T>(int attrId, T val)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
T existVal;
|
||||
object exist;
|
||||
if (_dictAttr.TryGetValue(attrId, out exist))
|
||||
{
|
||||
existVal = (T)exist;
|
||||
|
||||
if (!EqualityComparer<T>.Default.Equals(existVal, val))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
existVal = default(T);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
if (changed)
|
||||
{
|
||||
_dictAttr[attrId] = val;
|
||||
|
||||
AttrChangeHandler handler;
|
||||
if (_attrChangedListener.TryGetValue(attrId, out handler))
|
||||
{
|
||||
Action<T, T> deleHandle = handler.Handle as Action<T, T>;
|
||||
if (deleHandle != null)
|
||||
{
|
||||
deleHandle(existVal, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T GetAttribute<T>(int attrId)
|
||||
{
|
||||
T val;
|
||||
TryGetAttribute(attrId, out val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public bool IsHaveAttribute(int attrId)
|
||||
{
|
||||
return _dictAttr.ContainsKey((int)attrId);
|
||||
}
|
||||
|
||||
public bool TryGetAttribute<T>(int attrId, out T val)
|
||||
{
|
||||
return GetAttributeValue((int)attrId, out val);
|
||||
}
|
||||
|
||||
public bool GetAttributeValue<T>(int attrId, out T val)
|
||||
{
|
||||
object objVal;
|
||||
var ret = _dictAttr.TryGetValue(attrId, out objVal);
|
||||
if (ret)
|
||||
{
|
||||
val = (T)objVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = default(T);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void RegAttrChangeEvent<T>(int attrId, Action<T, T> handler)
|
||||
{
|
||||
AttrChangeHandler handleNode;
|
||||
if (!_attrChangedListener.TryGetValue(attrId, out handleNode))
|
||||
{
|
||||
handleNode = new AttrChangeHandler();
|
||||
_attrChangedListener[attrId] = handleNode;
|
||||
}
|
||||
|
||||
handleNode.AddDelegate(handler);
|
||||
}
|
||||
|
||||
public void UnRegAttrChangeEvent<T>(int attrId, Action<T, T> handler)
|
||||
{
|
||||
UnRegAttrChangeEvent(attrId, handler);
|
||||
}
|
||||
|
||||
public void UnRegAttrChangeEvent(int attrId, Delegate handler)
|
||||
{
|
||||
AttrChangeHandler handleNode;
|
||||
if (_attrChangedListener.TryGetValue(attrId, out handleNode))
|
||||
{
|
||||
handleNode.RmvDelegate(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b72801b116e4865983ba9e6c85a40b3
|
||||
timeCreated: 1663560140
|
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// Actor 组件基类
|
||||
/// </summary>
|
||||
public abstract class ActorComponent
|
||||
{
|
||||
public bool m_callStart = false;
|
||||
private bool m_calledOnDestroy = false;
|
||||
protected GameActor m_actor;
|
||||
|
||||
private List<RegisterAttrChangeData> m_registAttrChanged = new List<RegisterAttrChangeData>();
|
||||
|
||||
public bool m_destroy;
|
||||
public ActorComponent m_prev;
|
||||
public ActorComponent m_next;
|
||||
|
||||
public GameTimer m_updateTimer;
|
||||
public GameTimer m_lateUpdateTimer;
|
||||
public bool m_needOnceUpdate = false;
|
||||
public bool m_needLoopUpdate = false;
|
||||
public bool m_needLoopLateUpdate = false;
|
||||
|
||||
protected void RequestOnceUpdate()
|
||||
{
|
||||
if (!m_callStart)
|
||||
{
|
||||
m_needOnceUpdate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameTimer.IsNull(m_updateTimer))
|
||||
{
|
||||
ActorComponentPool.Instance.RequestOnceUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RequestLoopUpdate(string detail = null)
|
||||
{
|
||||
if (!m_callStart)
|
||||
{
|
||||
m_needLoopUpdate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameTimer.IsNull(m_updateTimer))
|
||||
{
|
||||
ActorComponentPool.Instance.RequestLoopUpdate(this, detail);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RequestLoopLateUpdate()
|
||||
{
|
||||
if (!m_callStart)
|
||||
{
|
||||
m_needLoopLateUpdate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameTimer.IsNull(m_lateUpdateTimer))
|
||||
{
|
||||
ActorComponentPool.Instance.RequestLoopLateUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void StopLoopUpdate()
|
||||
{
|
||||
///如果是持久update的类型
|
||||
if (!m_callStart)
|
||||
{
|
||||
m_needLoopUpdate = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GameTimer.IsNull(m_updateTimer))
|
||||
{
|
||||
ActorComponentPool.Instance.StopLoopUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class RegisterAttrChangeData
|
||||
{
|
||||
public int AttrId;
|
||||
public Delegate Handler;
|
||||
|
||||
public RegisterAttrChangeData(int attrId, Delegate handler)
|
||||
{
|
||||
AttrId = attrId;
|
||||
Handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
public GameActor OwnActor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_actor != null && m_actor.IsDestroyed)
|
||||
{
|
||||
m_actor = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return m_actor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get { return m_actor.Position; }
|
||||
}
|
||||
|
||||
#region 扩展接口
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void LateUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 不显示的时候是否需要update
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool IsInvisibleNeedUpdate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 操作接口
|
||||
|
||||
/// <summary>
|
||||
/// 只有添加到对象上,才触发下面的初始化逻辑
|
||||
/// </summary>
|
||||
/// <param name="actor"></param>
|
||||
/// <returns></returns>
|
||||
public bool BeforeAddToActor(GameActor actor)
|
||||
{
|
||||
m_actor = actor;
|
||||
m_callStart = false;
|
||||
Awake();
|
||||
|
||||
AddDebug();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void BeforeDestroy()
|
||||
{
|
||||
if (m_calledOnDestroy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RmvDebug();
|
||||
|
||||
m_calledOnDestroy = true;
|
||||
if (m_actor != null)
|
||||
{
|
||||
ClearAllEventChangeHandler();
|
||||
OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void CallStart()
|
||||
{
|
||||
Log.Assert(!m_callStart);
|
||||
Start();
|
||||
m_callStart = true;
|
||||
}
|
||||
|
||||
|
||||
public void AfterOnStartAction(ActorTimerMgr timerMgr)
|
||||
{
|
||||
if (m_needLoopUpdate)
|
||||
{
|
||||
Log.Assert(GameTimer.IsNull(m_updateTimer));
|
||||
|
||||
timerMgr.CreateLoopFrameTimer(ref m_updateTimer, GetType().FullName, Update);
|
||||
}
|
||||
else if (m_needOnceUpdate)
|
||||
{
|
||||
Log.Assert(GameTimer.IsNull(m_updateTimer));
|
||||
|
||||
if (GameTimer.IsNull(m_updateTimer))
|
||||
{
|
||||
m_updateTimer = timerMgr.CreateOnceFrameTimer(GetType().FullName, Update);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_needLoopLateUpdate)
|
||||
{
|
||||
Log.Assert(GameTimer.IsNull(m_lateUpdateTimer));
|
||||
|
||||
timerMgr.CreateLoopFrameLateTimer(ref m_lateUpdateTimer, GetType().FullName, LateUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DebugBehaviour
|
||||
|
||||
protected void AddDebug()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var debugData = UnityUtil.AddMonoBehaviour<ActorDebugerBehaviour>(OwnActor.gameObject);
|
||||
debugData.AddDebugComponent(GetType().Name);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected void RmvDebug()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var debugData = UnityUtil.AddMonoBehaviour<ActorDebugerBehaviour>(OwnActor.gameObject);
|
||||
debugData.RmvDebugComponent(GetType().Name);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected void SetDebugInfo(string key, string val)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var debugData = UnityUtil.AddMonoBehaviour<ActorDebugerBehaviour>(OwnActor.gameObject);
|
||||
debugData.SetDebugInfo(GetType().Name, key, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected void RemoveAllDebugInfo()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
var debugData = UnityUtil.AddMonoBehaviour<ActorDebugerBehaviour>(OwnActor.gameObject);
|
||||
debugData.RemoveAllDebugInfo(GetType().Name);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EventBehaviour
|
||||
|
||||
public void AddEventListener(int eventId, Action eventCallback)
|
||||
{
|
||||
m_actor.Event.AddEventListener(eventId, eventCallback, this);
|
||||
}
|
||||
|
||||
public void AddEventListener<T>(int eventId, Action<T> eventCallback)
|
||||
{
|
||||
m_actor.Event.AddEventListener(eventId, eventCallback, this);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, TU>(int eventId, Action<T, TU> eventCallback)
|
||||
{
|
||||
m_actor.Event.AddEventListener(eventId, eventCallback, this);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, TU, TV>(int eventId, Action<T, TU, TV> eventCallback)
|
||||
{
|
||||
m_actor.Event.AddEventListener(eventId, eventCallback, this);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, TU, TV, TS>(int eventId, Action<T, TU, TV, TS> eventCallback)
|
||||
{
|
||||
m_actor.Event.AddEventListener(eventId, eventCallback, this);
|
||||
}
|
||||
|
||||
public void RegAttrChangeEvent<T>(int attrId, Action<T, T> handler)
|
||||
{
|
||||
m_registAttrChanged.Add(new RegisterAttrChangeData(attrId, handler));
|
||||
OwnActor.Attr.RegAttrChangeEvent((int)attrId, handler);
|
||||
}
|
||||
|
||||
private void ClearAllEventChangeHandler()
|
||||
{
|
||||
var attr = OwnActor.Attr;
|
||||
for (int i = 0; i < m_registAttrChanged.Count; i++)
|
||||
{
|
||||
var data = m_registAttrChanged[i];
|
||||
attr.UnRegAttrChangeEvent(data.AttrId, data.Handler);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11beba8836b148d58a2cd426b79838ae
|
||||
timeCreated: 1663556055
|
@@ -0,0 +1,148 @@
|
||||
using TEngine.Runtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public class ActorComponentPool: BehaviourSingleton<ActorComponentPool>
|
||||
{
|
||||
private ActorComponent _listComponentHead;
|
||||
private ActorComponent _listStartComponentHead;
|
||||
private ActorTimerMgr _timerMgr;
|
||||
public override void Awake()
|
||||
{
|
||||
_timerMgr = ActorTimerMgr.Instance;
|
||||
}
|
||||
|
||||
|
||||
public T AllocComponent<T>() where T : ActorComponent,new()
|
||||
{
|
||||
var component = new T();
|
||||
AddToList(ref _listStartComponentHead, component);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public void FreeComponent(ActorComponent component)
|
||||
{
|
||||
if (component.m_destroy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
component.m_destroy = true;
|
||||
if (!component.m_callStart)
|
||||
{
|
||||
RmvFromList(ref _listStartComponentHead, component);
|
||||
|
||||
Debug.Assert(GameTimer.IsNull(component.m_updateTimer));
|
||||
Debug.Assert(GameTimer.IsNull(component.m_lateUpdateTimer));
|
||||
}
|
||||
else
|
||||
{
|
||||
RmvFromList(ref _listComponentHead, component);
|
||||
|
||||
var timerMgr = _timerMgr;
|
||||
timerMgr.DestroyTimer(ref component.m_updateTimer);
|
||||
timerMgr.DestroyTimer(ref component.m_lateUpdateTimer);
|
||||
}
|
||||
|
||||
Debug.Assert(component.m_next == null && component.m_prev == null);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
var timerMgr = _timerMgr;
|
||||
|
||||
while (_listStartComponentHead != null)
|
||||
{
|
||||
var start = _listStartComponentHead;
|
||||
Debug.Assert(!start.m_destroy);
|
||||
start.CallStart();
|
||||
if (start.m_destroy)
|
||||
{
|
||||
Debug.Assert(_listStartComponentHead != start);
|
||||
continue;
|
||||
}
|
||||
|
||||
RmvFromList(ref _listStartComponentHead, start);
|
||||
AddToList(ref _listComponentHead, start);
|
||||
start.AfterOnStartAction(timerMgr);
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestOnceUpdate(ActorComponent component)
|
||||
{
|
||||
component.m_updateTimer = _timerMgr.CreateOnceFrameTimer(component.GetType().FullName, component.Update);
|
||||
}
|
||||
|
||||
public void RequestLoopUpdate(ActorComponent component, string detail = null)
|
||||
{
|
||||
Debug.Assert(GameTimer.IsNull(component.m_updateTimer));
|
||||
var timerName = component.GetType().FullName;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!string.IsNullOrEmpty(detail))
|
||||
{
|
||||
timerName += ("_" + detail);
|
||||
}
|
||||
#endif
|
||||
|
||||
_timerMgr.CreateLoopFrameTimer(ref component.m_updateTimer, timerName, component.Update);
|
||||
}
|
||||
|
||||
public void StopLoopUpdate(ActorComponent component)
|
||||
{
|
||||
_timerMgr.DestroyTimer(ref component.m_updateTimer);
|
||||
}
|
||||
|
||||
public void RequestLoopLateUpdate(ActorComponent component)
|
||||
{
|
||||
Debug.Assert(GameTimer.IsNull(component.m_lateUpdateTimer));
|
||||
_timerMgr.CreateLoopFrameLateTimer(ref component.m_lateUpdateTimer, component.GetType().FullName, component.LateUpdate);
|
||||
}
|
||||
|
||||
public void StopLoopLateUpdate(ActorComponent component)
|
||||
{
|
||||
_timerMgr.DestroyTimer(ref component.m_lateUpdateTimer);
|
||||
}
|
||||
|
||||
private void AddToList(ref ActorComponent head, ActorComponent component)
|
||||
{
|
||||
if (head != null)
|
||||
{
|
||||
component.m_next = head;
|
||||
head.m_prev = component;
|
||||
}
|
||||
|
||||
head = component;
|
||||
}
|
||||
|
||||
private void RmvFromList(ref ActorComponent head, ActorComponent component)
|
||||
{
|
||||
var prev = component.m_prev;
|
||||
var next = component.m_next;
|
||||
|
||||
if (prev != null)
|
||||
{
|
||||
prev.m_next = next;
|
||||
}
|
||||
|
||||
if (next != null)
|
||||
{
|
||||
next.m_prev = prev;
|
||||
}
|
||||
|
||||
component.m_next = null;
|
||||
component.m_prev = null;
|
||||
|
||||
if (component == head)
|
||||
{
|
||||
head = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(prev != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e484ab8181734897b450b11453a922d5
|
||||
timeCreated: 1663557842
|
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
[Serializable]
|
||||
public class ActorComponentDebugKeyInfo
|
||||
{
|
||||
public string name;
|
||||
public string val;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ActorComponentDebugInfo
|
||||
{
|
||||
public string name;
|
||||
public List<ActorComponentDebugKeyInfo> infos = new List<ActorComponentDebugKeyInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用来调试查看actor信息
|
||||
/// </summary>
|
||||
public class ActorDebugerBehaviour : MonoBehaviour
|
||||
{
|
||||
public List<ActorComponentDebugInfo> componentInfos = new List<ActorComponentDebugInfo>();
|
||||
|
||||
public event Action OnGizmosSelect;
|
||||
public event Action OnGizmos;
|
||||
|
||||
public ActorComponentDebugInfo AddDebugComponent(string componentName)
|
||||
{
|
||||
var componentInfo = componentInfos.Find(item => item.name == componentName);
|
||||
if (componentInfo == null)
|
||||
{
|
||||
componentInfo = new ActorComponentDebugInfo();
|
||||
componentInfo.name = componentName;
|
||||
componentInfos.Add(componentInfo); ;
|
||||
}
|
||||
|
||||
return componentInfo;
|
||||
}
|
||||
|
||||
public void RmvDebugComponent(string componentName)
|
||||
{
|
||||
componentInfos.RemoveAll((item) => { return item.name == componentName; });
|
||||
}
|
||||
|
||||
public void SetDebugInfo(string componentName, string key, string val)
|
||||
{
|
||||
var componentInfo = AddDebugComponent(componentName);
|
||||
var entry = componentInfo.infos.Find(t => t.name == key);
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new ActorComponentDebugKeyInfo();
|
||||
entry.name = key;
|
||||
componentInfo.infos.Add(entry);
|
||||
}
|
||||
|
||||
entry.val = val;
|
||||
}
|
||||
|
||||
public void RemoveAllDebugInfo(string cmpName)
|
||||
{
|
||||
var cmpInfo = componentInfos.Find((item) => item.name == cmpName);
|
||||
if (cmpInfo != null)
|
||||
{
|
||||
cmpInfo.infos.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
if (OnGizmosSelect!=null)
|
||||
{
|
||||
OnGizmosSelect();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (OnGizmos != null)
|
||||
{
|
||||
OnGizmos();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d23fae349f9468c9f7bc6fa9dcb936f
|
||||
timeCreated: 1663558701
|
@@ -0,0 +1,447 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public class EventRegInfo
|
||||
{
|
||||
public Delegate callback;
|
||||
public object owner;
|
||||
public bool deleted;
|
||||
|
||||
public EventRegInfo(Delegate callback, object owner)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.owner = owner;
|
||||
deleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class ActorEventDispatcher
|
||||
{
|
||||
private readonly Dictionary<int, List<EventRegInfo>> _dictAllEventListener =
|
||||
new Dictionary<int, List<EventRegInfo>>();
|
||||
|
||||
/// <summary>
|
||||
/// 用于标记一个事件是不是正在处理
|
||||
/// </summary>
|
||||
private readonly List<int> _processEvent = new List<int>();
|
||||
|
||||
/// <summary>
|
||||
/// 用于标记一个事件是不是被移除
|
||||
/// </summary>
|
||||
private readonly List<int> _delayDeleteEvent = new List<int>();
|
||||
|
||||
public void DestroyAllEventListener()
|
||||
{
|
||||
var itr = _dictAllEventListener.GetEnumerator();
|
||||
while (itr.MoveNext())
|
||||
{
|
||||
var kv = itr.Current;
|
||||
kv.Value.Clear();
|
||||
}
|
||||
|
||||
_processEvent.Clear();
|
||||
_delayDeleteEvent.Clear();
|
||||
itr.Dispose();
|
||||
}
|
||||
|
||||
private void AddDelayDelete(int eventId)
|
||||
{
|
||||
if (!_delayDeleteEvent.Contains(eventId))
|
||||
{
|
||||
_delayDeleteEvent.Add(eventId);
|
||||
Log.Info("delay delete eventId[{0}]", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果找到eventId对应的监听,删除所有标记为delete的监听
|
||||
/// </summary>
|
||||
/// <param name="eventId"></param>
|
||||
private void CheckDelayDelete(int eventId)
|
||||
{
|
||||
if (_delayDeleteEvent.Contains(eventId))
|
||||
{
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
for (int i = 0; i < listListener.Count; i++)
|
||||
{
|
||||
if (listListener[i].deleted)
|
||||
{
|
||||
Log.Info("remove delay delete eventId[{0}]", eventId);
|
||||
listListener[i] = listListener[listListener.Count - 1];
|
||||
listListener.RemoveAt(listListener.Count - 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_delayDeleteEvent.Remove(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEvent(int eEventId)
|
||||
{
|
||||
int eventId = eEventId;
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
_processEvent.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEvent.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Action callBack = listListener[i].callback as Action;
|
||||
if (callBack != null)
|
||||
{
|
||||
callBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEvent.Count);
|
||||
Log.Assert(eventId == _processEvent[_processEvent.Count - 1]);
|
||||
#endif
|
||||
_processEvent.RemoveAt(_processEvent.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEvent<T>(int eEventId, T data)
|
||||
{
|
||||
int eventId = (int)eEventId;
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
_processEvent.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEvent.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<T> callBack = listListener[i].callback as Action<T>;
|
||||
if (callBack != null)
|
||||
{
|
||||
callBack(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEvent.Count);
|
||||
Log.Assert(eventId == _processEvent[_processEvent.Count - 1]);
|
||||
#endif
|
||||
|
||||
_processEvent.RemoveAt(_processEvent.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEvent<T, U>(int eEventId, T dataT, U dataU)
|
||||
{
|
||||
int eventId = (int)eEventId;
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
_processEvent.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEvent.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<T, U> callBack = listListener[i].callback as Action<T, U>;
|
||||
if (callBack != null)
|
||||
{
|
||||
callBack(dataT, dataU);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEvent.Count);
|
||||
Log.Assert(eventId == _processEvent[_processEvent.Count - 1]);
|
||||
#endif
|
||||
_processEvent.RemoveAt(_processEvent.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEvent<T, U, V>(int eEventId, T dataT, U dataU, V dataV)
|
||||
{
|
||||
int eventId = (int)eEventId;
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
_processEvent.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEvent.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<T, U, V> callBack = node.callback as Action<T, U, V>;
|
||||
if (callBack != null)
|
||||
{
|
||||
callBack(dataT, dataU, dataV);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEvent.Count);
|
||||
Log.Assert(eventId == _processEvent[_processEvent.Count - 1]);
|
||||
#endif
|
||||
_processEvent.RemoveAt(_processEvent.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEvent<T, U, V, S>(int eEventId, T dataT, U dataU, V dataV, S dataS)
|
||||
{
|
||||
int eventId = (int)eEventId;
|
||||
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventId, out listListener))
|
||||
{
|
||||
_processEvent.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEvent.Count;
|
||||
#endif
|
||||
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<T, U, V, S> callBack = listListener[i].callback as Action<T, U, V, S>;
|
||||
if (callBack != null)
|
||||
{
|
||||
callBack(dataT, dataU, dataV, dataS);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEvent.Count);
|
||||
Log.Assert(eventId == _processEvent[_processEvent.Count - 1]);
|
||||
#endif
|
||||
_processEvent.RemoveAt(_processEvent.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener(int eventHashId, Action eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventHashId, eventCallback, owner);
|
||||
}
|
||||
|
||||
public void AddEventListener<T>(int eventHashId, Action<T> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventHashId, eventCallback, owner);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U>(int eventHashId, Action<T, U> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventHashId, eventCallback, owner);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, V>(int eventHashId, Action<T, U, V> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventHashId, eventCallback, owner);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, V, S>(int eventHashId, Action<T, U, V, S> eventCallback,
|
||||
object owner)
|
||||
{
|
||||
AddEventListenerImp(eventHashId, eventCallback, owner);
|
||||
}
|
||||
|
||||
private void AddEventListenerImp(int eventHashId, Delegate listener, object owner)
|
||||
{
|
||||
List<EventRegInfo> listListener;
|
||||
if (!_dictAllEventListener.TryGetValue((int)eventHashId, out listListener))
|
||||
{
|
||||
listListener = new List<EventRegInfo>();
|
||||
_dictAllEventListener.Add((int)eventHashId, listListener);
|
||||
}
|
||||
|
||||
var existNode = listListener.Find((node) => { return node.callback == listener; });
|
||||
if (existNode != null)
|
||||
{
|
||||
if (existNode.deleted)
|
||||
{
|
||||
existNode.deleted = false;
|
||||
Log.Warning("AddEvent hashId deleted, repeat add: {0}", eventHashId);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Fatal("AddEvent hashId repeated: {0}", eventHashId);
|
||||
return;
|
||||
}
|
||||
|
||||
listListener.Add(new EventRegInfo(listener, owner));
|
||||
}
|
||||
|
||||
public void RemoveAllListenerByOwner(object owner)
|
||||
{
|
||||
var itr = _dictAllEventListener.GetEnumerator();
|
||||
while (itr.MoveNext())
|
||||
{
|
||||
var kv = itr.Current;
|
||||
var list = kv.Value;
|
||||
|
||||
int eventId = kv.Key;
|
||||
bool isProcessing = _processEvent.Contains(eventId);
|
||||
bool delayDeleted = false;
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
var regInfo = list[i];
|
||||
if (regInfo.owner == owner)
|
||||
{
|
||||
if (isProcessing)
|
||||
{
|
||||
regInfo.deleted = true;
|
||||
delayDeleted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
list[i] = list[list.Count - 1];
|
||||
list.RemoveAt(list.Count - 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayDeleted)
|
||||
{
|
||||
AddDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
itr.Dispose();
|
||||
}
|
||||
|
||||
public void RemoveEventListener(int eventHashId, Action eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventHashId, eventCallback);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T>(int eventHashId, Action<T> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventHashId, eventCallback);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U>(int eventHashId, Action<T, U> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventHashId, eventCallback);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, V>(int eventHashId, Action<T, U, V> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventHashId, eventCallback);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, V, S>(int eventHashId, Action<T, U, V, S> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventHashId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除监听,如果是正在处理的监听则标记为删除
|
||||
/// </summary>
|
||||
/// <param name="eventHashId"></param>
|
||||
/// <param name="listener"></param>
|
||||
protected void RemoveEventListenerImp(int eventHashId, Delegate listener)
|
||||
{
|
||||
List<EventRegInfo> listListener;
|
||||
if (_dictAllEventListener.TryGetValue(eventHashId, out listListener))
|
||||
{
|
||||
bool isProcessing = _processEvent.Contains(eventHashId);
|
||||
if (!isProcessing)
|
||||
{
|
||||
listListener.RemoveAll((node) => { return node.callback == listener; });
|
||||
}
|
||||
else
|
||||
{
|
||||
int listenCnt = listListener.Count;
|
||||
for (int i = 0; i < listenCnt; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.callback == listener)
|
||||
{
|
||||
node.deleted = true;
|
||||
AddDelayDelete(eventHashId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11f79102b8ab47d28744cb9f8d5ed7cf
|
||||
timeCreated: 1663559200
|
@@ -0,0 +1,30 @@
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public static class ActorEventHelper
|
||||
{
|
||||
public static void Send(GameActor actor, int eventId)
|
||||
{
|
||||
actor.Event.SendEvent(eventId);
|
||||
}
|
||||
|
||||
public static void Send<T>(GameActor actor, int eventId, T info)
|
||||
{
|
||||
actor.Event.SendEvent<T>(eventId, info);
|
||||
}
|
||||
|
||||
public static void Send<T, TU>(GameActor actor, int eventId, T info1, TU info2)
|
||||
{
|
||||
actor.Event.SendEvent<T, TU>(eventId, info1, info2);
|
||||
}
|
||||
|
||||
public static void Send<T, TU, TV>(GameActor actor, int eventId, T info1, TU info2, TV info3)
|
||||
{
|
||||
actor.Event.SendEvent<T, TU, TV>(eventId, info1, info2, info3);
|
||||
}
|
||||
|
||||
public static void Send<T, TU, TV, TW>(GameActor actor, int eventId, T info1, TU info2, TV info3, TW info4)
|
||||
{
|
||||
actor.Event.SendEvent<T, TU, TV, TW>(eventId, info1, info2, info3, info4);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e4e381f3f7a4bb285528fcfd817c120
|
||||
timeCreated: 1663559682
|
@@ -0,0 +1,7 @@
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public partial class ActorEventType
|
||||
{
|
||||
public static int ModelVisibleChange = StringId.StringToHash("ActorEventType.ModelVisibleChange");
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6a1564342d24e42974aef898d38228e
|
||||
timeCreated: 1663577274
|
248
Assets/TEngine/Scripts/Runtime/Actor/ActorManager.cs
Normal file
248
Assets/TEngine/Scripts/Runtime/Actor/ActorManager.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public partial class ActorType
|
||||
{
|
||||
public static int ActorNone = 1 << 0;
|
||||
public static int ActorPlayer = 1 << 1;
|
||||
}
|
||||
|
||||
public delegate bool CheckActorDelegate(GameActor actor);
|
||||
|
||||
public partial class ActorManager : BehaviourSingleton<ActorManager>
|
||||
{
|
||||
private const uint ClientGidStart = 1000000000;
|
||||
private const uint ClientGidEnd = 2000000000;
|
||||
private uint _clientGid = ClientGidStart;
|
||||
|
||||
private Dictionary<uint, GameActor> _actorPool = new Dictionary<uint, GameActor>();
|
||||
private Dictionary<int, GameActor> _goModelHash2Actor = new Dictionary<int, GameActor>();
|
||||
private List<GameActor> _listActor = new List<GameActor>();
|
||||
private GameActor _mainPlayer = null;
|
||||
private int _tickRefreshVisible;
|
||||
private Dictionary<int, System.Type> _actorTypes = new Dictionary<int, System.Type>();
|
||||
public Transform ActorRootTrans { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 注册Actor类型便于创建
|
||||
/// </summary>
|
||||
/// <param name="actorType"></param>
|
||||
/// <param name="type"></param>
|
||||
public void RegisterActorTypes(int actorType,System.Type type)
|
||||
{
|
||||
if (!_actorTypes.ContainsKey(actorType))
|
||||
{
|
||||
_actorTypes.Add(actorType,type);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
InitActorRoot();
|
||||
|
||||
_tickRefreshVisible = TimerMgr.Instance.AddTimer(o => { RefreshActorVisible(); }, 1f, true, true);
|
||||
}
|
||||
|
||||
private void InitActorRoot()
|
||||
{
|
||||
var actorRoot = GameObject.Find("ActorRoot");
|
||||
if (actorRoot == null)
|
||||
{
|
||||
actorRoot = new GameObject("ActorRoot");
|
||||
Object.DontDestroyOnLoad(actorRoot);
|
||||
ActorRootTrans = actorRoot.transform;
|
||||
ActorRootTrans.position = Vector3.zero;
|
||||
ActorRootTrans.rotation = Quaternion.identity;
|
||||
ActorRootTrans.localScale = Vector3.one;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshActorVisible()
|
||||
{
|
||||
}
|
||||
|
||||
public GameObject CreateGameObject(GameActor gameActor)
|
||||
{
|
||||
string name = gameActor.GetGameObjectName();
|
||||
GameObject actorGo = new GameObject(name);
|
||||
var trans = actorGo.transform;
|
||||
trans.parent = ActorRootTrans;
|
||||
trans.localPosition = Vector3.zero;
|
||||
trans.localRotation = Quaternion.identity;
|
||||
trans.localScale = Vector3.one;
|
||||
return actorGo;
|
||||
}
|
||||
|
||||
private uint AllocClientGid()
|
||||
{
|
||||
++_clientGid;
|
||||
if (_clientGid >= ClientGidEnd)
|
||||
{
|
||||
_clientGid = ClientGidStart;
|
||||
}
|
||||
return _clientGid;
|
||||
}
|
||||
|
||||
public void AddClientActor(GameActor actor)
|
||||
{
|
||||
if (actor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveClientActor(actor);
|
||||
actor.ActorId = AllocClientGid();
|
||||
_actorPool.Add(actor.ActorId, actor);
|
||||
_listActor.Add(actor);
|
||||
if (actor.gameObject != null)
|
||||
{
|
||||
_goModelHash2Actor[actor.gameObject.GetHashCode()] = actor;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveClientActor(GameActor actor)
|
||||
{
|
||||
if (actor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_actorPool.Remove(actor.ActorId);
|
||||
_listActor.Remove(actor);
|
||||
if (actor.gameObject != null)
|
||||
{
|
||||
_goModelHash2Actor.Remove(actor.gameObject.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public GameActor GetActor(uint actorGID)
|
||||
{
|
||||
GameActor actor = null;
|
||||
_actorPool.TryGetValue(actorGID, out actor);
|
||||
return actor;
|
||||
}
|
||||
|
||||
public GameActor GetActor(GameObject go)
|
||||
{
|
||||
GameActor actor;
|
||||
if (_goModelHash2Actor.TryGetValue(go.GetHashCode(), out actor))
|
||||
{
|
||||
return actor;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void BindGameActorGo(GameActor actor, GameObject go)
|
||||
{
|
||||
_goModelHash2Actor[go.GetHashCode()] = actor;
|
||||
}
|
||||
|
||||
public GameActor GetMainPlayer()
|
||||
{
|
||||
return _mainPlayer;
|
||||
}
|
||||
|
||||
#region Methods
|
||||
|
||||
public bool DestroyActor(GameActor actor)
|
||||
{
|
||||
return DestroyActor(actor.ActorId);
|
||||
}
|
||||
|
||||
public GameActor CreateGameActor(int actorType, uint actorID, bool isMainPlayer)
|
||||
{
|
||||
GameActor ret = null;
|
||||
|
||||
GameActor actorSave;
|
||||
if (_actorPool.TryGetValue(actorID, out actorSave))
|
||||
{
|
||||
var oldActor = _actorPool[actorID];
|
||||
var oldActorType = oldActor.GetActorType();
|
||||
Log.Error("duplicate actor gid {0} {1} {2}", actorID, actorType, oldActorType);
|
||||
if (oldActorType != actorType)
|
||||
{
|
||||
DestroyActor(actorID);
|
||||
ret = CreateGameActor(actorType, actorID);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = _actorPool[actorID];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = CreateGameActor(actorType, actorID);
|
||||
}
|
||||
|
||||
if (ret == null)
|
||||
{
|
||||
Log.Error("create actor failed, type is {0}, id is {1}", actorType, actorID);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isMainPlayer)
|
||||
{
|
||||
SetMainPlayer(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private GameActor CreateGameActor(int actorType, uint actorID)
|
||||
{
|
||||
GameActor newActor = null;
|
||||
|
||||
if (_actorTypes.TryGetValue(actorType, out var type))
|
||||
{
|
||||
newActor = System.Activator.CreateInstance(type) as GameActor;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("unknown actor type:{0}", actorType);
|
||||
}
|
||||
|
||||
if (newActor != null)
|
||||
{
|
||||
newActor.ActorId = actorID;
|
||||
_actorPool.Add(actorID, newActor);
|
||||
_listActor.Add(newActor);
|
||||
}
|
||||
|
||||
return newActor;
|
||||
}
|
||||
|
||||
public bool DestroyActor(uint actorID)
|
||||
{
|
||||
GameActor actor = null;
|
||||
if (_actorPool.TryGetValue(actorID, out actor))
|
||||
{
|
||||
if (actor == _mainPlayer)
|
||||
{
|
||||
SetMainPlayer(null);
|
||||
}
|
||||
|
||||
if (actor.gameObject != null)
|
||||
{
|
||||
_goModelHash2Actor.Remove(actor.gameObject.GetHashCode());
|
||||
}
|
||||
|
||||
actor.Destroy();
|
||||
_actorPool.Remove(actorID);
|
||||
_listActor.Remove(actor);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetMainPlayer(GameActor actor)
|
||||
{
|
||||
_mainPlayer = actor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 229662c5312943abbe0f2e01d993c6dd
|
||||
timeCreated: 1663577914
|
554
Assets/TEngine/Scripts/Runtime/Actor/ActorTimerMgr.cs
Normal file
554
Assets/TEngine/Scripts/Runtime/Actor/ActorTimerMgr.cs
Normal file
@@ -0,0 +1,554 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public enum TimerType
|
||||
{
|
||||
TimerTime = 0,
|
||||
TimerFrameUpdate,
|
||||
TimerFrameLateUpdate,
|
||||
TimerFrameOnceUpdate,
|
||||
TimerUnscaledTime,
|
||||
}
|
||||
|
||||
public class GameTimer
|
||||
{
|
||||
public GameTimer Next;
|
||||
public GameTimer Prev;
|
||||
public string DebugSourceName;
|
||||
public Action CallAction;
|
||||
public bool Destroyed;
|
||||
public bool Loop;
|
||||
public float Interval;
|
||||
public float TriggerTime;
|
||||
public bool InExeQueue;
|
||||
public TimerType timerType;
|
||||
|
||||
public static bool IsNull(GameTimer gameTimer)
|
||||
{
|
||||
return gameTimer == null || gameTimer.Destroyed;
|
||||
}
|
||||
}
|
||||
|
||||
public class GameTimerList
|
||||
{
|
||||
public GameTimer Head;
|
||||
public GameTimer Tail;
|
||||
|
||||
public int Count = 0;
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return Head == null; }
|
||||
}
|
||||
|
||||
public void AddTail(GameTimer node)
|
||||
{
|
||||
var tail = Tail;
|
||||
if (tail != null)
|
||||
{
|
||||
tail.Next = node;
|
||||
node.Prev = tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
Head = node;
|
||||
}
|
||||
|
||||
Tail = node;
|
||||
AddCount();
|
||||
}
|
||||
|
||||
|
||||
private void AddCount()
|
||||
{
|
||||
Count++;
|
||||
}
|
||||
|
||||
public void DecCount(int sub = 1)
|
||||
{
|
||||
Count -= sub;
|
||||
Log.Assert(Count >= 0);
|
||||
}
|
||||
|
||||
public void AddSorted(GameTimer node, float triggerTime)
|
||||
{
|
||||
Log.Assert(node.Prev == null);
|
||||
Log.Assert(node.Next == null);
|
||||
|
||||
node.TriggerTime = triggerTime;
|
||||
|
||||
var head = Head;
|
||||
while (head != null)
|
||||
{
|
||||
if (head.TriggerTime >= triggerTime)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
head = head.Next;
|
||||
}
|
||||
|
||||
if (head != null)
|
||||
{
|
||||
var prev = head.Prev;
|
||||
if (prev != null)
|
||||
{
|
||||
prev.Next = node;
|
||||
}
|
||||
|
||||
node.Prev = prev;
|
||||
|
||||
node.Next = head;
|
||||
head.Prev = node;
|
||||
|
||||
if (prev == null)
|
||||
{
|
||||
Head = node;
|
||||
}
|
||||
|
||||
AddCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddTail(node);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(GameTimer node)
|
||||
{
|
||||
var prev = node.Prev;
|
||||
var next = node.Next;
|
||||
|
||||
if (prev != null)
|
||||
{
|
||||
prev.Next = next;
|
||||
}
|
||||
|
||||
if (next != null)
|
||||
{
|
||||
next.Prev = prev;
|
||||
}
|
||||
|
||||
node.Next = null;
|
||||
node.Prev = null;
|
||||
|
||||
if (Head == node)
|
||||
{
|
||||
Head = next;
|
||||
}
|
||||
|
||||
if (Tail == node)
|
||||
{
|
||||
Tail = prev;
|
||||
}
|
||||
|
||||
DecCount();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Head = null;
|
||||
Tail = null;
|
||||
Count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class ActorTimerMgr : BehaviourSingleton<ActorTimerMgr>
|
||||
{
|
||||
private GameTimerList _runningList = new GameTimerList();
|
||||
private GameTimerList _frameUpdateList = new GameTimerList();
|
||||
private GameTimerList _frameLateUpdateList = new GameTimerList();
|
||||
private GameTimerList _frameOnceUpdateList = new GameTimerList();
|
||||
private GameTimerList _unscaleRunningList = new GameTimerList();
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
DoCreateLoopTimer("TimerDebug", 10f, () =>
|
||||
{
|
||||
var totalCount = _frameUpdateList.Count + _frameLateUpdateList.Count +
|
||||
+_frameOnceUpdateList.Count + _runningList.Count + _unscaleRunningList.Count;
|
||||
|
||||
int maxTriggerCount = 2000;
|
||||
if (totalCount > maxTriggerCount)
|
||||
{
|
||||
Log.Fatal("Timer is overflow: {0}", totalCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#region 创建定时器接口
|
||||
|
||||
public bool CreateLoopTimer(ref GameTimer result, string source, float interval, Action timerAction)
|
||||
{
|
||||
if (!GameTimer.IsNull(result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = DoCreateLoopTimer(source, interval, timerAction);
|
||||
return true;
|
||||
}
|
||||
|
||||
private GameTimer DoCreateLoopTimer(string source, float interval, Action timerAction)
|
||||
{
|
||||
interval = Math.Max(interval, 0.001f);
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerTime;
|
||||
timer.Loop = true;
|
||||
timer.Interval = interval;
|
||||
var triggerTime = Time.time + interval;
|
||||
_runningList.AddSorted(timer, triggerTime);
|
||||
return timer;
|
||||
}
|
||||
|
||||
public GameTimer CreateOnceTimer(string source, float elapse, Action timerAction)
|
||||
{
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerTime;
|
||||
var triggerTime = Time.time + elapse;
|
||||
_runningList.AddSorted(timer, triggerTime);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改定时器循环创建接口,改为更加安全的方式
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="timerAction"></param>
|
||||
public bool CreateLoopFrameTimer(ref GameTimer result, string source, Action timerAction)
|
||||
{
|
||||
if (!GameTimer.IsNull(result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = DoCreateLoopFrameTimer(source, timerAction);
|
||||
return true;
|
||||
}
|
||||
|
||||
private GameTimer DoCreateLoopFrameTimer(string source, Action timerAction)
|
||||
{
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerFrameUpdate;
|
||||
_frameUpdateList.AddTail(timer);
|
||||
return timer;
|
||||
}
|
||||
|
||||
public GameTimer CreateOnceFrameTimer(string source, Action timerAction)
|
||||
{
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerFrameOnceUpdate;
|
||||
_frameOnceUpdateList.AddTail(timer);
|
||||
return timer;
|
||||
}
|
||||
|
||||
public bool CreateLoopFrameLateTimer(ref GameTimer result, string source, Action timerAction)
|
||||
{
|
||||
if (!GameTimer.IsNull(result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = DoCreateLoopFrameLateTimer(source, timerAction);
|
||||
return true;
|
||||
}
|
||||
|
||||
private GameTimer DoCreateLoopFrameLateTimer(string source, Action timerAction)
|
||||
{
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerFrameLateUpdate;
|
||||
_frameLateUpdateList.AddTail(timer);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 不受
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="interval"></param>
|
||||
/// <param name="timerAction"></param>
|
||||
/// <returns></returns>
|
||||
public GameTimer CreateUnscaleLoopTimer(string source, float interval, Action timerAction)
|
||||
{
|
||||
interval = Math.Max(interval, 0.001f);
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerUnscaledTime;
|
||||
timer.Loop = true;
|
||||
timer.Interval = interval;
|
||||
var triggerTime = Time.unscaledTime + interval;
|
||||
_unscaleRunningList.AddSorted(timer, triggerTime);
|
||||
return timer;
|
||||
}
|
||||
|
||||
public GameTimer CreateUnscaleOnceTimer(string source, float elapse, Action timerAction)
|
||||
{
|
||||
var timer = AllocTimer(source, timerAction);
|
||||
timer.timerType = TimerType.TimerUnscaledTime;
|
||||
var triggerTime = Time.unscaledTime + elapse;
|
||||
_unscaleRunningList.AddSorted(timer, triggerTime);
|
||||
return timer;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 销毁定时器接口
|
||||
|
||||
public void DestroyTimer(ref GameTimer gameTimer)
|
||||
{
|
||||
ProcessDestroyTimer(gameTimer);
|
||||
gameTimer = null;
|
||||
}
|
||||
|
||||
private void ProcessDestroyTimer(GameTimer gameTimer)
|
||||
{
|
||||
if (gameTimer == null || gameTimer.Destroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DoDestroy(gameTimer);
|
||||
|
||||
if (!gameTimer.InExeQueue)
|
||||
{
|
||||
var type = gameTimer.timerType;
|
||||
if (type == TimerType.TimerTime)
|
||||
{
|
||||
_runningList.Remove(gameTimer);
|
||||
}
|
||||
else if (type == TimerType.TimerFrameUpdate)
|
||||
{
|
||||
_frameUpdateList.Remove(gameTimer);
|
||||
}
|
||||
else if (type == TimerType.TimerFrameOnceUpdate)
|
||||
{
|
||||
_frameOnceUpdateList.Remove(gameTimer);
|
||||
}
|
||||
else if (type == TimerType.TimerUnscaledTime)
|
||||
{
|
||||
_unscaleRunningList.Remove(gameTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Assert(type == TimerType.TimerFrameLateUpdate);
|
||||
_frameLateUpdateList.Remove(gameTimer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Debug("Free when in exuete queue");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool IsHaveLateUpdate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void LateUpdate()
|
||||
{
|
||||
UpdateFrameTimer(_frameLateUpdateList);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
TProfiler.BeginSample("UpdateTickTimer");
|
||||
UpdateTickTimer(false);
|
||||
TProfiler.EndSample();
|
||||
|
||||
TProfiler.BeginSample("UpdateUnscaleTickTimer");
|
||||
UpdateTickTimer(true);
|
||||
TProfiler.EndSample();
|
||||
|
||||
TProfiler.BeginSample("UpdateFrameTimer");
|
||||
UpdateFrameTimer(_frameUpdateList);
|
||||
TProfiler.EndSample();
|
||||
|
||||
TProfiler.BeginSample("UpdateOnceFrameTimer");
|
||||
UpdateOnceFrameTimer(_frameOnceUpdateList);
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
|
||||
private void UpdateTickTimer(bool isUnscaled)
|
||||
{
|
||||
var runningList = isUnscaled ? _unscaleRunningList : _runningList;
|
||||
var head = runningList.Head;
|
||||
if (head != null)
|
||||
{
|
||||
var nowTime = isUnscaled ? Time.unscaledTime : Time.time;
|
||||
var node = head;
|
||||
|
||||
int delCount = 0;
|
||||
while (node != null && node.TriggerTime <= nowTime)
|
||||
{
|
||||
Log.Assert(!node.Destroyed);
|
||||
node.InExeQueue = true;
|
||||
node = node.Next;
|
||||
|
||||
delCount++;
|
||||
}
|
||||
|
||||
if (head == node)
|
||||
{
|
||||
Log.Assert(delCount <= 0);
|
||||
return;
|
||||
}
|
||||
|
||||
GameTimer waitExeHead = null;
|
||||
if (node != null)
|
||||
{
|
||||
var prev = node.Prev;
|
||||
prev.Next = null;
|
||||
|
||||
node.Prev = null;
|
||||
runningList.Head = node;
|
||||
|
||||
runningList.DecCount(delCount);
|
||||
Log.Assert(runningList.Count >= 0);
|
||||
|
||||
waitExeHead = head;
|
||||
}
|
||||
else
|
||||
{
|
||||
waitExeHead = head;
|
||||
runningList.Clear();
|
||||
}
|
||||
|
||||
node = waitExeHead;
|
||||
while (node != null)
|
||||
{
|
||||
var next = node.Next;
|
||||
node.Next = null;
|
||||
node.Prev = null;
|
||||
|
||||
if (!node.Destroyed)
|
||||
{
|
||||
TProfiler.BeginFirstSample(node.DebugSourceName);
|
||||
|
||||
node.CallAction();
|
||||
|
||||
TProfiler.EndFirstSample();
|
||||
|
||||
if (node.Loop && !node.Destroyed)
|
||||
{
|
||||
node.InExeQueue = false;
|
||||
var triggerTime = node.Interval + nowTime;
|
||||
runningList.AddSorted(node, triggerTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDestroy(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Debug("destroy timer: {0}", node.DebugSourceName);
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PrintTimerListStatic(GameTimerList list)
|
||||
{
|
||||
Dictionary<string, int> dictStat = new Dictionary<string, int>();
|
||||
var node = list.Head;
|
||||
while (node != null)
|
||||
{
|
||||
var count = 0;
|
||||
dictStat.TryGetValue(node.DebugSourceName, out count);
|
||||
count++;
|
||||
|
||||
dictStat[node.DebugSourceName] = count;
|
||||
node = node.Next;
|
||||
}
|
||||
|
||||
var itr = dictStat.GetEnumerator();
|
||||
while (itr.MoveNext())
|
||||
{
|
||||
Log.Warning("{0}:{1}", itr.Current.Key, itr.Current.Value);
|
||||
}
|
||||
itr.Dispose();
|
||||
}
|
||||
|
||||
private void UpdateFrameTimer(GameTimerList list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var node = list.Head;
|
||||
while (node != null)
|
||||
{
|
||||
Log.Assert(!node.Destroyed, node.DebugSourceName);
|
||||
|
||||
node.InExeQueue = true;
|
||||
|
||||
TProfiler.BeginSample(node.DebugSourceName);
|
||||
|
||||
if (node.CallAction != null)
|
||||
{
|
||||
node.CallAction();
|
||||
}
|
||||
|
||||
TProfiler.EndSample();
|
||||
|
||||
node.InExeQueue = false;
|
||||
|
||||
var next = node.Next;
|
||||
if (node.Destroyed)
|
||||
{
|
||||
Log.Debug("timer is destroy when loop, free it");
|
||||
list.Remove(node);
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateOnceFrameTimer(GameTimerList list)
|
||||
{
|
||||
var node = list.Head;
|
||||
list.Clear();
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
Log.Assert(!node.Destroyed);
|
||||
|
||||
node.InExeQueue = true;
|
||||
|
||||
TProfiler.BeginFirstSample(node.DebugSourceName);
|
||||
|
||||
node.CallAction();
|
||||
|
||||
TProfiler.EndFirstSample();
|
||||
|
||||
var next = node.Next;
|
||||
DoDestroy(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DoDestroy(GameTimer gameTimer)
|
||||
{
|
||||
gameTimer.Destroyed = true;
|
||||
gameTimer.CallAction = null;
|
||||
}
|
||||
|
||||
private GameTimer AllocTimer(string source, Action timerAction)
|
||||
{
|
||||
var freeHead = new GameTimer();
|
||||
freeHead.CallAction = timerAction;
|
||||
freeHead.DebugSourceName = source;
|
||||
return freeHead;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b9600b871d94b468afbd03e9ef3fbf0
|
||||
timeCreated: 1663557236
|
277
Assets/TEngine/Scripts/Runtime/Actor/GameActor.cs
Normal file
277
Assets/TEngine/Scripts/Runtime/Actor/GameActor.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏对象(GameActor)
|
||||
/// </summary>
|
||||
public abstract partial class GameActor
|
||||
{
|
||||
#region Propreties
|
||||
public uint ActorId { get; set; }
|
||||
|
||||
public bool IsCreated { get; set; }
|
||||
|
||||
public byte ActorSide;
|
||||
|
||||
public abstract int GetActorType();
|
||||
|
||||
public bool IsDestroyed { get; set; }
|
||||
|
||||
public string Name = string.Empty;
|
||||
|
||||
private ActorEventDispatcher _event = new ActorEventDispatcher();
|
||||
|
||||
public ActorEventDispatcher Event => _event;
|
||||
|
||||
private GameObject _gameObject;
|
||||
|
||||
public GameObject gameObject => _gameObject;
|
||||
|
||||
private float _visibleTime = 0;
|
||||
|
||||
private bool _visible;
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get { return _visible; }
|
||||
set
|
||||
{
|
||||
if (_gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_visible != value)
|
||||
{
|
||||
_visible = value && CheckActorCanVisible();
|
||||
if (_visible && _visibleTime <= 0.0001f)
|
||||
{
|
||||
_visibleTime = Time.time;
|
||||
}
|
||||
Event.SendEvent(ActorEventType.ModelVisibleChange, _visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CheckActorCanVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetGameObjectName()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return string.Format("[{0}][{1}][{2}]", ActorId, GetActorType(), GetActorName());
|
||||
#else
|
||||
return "GameActor";
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual string GetActorName()
|
||||
{
|
||||
return "UNNAMED";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Actions
|
||||
public Action Awake;
|
||||
public Action OnInit;
|
||||
public Action AfterInit;
|
||||
#endregion
|
||||
|
||||
#region Transform
|
||||
public Transform transform
|
||||
{
|
||||
get
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor gameObject is Null");
|
||||
}
|
||||
|
||||
return gameObject.transform;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
return transform.position;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
transform.position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Forward
|
||||
{
|
||||
get
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
return transform.forward;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
transform.forward = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 LocalScale
|
||||
{
|
||||
get
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
return transform.localScale;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (transform == null)
|
||||
{
|
||||
throw new Exception("Runtime GameActor transform is Null");
|
||||
}
|
||||
|
||||
transform.localScale = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion Rotation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (transform != null)
|
||||
{
|
||||
return transform.rotation;
|
||||
}
|
||||
|
||||
return Quaternion.identity;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (transform != null)
|
||||
{
|
||||
transform.rotation = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
public GameActor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual GameObject CreateGameObject()
|
||||
{
|
||||
return ActorManager.Instance.CreateGameObject(this);
|
||||
}
|
||||
|
||||
protected void BaseInit()
|
||||
{
|
||||
if (_gameObject == null)
|
||||
{
|
||||
_visible = false;
|
||||
|
||||
_gameObject = CreateGameObject();
|
||||
|
||||
ActorManager.Instance.BindGameActorGo(this,_gameObject);
|
||||
}
|
||||
InitExt();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
Visible = false;
|
||||
|
||||
_isDestroying = true;
|
||||
|
||||
BeforeDestroyAllComponent();
|
||||
|
||||
DestroyAllComponent();
|
||||
|
||||
if (gameObject != null)
|
||||
{
|
||||
Object.Destroy(_gameObject);
|
||||
|
||||
_gameObject = null;
|
||||
}
|
||||
|
||||
IsDestroyed = true;
|
||||
_isDestroying = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Expand
|
||||
|
||||
#region Base
|
||||
public static bool operator ==(GameActor obj1, GameActor obj2)
|
||||
{
|
||||
if (ReferenceEquals(obj1, obj2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isObj1Null = ReferenceEquals(obj1, null) || obj1.IsDestroyed;
|
||||
bool isObj2Null = ReferenceEquals(obj2, null) || obj2.IsDestroyed;
|
||||
return isObj1Null && isObj2Null;
|
||||
}
|
||||
|
||||
public static bool operator !=(GameActor obj1, GameActor obj2)
|
||||
{
|
||||
return !(obj1 == obj2);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj2)
|
||||
{
|
||||
bool isObj1Null = IsDestroyed;
|
||||
bool isObj2Null = ReferenceEquals(obj2, null);
|
||||
if (isObj1Null && isObj2Null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ReferenceEquals(this, obj2);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
3
Assets/TEngine/Scripts/Runtime/Actor/GameActor.cs.meta
Normal file
3
Assets/TEngine/Scripts/Runtime/Actor/GameActor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bf64870c7814cedabaf3be95c0165c2
|
||||
timeCreated: 1663555405
|
120
Assets/TEngine/Scripts/Runtime/Actor/GameActorExt.cs
Normal file
120
Assets/TEngine/Scripts/Runtime/Actor/GameActorExt.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Runtime.Actor
|
||||
{
|
||||
public abstract partial class GameActor
|
||||
{
|
||||
public ActorAttribute Attr = new ActorAttribute();
|
||||
private readonly List<ActorComponent> _listComponents = new List<ActorComponent>();
|
||||
private readonly Dictionary<string, ActorComponent> _mapComponents = new Dictionary<string, ActorComponent>();
|
||||
private bool _isDestroying = false;
|
||||
|
||||
protected void InitExt()
|
||||
{
|
||||
_isDestroying = false;
|
||||
}
|
||||
|
||||
#region component
|
||||
|
||||
public T AddComponent<T>() where T : ActorComponent, new()
|
||||
{
|
||||
if (IsDestroyed || _isDestroying)
|
||||
{
|
||||
Log.Fatal("Actor is destroyed, cant add component: {0}, Is Destroying[{1}]",
|
||||
GetClassName(typeof(T)), _isDestroying);
|
||||
return null;
|
||||
}
|
||||
|
||||
T component = GetComponent<T>();
|
||||
if (component != null)
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
component = ActorComponentPool.Instance.AllocComponent<T>();
|
||||
if (!AddComponentImp(component))
|
||||
{
|
||||
Log.Warning("AddComponent failed, Component name: {0}", GetClassName(typeof(T)));
|
||||
component.BeforeDestroy();
|
||||
ActorComponentPool.Instance.FreeComponent(component);
|
||||
return null;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public T GetComponent<T>() where T : ActorComponent
|
||||
{
|
||||
ActorComponent component;
|
||||
if (_mapComponents.TryGetValue(GetClassName(typeof(T)), out component))
|
||||
{
|
||||
return component as T;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveComponent<T>() where T : ActorComponent
|
||||
{
|
||||
if (_isDestroying)
|
||||
{
|
||||
Log.Debug("GameActor[{0}] is destroying, no need destroy component anyway", Name);
|
||||
return;
|
||||
}
|
||||
|
||||
string className = GetClassName(typeof(T));
|
||||
ActorComponent component;
|
||||
if (_mapComponents.TryGetValue(className, out component))
|
||||
{
|
||||
component.BeforeDestroy();
|
||||
|
||||
Event.RemoveAllListenerByOwner(component);
|
||||
_mapComponents.Remove(className);
|
||||
_listComponents.Remove(component);
|
||||
|
||||
ActorComponentPool.Instance.FreeComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
private bool AddComponentImp<T>(T component) where T : ActorComponent
|
||||
{
|
||||
if (!component.BeforeAddToActor(this))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_listComponents.Add(component);
|
||||
_mapComponents[GetClassName(typeof(T))] = component;
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetClassName(Type type)
|
||||
{
|
||||
return type.FullName;
|
||||
}
|
||||
|
||||
private void BeforeDestroyAllComponent()
|
||||
{
|
||||
var listCmpt = _listComponents;
|
||||
for (int i = listCmpt.Count - 1; i >= 0; i--)
|
||||
{
|
||||
listCmpt[i].BeforeDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyAllComponent()
|
||||
{
|
||||
var componentPool = ActorComponentPool.Instance;
|
||||
|
||||
var listComponents = _listComponents;
|
||||
for (int i = listComponents.Count - 1; i >= 0; i--)
|
||||
{
|
||||
componentPool.FreeComponent(listComponents[i]);
|
||||
}
|
||||
_listComponents.Clear();
|
||||
_mapComponents.Clear();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4aeb507ce5b4cb596451316dc069212
|
||||
timeCreated: 1663558112
|
Reference in New Issue
Block a user