ACSystem
This commit is contained in:
ALEXTANG
2022-09-19 17:44:41 +08:00
parent a35830a912
commit 818bd8eafd
24 changed files with 2389 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 334a6fb5ca0d4c62b3f3fdf9b32d37ab
timeCreated: 1663555394

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6731a6b3e0ce4882b9ef2c5a890684ea
timeCreated: 1663559772

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8b72801b116e4865983ba9e6c85a40b3
timeCreated: 1663560140

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11beba8836b148d58a2cd426b79838ae
timeCreated: 1663556055

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e484ab8181734897b450b11453a922d5
timeCreated: 1663557842

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0d23fae349f9468c9f7bc6fa9dcb936f
timeCreated: 1663558701

View File

@@ -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;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11f79102b8ab47d28744cb9f8d5ed7cf
timeCreated: 1663559200

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9e4e381f3f7a4bb285528fcfd817c120
timeCreated: 1663559682

View File

@@ -0,0 +1,7 @@
namespace TEngine.Runtime.Actor
{
public partial class ActorEventType
{
public static int ModelVisibleChange = StringId.StringToHash("ActorEventType.ModelVisibleChange");
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b6a1564342d24e42974aef898d38228e
timeCreated: 1663577274

View 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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 229662c5312943abbe0f2e01d993c6dd
timeCreated: 1663577914

View 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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8b9600b871d94b468afbd03e9ef3fbf0
timeCreated: 1663557236

View 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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9bf64870c7814cedabaf3be95c0165c2
timeCreated: 1663555405

View 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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f4aeb507ce5b4cb596451316dc069212
timeCreated: 1663558112