using System; using System.Collections.Generic; using UnityEngine; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using BITKit.Core.Entites; using Cysharp.Threading.Tasks; using UnityEngine.UIElements; // ReSharper disable RedundantTypeArgumentsOfMethod namespace BITKit.Entities { public class Entity : MonoBehaviour, IEntity { private readonly GenericEvent genericEvent = new(); private readonly Processor processor = new(); public IEntityComponent[] entityComponents { get; set; } public ulong Id { get; private set; } public CancellationToken CancellationToken => _cancellationToken; Core.Entites.IEntityComponent[] Core.Entites.IEntity.Components => _components; bool Core.Entites.IEntity.RegisterComponent(T component) { throw new InvalidOperationException("Unity Entity can't register component"); } IServiceProvider Core.Entites.IEntity.ServiceProvider=> throw new InvalidOperationException("Unity Entity can't register component"); public void Inject(object obj) { foreach (var fieldInfo in obj .GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(fieldInfo=>fieldInfo.GetCustomAttribute() is not null)) { var type = fieldInfo.FieldType; var attribute = fieldInfo.GetCustomAttribute(); var currentValue = fieldInfo.GetValue(obj); try { switch (currentValue) { case null: break; case Core.Entites.IEntityComponent entityComponent: if(entityComponent.Entity.Id == Id) continue; break; case MonoBehaviour { destroyCancellationToken: { IsCancellationRequested: false } }: continue; case not null: continue; } } catch (MissingReferenceException){} if(genericEvent.TryGetObjectDirect(type.FullName,out var value)) { fieldInfo.SetValue(obj,value); } else if(attribute?.CanBeNull is false) { BIT4Log.Warning($"{name}未找到{type.FullName}"); BIT4Log.Warning(genericEvent.GetDiagnostics()); } } } private CancellationToken _cancellationToken; private bool isInitialized; private Core.Entites.IEntityComponent[] _components => entityComponents.Cast().ToArray(); private void Awake() { Id = (ulong)Guid.NewGuid().GetHashCode(); _cancellationToken = gameObject.GetCancellationTokenOnDestroy(); Set(_cancellationToken); entityComponents = GetComponentsInChildren(true).Distinct().ToArray(); UnityEntitiesService.Register(this); } private void Start() { try { var monoBehaviours = GetComponentsInChildren(true); foreach (var x in monoBehaviours) { foreach (var att in x //.GetCustomAttributes() .GetType() //.GetCustomAttributes() .GetCustomAttributes() .OfType() ) { genericEvent.Set(att.Type,x); genericEvent.Set(att.Type.FullName, x); genericEvent.SetDirect(att.Type.FullName,x); } genericEvent.Set(x.GetType(),x); } foreach (var x in monoBehaviours) { Inject(x); } entityComponents.ForEach(x => x.Initialize(this)); entityComponents.ForEach(x => x.OnAwake()); entityComponents.ForEach(x => x.OnStart()); isInitialized = true; } catch (Exception e) { Debug.LogWarning(name); Debug.LogException(e); } } private void OnDestroy() { if (isInitialized) { entityComponents.ForEach(x => x.OnDestroyComponent()); } UnityEntitiesService.UnRegister(this); } private void Update() { entityComponents.ForEach(x => x.OnUpdate(Time.deltaTime)); } private void FixedUpdate() { entityComponents.ForEach(x => x.OnFixedUpdate(Time.fixedDeltaTime)); } private void LateUpdate() { entityComponents.ForEach(x => x.OnLateUpdate(Time.deltaTime)); } public void AddListener(Action action) => genericEvent.AddListener(action); public void Invoke(T value) => genericEvent.Invoke(value); public void RemoveListener(Action action) => genericEvent.RemoveListener(action); public void AddListener(string key, Action action) => genericEvent.AddListener(key, action); public void Invoke(string key, T value) => genericEvent.Invoke(key, value); public void Invoke() where T : new() => genericEvent.Invoke(); public void RemoveListener(string key, Action action) => genericEvent.RemoveListener(key, action); public T Get(string key = Constant.System.Internal) { var value = genericEvent.Get(key); if (value is not null || !typeof(T).IsAssignableFrom(typeof(Component))) return value; if (!TryGetComponent(out var component)) return default(T); Set(component); return component; } public void Set(T value) => genericEvent.Set(value); public void Set(string key = Constant.System.Internal, T value = default) => genericEvent.Set(key, value); public T GetContext(T value = default) => processor.GetContext(value); public void AddProcessor(Func func) => processor.AddProcessor(func); public void RemoveProcessor(Func func) => processor.RemoveProcessor(func); public T GetContext(string key, T value) => processor.GetContext(value); public void AddProcessor(string key, Func func) => processor.AddProcessor(key, func); public void RemoveProcessor(string key, Func func) => processor.RemoveProcessor(key, func); public void RegisterCallback(T t) { var value = GetCallbacks() as List; value!.Add(t); } public void UnRegisterCallback(T t) { var value = GetCallbacks() as List; value!.Remove(t); } public IEnumerable GetCallbacks() { var value = Get>(nameof(ICallback)).CreateOrAddIfEmety(() => { List newList = new(); Set>(nameof(ICallback), newList); return newList; }); if (value is null) { Debug.LogWarning("List is Null"); } return value; } } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(Entity))] public class EntityInspector : BITInspector { public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); CreateSubTitle("Identity"); var idLabel = root.Create