mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +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