using System; using System.Collections.Generic; using Fort23.UTool; using UnityEngine; using UnityEngine.Pool; namespace Fort23.Core { public class Scene : Entity { public new Entity Domain { get => this.domain; set => this.domain = value; } public Scene() { this.IsRegister = true; this.Domain = this; } } public partial class Entity : CObject { private static readonly Pool> _dictPool = new Pool>(); private static readonly Pool> _childrenPool = new Pool>(); public long InstanceID { get; protected set; } public bool IsDisposed => this.InstanceID == 0; public long ID { get; set; } private bool _isFromPool { get; set; } private bool _isComponent { get; set; } private bool _isRegister; protected bool IsRegister { get => _isRegister; set { _isRegister = value; EventSystem.Instance.RegisterSystem(this, value); } } protected static Entity Create(Type type, bool isFromPool) { Entity component; if (isFromPool) { component = (Entity) CObjectPool.Instance.Fetch(type); } else { component = (Entity) Activator.CreateInstance(type); } return component; } public override void Dispose() { if (this.IsDisposed) { return; } // 清理Component if (this._components != null) { List keys = new List(); foreach (var componentsKey in _components.Keys) { keys.Add(componentsKey); } for (var i = 0; i < keys.Count; i++) { _components[keys[i]].Dispose(); } // foreach (KeyValuePair kv in this._components) // { // kv.Value.Dispose(); // } this._components.Clear(); _dictPool.Recycle(this._components); this._components = null; } // 清理Children if (this._children != null) { List keys = new List(); foreach (var childrenKey in _children.Keys) { keys.Add(childrenKey); } for (var i = 0; i < keys.Count; i++) { _children[keys[i]].Dispose(); } // foreach (Entity child in this._children.Values) // { // child.Dispose(); // } if (_children != null) { this._children.Clear(); _childrenPool.Recycle(this._children); this._children = null; } } // 触发Destroy事件 EventSystem.Instance.Destroy(this); this.domain = null; if (this.parent != null && !this.parent.IsDisposed) { if (this._isComponent) { this.parent.RemoveComponent(this); } else { this.parent.RemoveChild(this); } } this.parent = null; if (this._isFromPool) { CObjectPool.Instance.Recycle(this); } else { base.Dispose(); } this.InstanceID = 0; this.IsRegister = false; } public override void ActiveObj() { } public override void DormancyObj() { } public virtual bool IsUpdate() { return true; } private Dictionary _components; public Dictionary Components { get { if (this._components == null) { this._components = _dictPool.Fetch(); } return this._components; } } protected Entity parent; // 可以改变parent,但是不能设置为null(只能通过调用dispose重置为null) public Entity Parent { get => this.parent; set { if (value == null) { // throw new Exception($"cant set parent null: {this.GetType().Name}"); LogTool.Exception(new Exception($"cant set parent null: {this.GetType().Name}")); } if (value == this) { LogTool.Exception(new Exception($"cant set parent self: {this.GetType().Name}")); } if (this.parent != null) // 之前有parent { // parent相同,不设置 if (this.parent == value) { LogTool.Exception(new Exception($"重复设置了Parent: {this.GetType().Name} parent: {this.parent.GetType().Name}")); } this.parent.RemoveChild(this); } this.parent = value; this.parent.AddChild(this); this._isComponent = false; this.Domain = this.parent.domain; } } // 该方法只能在AddComponent中调用,其他人不允许调用 private Entity ComponentParent { set { if (this.parent != null) { LogTool.Exception(new Exception($"Component parent is not null: {this.GetType().Name}")); } this.parent = value; this._isComponent = true; this.Domain = this.parent.domain; } } private Dictionary _children; public Dictionary Children { get { if (this._children == null) { this._children = _childrenPool.Fetch(); } return this._children; } } protected Entity domain; /// /// 域,数据树的root /// /// public Entity Domain { get { return this.domain; } private set { if (value == null) { LogTool.Exception(new Exception($"domain cant set null: {this.GetType().Name}")); } if (this.domain == value) { return; } Entity preDomain = this.domain; this.domain = value; if (preDomain == null) { this.InstanceID = IdGenerater.GenerateId(); this.IsRegister = true; } // 递归设置孩子的Domain if (this._children != null) { foreach (Entity entity in this._children.Values) { entity.Domain = this.domain; } } if (this._components != null) { foreach (Entity component in this._components.Values) { component.Domain = this.domain; } } } } #region 获取组件(包含获取children的) public K GetChild(long id) where K : Entity { if (this._children == null) { return null; } this._children.TryGetValue(id, out Entity child); return child as K; } public virtual K GetComponent() where K : Entity { if (this._components == null) { return null; } Entity component; if (!this._components.TryGetValue(typeof(K), out component)) { return default; } return (K) component; } public virtual K[] GetComponentAll() where K : Entity { if (this._components == null) { return null; } Entity component; List allValue = ListPool.Get(); foreach (var VARIABLE in _components.Values) { if (VARIABLE is K) { allValue.Add(VARIABLE as K); } } K[] array = allValue.ToArray(); ListPool.Release(allValue); return array; } public virtual Entity GetComponent(Type type) { if (this._components == null) { return null; } Entity component; if (!this._components.TryGetValue(type, out component)) { return null; } return component; } #endregion #region 添加组件 public Entity AddComponent(Entity component) { Type type = component.GetType(); if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } component.ComponentParent = this; this.AddToComponent(type, component); return component; } public Entity AddComponent(Type type, bool isFromPool = false) { if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } Entity component = Create(type, isFromPool); component.ID = this.ID; component.ComponentParent = this; EventSystem.Instance.Awake(component, null); this.AddToComponent(type, component); return component; } public K AddComponent(bool isFromPool = false) where K : Entity, new() { Type type = typeof(K); if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } // return default; Entity component = Create(type, isFromPool); component.ID = this.ID; component.ComponentParent = this; EventSystem.Instance.Awake(component, null); this.AddToComponent(type, component); return component as K; } public K AddComponent(P1 p1, bool isFromPool = false) where K : Entity, new() { Type type = typeof(K); if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } Entity component = Create(type, isFromPool); component.ID = this.ID; component.ComponentParent = this; EventSystem.Instance.Awake(component, new object[] {p1}); this.AddToComponent(type, component); return component as K; } public K AddComponent(P1 p1, P2 p2, bool isFromPool = false) where K : Entity, new() { Type type = typeof(K); if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } Entity component = Create(type, isFromPool); component.ID = this.ID; component.ComponentParent = this; EventSystem.Instance.Awake(component, new object[] {p1, p2}); this.AddToComponent(type, component); return component as K; } public K AddComponent(P1 p1, P2 p2, P3 p3, bool isFromPool = false) where K : Entity, new() { Type type = typeof(K); if (this._components != null && this._components.ContainsKey(type)) { LogTool.Exception(new Exception($"entity already has component: {type.FullName}")); } Entity component = Create(type, isFromPool); component.ID = this.ID; component.ComponentParent = this; EventSystem.Instance.Awake(component, new object[] {p1, p2, p3}); this.AddToComponent(type, component); return component as K; } #endregion #region 移除组件 public void RemoveComponent() where K : Entity { if (this._components == null) { return; } Type type = typeof(K); Entity c = this.GetComponent(type); if (c == null) { return; } this.RemoveFromComponent(type, c); c.Dispose(); } public void RemoveComponent(Entity component) { if (this._components == null) { return; } Type type = component.GetType(); Entity c = this.GetComponent(component.GetType()); if (c == null) { return; } this.RemoveFromComponent(type, c); c.Dispose(); } public void RemoveComponent(Type type) { Entity c = this.GetComponent(type); if (c == null) { return; } RemoveFromComponent(type, c); c.Dispose(); } #endregion #region 添加组件为child public T AddChild(bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, null); return component; } public T AddChild(A a, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a}); return component; } public T AddChild(A a, B b, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b}); return component; } public T AddChild(A a, B b, C c, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b, c}); return component; } public T AddChild(A a, B b, C c, D d, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b, c, d}); return component; } public T AddChild(A a, B b, C c, D d, E e, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = IdGenerater.GenerateId(); component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b, c, d, e}); return component; } public T AddChildWithId(long id, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = id; component.Parent = this; EventSystem.Instance.Awake(component, null); return component; } public T AddChildWithId(long id, A a, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = id; component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a}); return component; } public T AddChildWithId(long id, A a, B b, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = id; component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b}); return component; } public T AddChildWithId(long id, A a, B b, C c, bool isFromPool = false) where T : Entity { Type type = typeof(T); T component = (T) Entity.Create(type, isFromPool); component.ID = id; component.Parent = this; EventSystem.Instance.Awake(component, new object[] {a, b, c}); return component; } #endregion #region 私有方法,增删组件和增删child private void AddChild(Entity entity) { this.Children.Add(entity.ID, entity); } private void RemoveChild(Entity entity) { if (this._children == null) { return; } this._children.Remove(entity.ID); if (this._children.Count == 0) { _childrenPool.Recycle(this._children); this._children = null; } } private void AddToComponent(Type type, Entity component) { if (this._components == null) { this._components = _dictPool.Fetch(); } this._components.Add(type, component); } private void RemoveFromComponent(Type type, Entity component) { if (this._components == null) { return; } this._components.Remove(type); if (this._components.Count == 0 && this._isFromPool) { _dictPool.Recycle(this._components); this._components = null; } } #endregion } public class Pool where T : class, new() { private readonly Queue _pool = new Queue(); public T Fetch() { if (_pool.Count == 0) { return new T(); } return _pool.Dequeue(); } public void Recycle(T t) { _pool.Enqueue(t); } public void Clear() { this._pool.Clear(); } } }