using System; using System.Collections.Generic; using UnityEngine; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using BITKit.Entities; using Cysharp.Threading.Tasks; using UnityEngine.UIElements; // ReSharper disable RedundantTypeArgumentsOfMethod namespace BITKit.Entities { public class Entity : MonoBehaviour, IUnityEntity { private readonly GenericEvent genericEvent = new(); public ulong Id { get; private set; } public CancellationToken CancellationToken { get; private set; } public IEntityBehavior[] Behaviors { get;private set; } public IEntityComponent[] Components => Behaviors.Cast().ToArray(); bool Entities.IEntity.RegisterComponent(T component) { throw new InvalidOperationException("Unity Entity can't register component"); } IServiceProvider Entities.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 Entities.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}未找到{obj.GetType().Name}需要的{type.FullName}"); //BIT4Log.Warning(genericEvent.GetDiagnostics()); } } } public void AddService(T service) { AddService(typeof(T),service); } public void AddService(object service) { AddService(service.GetType(),service); } public void AddService(Type type, object service) { genericEvent.Set(type,service); genericEvent.Set(type.FullName, service); genericEvent.SetDirect(type.FullName,service); } private bool isInitialized; private void Awake() { Id = (ulong)Guid.NewGuid().GetHashCode(); CancellationToken = gameObject.GetCancellationTokenOnDestroy(); Set(CancellationToken); Behaviors = GetComponentsInChildren(true).Distinct().ToArray(); UnityEntitiesService.Register(this); } private void Start() { try { var monoBehaviours = GetComponentsInChildren(true); Behaviors.ForEach(x => x.Initialize(this)); foreach (var x in monoBehaviours) { foreach (var att in x //.GetCustomAttributes() .GetType() //.GetCustomAttributes() .GetCustomAttributes() .OfType() ) { AddService(att.Type, x); } genericEvent.Set(x.GetType(),x); } foreach (var x in monoBehaviours) { Inject(x); } Behaviors.ForEach(x => x.OnAwake()); Behaviors.ForEach(x => x.OnStart()); isInitialized = true; } catch (Exception e) { Debug.LogWarning(name); Debug.LogException(e); } } private void OnDestroy() { if (isInitialized) { Behaviors.ForEach(x => x.OnDestroyComponent()); } UnityEntitiesService.UnRegister(this); } private void Update() { Behaviors.ForEach(x => x.OnUpdate(Time.deltaTime)); } private void FixedUpdate() { Behaviors.ForEach(x => x.OnFixedUpdate(Time.fixedDeltaTime)); } private void LateUpdate() { Behaviors.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); } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(Entity))] public class EntityInspector : BITInspector { public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); CreateSubTitle("Identity"); var idLabel = root.Create