mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
8
Assets/TEngine/Runtime/ECS.meta
Normal file
8
Assets/TEngine/Runtime/ECS.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d941eb2d2cbae294bb5d2788bb724e80
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
113
Assets/TEngine/Runtime/ECS/ArrayPool.cs
Normal file
113
Assets/TEngine/Runtime/ECS/ArrayPool.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public interface IIndex
|
||||
{
|
||||
int Index { get; set; }
|
||||
}
|
||||
|
||||
internal class HashSetDebugView<T> where T : IIndex
|
||||
{
|
||||
private readonly ArrayPool<T> m_Set;
|
||||
|
||||
public HashSetDebugView(ArrayPool<T> set)
|
||||
{
|
||||
m_Set = set ?? throw new ArgumentNullException(nameof(set));
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public T[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Set.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerTypeProxy(typeof(HashSetDebugView<>))]
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
public class ArrayPool<T> where T:IIndex
|
||||
{
|
||||
internal T[] m_Items = new T[256];
|
||||
internal bool[] Buckets = new bool[256];
|
||||
private int m_Index;
|
||||
private int count;
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Items[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
m_Items[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < m_Items.Length; i++)
|
||||
{
|
||||
if (Buckets[i])
|
||||
{
|
||||
elements.Add(m_Items[i]);
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
public void Remove(T item)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
m_Items[item.Index] = default;
|
||||
Buckets[item.Index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (item.Index != -1)
|
||||
{
|
||||
if (!Buckets[item.Index])
|
||||
{
|
||||
m_Items[item.Index] = item;
|
||||
Buckets[item.Index] = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_Items[m_Index] = item;
|
||||
Buckets[m_Index] = true;
|
||||
item.Index = m_Index;
|
||||
m_Index++;
|
||||
if (m_Index >= m_Items.Length)
|
||||
{
|
||||
T[] newItems = new T[m_Items.Length * 2];
|
||||
bool[] newBuckets = new bool[m_Items.Length * 2];
|
||||
Array.Copy(m_Items,0,newItems,0,m_Items.Length);
|
||||
Array.Copy(Buckets, 0, newBuckets, 0, Buckets.Length);
|
||||
m_Items = newItems;
|
||||
Buckets = newBuckets;
|
||||
}
|
||||
count = m_Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ArrayPool.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ArrayPool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1abd052a77e45b44ebcde5803fb36afd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/ECS/Demo.meta
Normal file
8
Assets/TEngine/Runtime/ECS/Demo.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 385b1863dab169f4fa291611477e106c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
25
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs
Normal file
25
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
|
||||
public class ECSDemoApp : MonoBehaviour
|
||||
{
|
||||
public ECSGameSystem EcsGameSystem = new ECSGameSystem();
|
||||
public GameObject @object;
|
||||
|
||||
void Start()
|
||||
{
|
||||
var entity = EcsGameSystem.Create<Entity>();
|
||||
ECSActor actor = entity.AddComponent<ECSActor>();
|
||||
actor.Name = typeof(ECSActor).ToString();
|
||||
actor.gameObject = Instantiate(@object);
|
||||
actor.transform = actor.gameObject.GetComponent<Transform>();
|
||||
entity.AddComponent<ECSComponent>();
|
||||
|
||||
Debug.Log(entity.ToString());
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
EcsGameSystem.OnUpdate();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb5cf3287e9bf3949820b50049e4bd8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs
Normal file
9
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using TEngine;
|
||||
|
||||
public class ECSGameSystem : ECSSystem
|
||||
{
|
||||
public void OnUpdate()
|
||||
{
|
||||
Update();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9d458a85873d744ab382e86008b89a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/TEngine/Runtime/ECS/ECSActor.cs
Normal file
13
Assets/TEngine/Runtime/ECS/ECSActor.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS Actor
|
||||
/// </summary>
|
||||
public class ECSActor : ECSComponent
|
||||
{
|
||||
public string Name;
|
||||
public UnityEngine.GameObject gameObject;
|
||||
public UnityEngine.Transform transform;
|
||||
public uint ActorID;
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSActor.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSActor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34a977c48d3bdb144b7c923a702164b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
14
Assets/TEngine/Runtime/ECS/ECSComponent.cs
Normal file
14
Assets/TEngine/Runtime/ECS/ECSComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS构架可以将此组件从Entity上移除这个组件并丢入对象池,给其他此刻需要此组件的Entity使用,
|
||||
/// 因此可以节省大量的内存反复创建和释放, 这也是ECS的特性可以大量重复使用组件
|
||||
/// </summary>
|
||||
public class ECSComponent:ECSObject
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public Entity Entity { get; set; }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e93d874e10ffedf488c413fd5bbc012f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
72
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs
Normal file
72
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public enum ECSDebugType
|
||||
{
|
||||
Entity,
|
||||
System,
|
||||
Component
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ECSCmptDebugKeyInfo
|
||||
{
|
||||
public string m_name;
|
||||
public string val;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ECSCmptDebugInfo
|
||||
{
|
||||
public string m_name;
|
||||
public ECSDebugType Type = ECSDebugType.Component;
|
||||
public List<ECSCmptDebugKeyInfo> m_info = new List<ECSCmptDebugKeyInfo>();
|
||||
}
|
||||
|
||||
public class ECSDebugBehaviour : UnityEngine.MonoBehaviour
|
||||
{
|
||||
public List<ECSCmptDebugInfo> m_ECSInfo = new List<ECSCmptDebugInfo>();
|
||||
public ECSCmptDebugInfo AddDebugCmpt(string cmptName)
|
||||
{
|
||||
var cmptInfo = m_ECSInfo.Find((item) => { return item.m_name == cmptName; });
|
||||
if (cmptInfo == null)
|
||||
{
|
||||
cmptInfo = new ECSCmptDebugInfo();
|
||||
cmptInfo.m_name = cmptName;
|
||||
m_ECSInfo.Add(cmptInfo); ;
|
||||
}
|
||||
|
||||
return cmptInfo;
|
||||
}
|
||||
|
||||
public void RmvDebugCmpt(string cmptName)
|
||||
{
|
||||
m_ECSInfo.RemoveAll((item) => { return item.m_name == cmptName; });
|
||||
}
|
||||
|
||||
public void SetDebugInfo(string cmptName, string key, string val)
|
||||
{
|
||||
var cmptInfo = AddDebugCmpt(cmptName);
|
||||
var entry = cmptInfo.m_info.Find((t) => { return t.m_name == key; });
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new ECSCmptDebugKeyInfo();
|
||||
entry.m_name = key;
|
||||
cmptInfo.m_info.Add(entry);
|
||||
}
|
||||
|
||||
entry.val = val;
|
||||
}
|
||||
|
||||
public void RemoveAllDebugInfo(string cmpName)
|
||||
{
|
||||
var cmpInfo = m_ECSInfo.Find((item) => { return item.m_name == cmpName; });
|
||||
if (cmpInfo != null)
|
||||
{
|
||||
cmpInfo.m_info.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dc3e456c545c0c419624e068b9249dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
96
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs
Normal file
96
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class ECSEventCmpt : ECSComponent
|
||||
{
|
||||
private GameEvent _gameEvent;
|
||||
|
||||
#region AddEventListener
|
||||
public void AddEventListener<T>(int eventId, Action<T> action)
|
||||
{
|
||||
_gameEvent.AddEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U>(int eventId, Action<T, U> action)
|
||||
{
|
||||
_gameEvent.AddEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, W>(int eventId, Action<T, U, W> action)
|
||||
{
|
||||
_gameEvent.AddEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void AddEventListener(int eventId, Action action)
|
||||
{
|
||||
_gameEvent.AddEventListener(eventId, action);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoveEventListener
|
||||
public void RemoveEventListener<T>(int eventId, Action<T> action)
|
||||
{
|
||||
_gameEvent.RemoveEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U>(int eventId, Action<T, U> action)
|
||||
{
|
||||
_gameEvent.RemoveEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, W>(int eventId, Action<T, U, W> action)
|
||||
{
|
||||
_gameEvent.RemoveEventListener(eventId, action);
|
||||
}
|
||||
|
||||
public void RemoveEventListener(int eventId, Action action)
|
||||
{
|
||||
_gameEvent.RemoveEventListener(eventId, action);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
public void Send<T>(int eventId, T info)
|
||||
{
|
||||
_gameEvent.Send(eventId, info);
|
||||
}
|
||||
|
||||
public void Send<T, U>(int eventId, T info, U info2)
|
||||
{
|
||||
_gameEvent.Send(eventId, info, info2);
|
||||
}
|
||||
|
||||
public void Send<T, U, W>(int eventId, T info, U info2, W info3)
|
||||
{
|
||||
_gameEvent.Send(eventId, info, info2, info3);
|
||||
}
|
||||
|
||||
public void Send(int eventId)
|
||||
{
|
||||
_gameEvent.Send(eventId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Clear
|
||||
public void Clear()
|
||||
{
|
||||
GameMemPool<GameEvent>.Free(_gameEvent);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
_gameEvent = GameMemPool<GameEvent>.Alloc();
|
||||
Entity.Event = this;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af343da6b3090a24b92fc12aaa638411
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
112
Assets/TEngine/Runtime/ECS/ECSObject.cs
Normal file
112
Assets/TEngine/Runtime/ECS/ECSObject.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS架构基类Object
|
||||
/// </summary>
|
||||
public class ECSObject
|
||||
{
|
||||
internal int HashCode;
|
||||
|
||||
internal ECSSystem System;
|
||||
|
||||
public ECSObject()
|
||||
{
|
||||
HashCode = GetType().GetHashCode();
|
||||
}
|
||||
|
||||
public virtual void Awake() { }
|
||||
|
||||
public virtual void OnDestroy() { }
|
||||
|
||||
/// <summary>
|
||||
/// Remove The ECSEntity or Component And Throw the ECSObject to ArrayPool When AddComponent Or Create Can Use Again
|
||||
/// </summary>
|
||||
/// <param name="ecsObject"></param>
|
||||
/// <param name="reuse">此对象是否可以复用,复用会将对象丢入System对象池中 等待再次使用,如果是Entity对象,并且不复用的话,则把Entity所使用的组件也不复用</param>
|
||||
public static void Destroy(ECSObject ecsObject, bool reuse = true)
|
||||
{
|
||||
if (ecsObject is ECSComponent ecsComponent)
|
||||
{
|
||||
ecsComponent.Entity.Components.Remove(ecsComponent);
|
||||
if (ecsComponent is IUpdate update)
|
||||
{
|
||||
ecsComponent.Entity.Updates.Remove(update);
|
||||
}
|
||||
if (reuse)
|
||||
{
|
||||
ecsComponent.Entity.System.Push(ecsComponent);
|
||||
}
|
||||
ecsObject.OnDestroy();
|
||||
return;
|
||||
}
|
||||
else if (ecsObject is Entity entity)
|
||||
{
|
||||
entity.System.RemoveEntity(entity);
|
||||
entity.OnDestroy();
|
||||
while (entity.Components.Count > 0)
|
||||
{
|
||||
ECSComponent ecsComponentTemp = entity.Components[0];
|
||||
entity.Components.RemoveAt(0);
|
||||
ecsComponentTemp.OnDestroy();
|
||||
if (reuse)
|
||||
{
|
||||
entity.System.Push(ecsComponentTemp);
|
||||
}
|
||||
}
|
||||
entity.Updates.Clear();
|
||||
entity.CanUpdate = false;
|
||||
if (reuse)
|
||||
{
|
||||
entity.System.Push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T FindObjectOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var elements = System.Entities.ToArray();
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
if (elements[i].GetType() == type)
|
||||
{
|
||||
return elements[i] as T;
|
||||
}
|
||||
for (int n = 0; n < elements[i].Components.Count; n++)
|
||||
{
|
||||
if (elements[i].Components[n].GetType() == type)
|
||||
{
|
||||
return elements[i].Components[n] as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] FindObjectsOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var items = System.Entities.ToArray();
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
if (items[i].GetType() == type)
|
||||
{
|
||||
elements.Add(items[i] as T);
|
||||
}
|
||||
for (int n = 0; n < items[i].Components.Count; n++)
|
||||
{
|
||||
if (items[i].Components[n].GetType() == type)
|
||||
{
|
||||
elements.Add(items[i].Components[n] as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSObject.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSObject.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 003794832e9179348a633bdafe92ff3c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
233
Assets/TEngine/Runtime/ECS/ECSSystem.cs
Normal file
233
Assets/TEngine/Runtime/ECS/ECSSystem.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS系统 管理Entity、ECSComponent复用对象池
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ECSSystem : IDisposable
|
||||
{
|
||||
private static ECSSystem instance = new ECSSystem();
|
||||
public static ECSSystem Instance => instance;
|
||||
private readonly Dictionary<int,Stack<ECSObject>> m_ObjectPool = new Dictionary<int, Stack<ECSObject>>();
|
||||
internal readonly ArrayPool<Entity> Entities = new ArrayPool<Entity>();
|
||||
private bool m_IsDispose = false;
|
||||
|
||||
public void AddEntity(Entity entity)
|
||||
{
|
||||
entity.System = this;
|
||||
entity.Awake();
|
||||
Entities.Add(entity);
|
||||
}
|
||||
|
||||
public void RemoveEntity(Entity entity)
|
||||
{
|
||||
Entities.Remove(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Object From ECSSystem
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T Get<T>() where T : ECSObject, new()
|
||||
{
|
||||
int type = typeof(T).GetHashCode();
|
||||
if (m_ObjectPool.TryGetValue(type,out Stack<ECSObject> stack))
|
||||
{
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
return (T) stack.Pop();
|
||||
}
|
||||
goto Instantiate;
|
||||
}
|
||||
stack = new Stack<ECSObject>();
|
||||
m_ObjectPool.Add(type,stack);
|
||||
Instantiate: T ecsObject = new T();
|
||||
return ecsObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Push Object To ECSSystem
|
||||
/// </summary>
|
||||
public void Push(ECSObject ecsObject)
|
||||
{
|
||||
int type = ecsObject.HashCode;
|
||||
|
||||
if (m_ObjectPool.TryGetValue(type,out Stack<ECSObject> stack))
|
||||
{
|
||||
stack.Push(ecsObject);
|
||||
return;
|
||||
}
|
||||
stack = new Stack<ECSObject>();
|
||||
m_ObjectPool.Add(type,stack);
|
||||
stack.Push(ecsObject);
|
||||
}
|
||||
|
||||
public T Create<T>() where T : Entity, new()
|
||||
{
|
||||
T entity = Get<T>();
|
||||
AddEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public T Create<T>(T entity) where T : Entity, new()
|
||||
{
|
||||
AddEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新ECS系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void Update(bool worker = false)
|
||||
{
|
||||
Run(worker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新ECS物理系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void FixedUpdate(bool worker = false)
|
||||
{
|
||||
RunFixed(worker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行ECS系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void Run(bool worker = false)
|
||||
{
|
||||
int count = Entities.Count;
|
||||
if (!worker)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanUpdate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Entities[i].Execute();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parallel.For(0, count, i =>
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Entities[i].Execute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void RunFixed(bool worker = false)
|
||||
{
|
||||
int count = Entities.Count;
|
||||
if (!worker)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanFixedUpdate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Entities[i].FixedUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parallel.For(0, count, i =>
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanFixedUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Entities[i].FixedUpdate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_IsDispose)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_IsDispose = true;
|
||||
}
|
||||
|
||||
public T FindObjectOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var elements = Entities.ToArray();
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
if (elements[i].GetType() == type)
|
||||
{
|
||||
return elements[i] as T;
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements[i].Components.Count; j++)
|
||||
{
|
||||
if (elements[i].Components[j].GetType() == type)
|
||||
{
|
||||
return elements[i].Components[j] as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] FindObjectsOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var entities = Entities.ToArray();
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < entities.Length; i++)
|
||||
{
|
||||
if (entities[i].GetType() == type)
|
||||
{
|
||||
elements.Add(entities[i] as T);
|
||||
}
|
||||
for (int n = 0; n < entities[i].Components.Count; n++)
|
||||
{
|
||||
if (entities[i].Components[n].GetType() == type)
|
||||
{
|
||||
elements.Add(entities[i].Components[n] as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSSystem.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2bd4af51a518164c8da0dff296b2bb1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
273
Assets/TEngine/Runtime/ECS/Entity.cs
Normal file
273
Assets/TEngine/Runtime/ECS/Entity.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class Entity : ECSObject, IIndex
|
||||
{
|
||||
[SerializeField]
|
||||
internal List<ECSComponent> Components = new List<ECSComponent>();
|
||||
internal List<IUpdate> Updates = new List<IUpdate>();
|
||||
internal List<IFixedUpdate> FixedUpdates = new List<IFixedUpdate>();
|
||||
internal bool InActive;
|
||||
internal bool CanUpdate;
|
||||
internal bool CanFixedUpdate;
|
||||
public int Index { get; set; } = -1;
|
||||
public ECSEventCmpt Event { get; set; }
|
||||
public Entity()
|
||||
{
|
||||
InActive = true;
|
||||
System = ECSSystem.Instance;
|
||||
}
|
||||
|
||||
~Entity()
|
||||
{
|
||||
InActive = false;
|
||||
}
|
||||
|
||||
internal void Execute()
|
||||
{
|
||||
for (int i = 0; i < Updates.Count; i++)
|
||||
{
|
||||
Updates[i].Update();
|
||||
}
|
||||
}
|
||||
|
||||
internal void FixedUpdate()
|
||||
{
|
||||
for (int i = 0; i < FixedUpdates.Count; i++)
|
||||
{
|
||||
FixedUpdates[i].FixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvComponent<T>() where T : ECSComponent, new()
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T component)
|
||||
{
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Remove(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Remove(fixedUpdate);
|
||||
}
|
||||
|
||||
System.Push(component);
|
||||
|
||||
CanUpdate = Updates.Count > 0;
|
||||
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void RmvComponent(Type componentType)
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i].GetType() == componentType)
|
||||
{
|
||||
|
||||
if (componentType is IUpdate update)
|
||||
{
|
||||
Updates.Remove(update);
|
||||
|
||||
CanUpdate = Updates.Count > 0;
|
||||
}
|
||||
else if (componentType is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Remove(fixedUpdate);
|
||||
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
}
|
||||
//if (componentType is ECSComponent component)
|
||||
//{
|
||||
// System.Push(component);
|
||||
//}
|
||||
}
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
public T AddComponent<T>() where T : ECSComponent, new()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
T component = System.Get<T>();
|
||||
component.Entity = this;
|
||||
component.System = System;
|
||||
Components.Add(component);
|
||||
component.Awake();
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Add(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Add(fixedUpdate);
|
||||
}
|
||||
CanUpdate = Updates.Count > 0;
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
return component;
|
||||
}
|
||||
|
||||
public ECSComponent AddComponent(ECSComponent component)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
component.Entity = this;
|
||||
component.System = System;
|
||||
Components.Add(component);
|
||||
component.Awake();
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Add(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Add(fixedUpdate);
|
||||
}
|
||||
CanUpdate = Updates.Count > 0;
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
return component;
|
||||
}
|
||||
|
||||
public T GetComponent<T>() where T : ECSComponent
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ECSComponent GetComponent(Type componentType)
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i].GetType() == componentType)
|
||||
{
|
||||
return Components[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] GetComponents<T>() where T : ECSComponent
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
elements.Add(type);
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
public List<T> GetComponentsList<T>() where T : ECSComponent
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
elements.Add(type);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public ECSComponent[] GetComponents(Type comType)
|
||||
{
|
||||
List<ECSComponent> elements = new List<ECSComponent>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
{
|
||||
if (Components[i].GetType() == comType)
|
||||
{
|
||||
elements.Add(Components[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string str = "[";
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
str += Components[i].GetType().Name + ",";
|
||||
}
|
||||
str = str.TrimEnd(',');
|
||||
str += "]";
|
||||
return $"{GetType().Name} Components: {str}";
|
||||
}
|
||||
|
||||
|
||||
public void CheckDebugInfo(GameObject gameObject)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var debugBehaviour = UnityUtil.AddMonoBehaviour<ECSDebugBehaviour>(gameObject);
|
||||
debugBehaviour.m_ECSInfo.Clear();
|
||||
for (int i = 0; i < this.Components.Count; i++)
|
||||
{
|
||||
var component = this.Components[i];
|
||||
var cmptName = component.GetType().Name;
|
||||
debugBehaviour.SetDebugInfo(cmptName, "", "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
public void CheckDebugInfo()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
//var actorEntity = this as Entity;
|
||||
|
||||
//if (actorEntity == null)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (actorEntity.gameObject == null)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//var debugBehaviour = UnityUtil.AddMonoBehaviour<ECSDebugBehaviour>(actorEntity.gameObject);
|
||||
//debugBehaviour.m_ECSInfo.Clear();
|
||||
//for (int i = 0; i < this.Components.Count; i++)
|
||||
//{
|
||||
// var component = this.Components[i];
|
||||
// var cmptName = component.GetType().Name;
|
||||
// debugBehaviour.SetDebugInfo(cmptName, "", "");
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Entity.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Entity.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f5bc14d7a4aee34695c39d02ae1c71f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
32
Assets/TEngine/Runtime/ECS/HotfixComponent.cs
Normal file
32
Assets/TEngine/Runtime/ECS/HotfixComponent.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class HotfixComponent : ECSComponent,IUpdate
|
||||
{
|
||||
public object[] Values;
|
||||
public Action OnAwake, OnUpdate, OnDestroyExt;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
OnAwake?.Invoke();
|
||||
}
|
||||
|
||||
void IUpdate.Update()
|
||||
{
|
||||
OnUpdate?.Invoke();
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
OnDestroyExt?.Invoke();
|
||||
OnAwake = null;
|
||||
OnUpdate = null;
|
||||
OnDestroyExt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/HotfixComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/HotfixComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0ac8b7fabe2bae499a568608191eb57
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
10
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs
Normal file
10
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS组件更新接口(减少组件for循环开销)
|
||||
/// </summary>
|
||||
public interface IFixedUpdate
|
||||
{
|
||||
void FixedUpdate();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fb8a7b6d364a024e8a49a0a731de201
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
10
Assets/TEngine/Runtime/ECS/IUpdate.cs
Normal file
10
Assets/TEngine/Runtime/ECS/IUpdate.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS组件更新接口(减少组件for循环开销)
|
||||
/// </summary>
|
||||
public interface IUpdate
|
||||
{
|
||||
void Update();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/IUpdate.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/IUpdate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7918afae3870234391c6e6f521e9ca7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/TEngine/Runtime/ECS/UpdateComponent.cs
Normal file
13
Assets/TEngine/Runtime/ECS/UpdateComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 热更层由此组件进行更新(ILRuntime不支持多继承, 接口继承)
|
||||
/// </summary>
|
||||
public class UpdateComponent :ECSComponent, IUpdate
|
||||
{
|
||||
public virtual void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/UpdateComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/UpdateComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02463b27b6971f0408bb517c32c66553
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user