BITKit/Src/Unity/Scripts/Entity/Core/Entity.cs

234 lines
8.3 KiB
C#
Raw Normal View History

2023-06-05 19:57:17 +08:00
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
2023-09-01 14:35:05 +08:00
using System.Reflection;
2023-10-06 23:43:19 +08:00
using System.Text;
2023-09-01 14:35:05 +08:00
using System.Threading;
2023-11-06 01:17:23 +08:00
using BITKit.Entities;
2023-09-01 14:35:05 +08:00
using Cysharp.Threading.Tasks;
2024-03-31 23:31:00 +08:00
using UnityEngine.Profiling;
2023-06-05 19:57:17 +08:00
using UnityEngine.UIElements;
2023-08-23 01:59:26 +08:00
// ReSharper disable RedundantTypeArgumentsOfMethod
2023-06-05 19:57:17 +08:00
namespace BITKit.Entities
{
2024-03-31 23:31:00 +08:00
[CustomType(typeof(IUnityEntity))]
[CustomType(typeof(IEntity))]
2023-11-06 01:17:23 +08:00
public class Entity : MonoBehaviour, IUnityEntity
2023-06-05 19:57:17 +08:00
{
2023-06-29 14:57:11 +08:00
private readonly GenericEvent genericEvent = new();
2024-03-31 23:31:00 +08:00
public ulong Id { get; set; }
2023-11-06 01:17:23 +08:00
public CancellationToken CancellationToken { get; private set; }
public IEntityBehavior[] Behaviors { get;private set; }
public IEntityComponent[] Components => Behaviors.Cast<IEntityComponent>().ToArray();
2023-11-30 00:25:43 +08:00
private bool _initialized;
2023-11-06 01:17:23 +08:00
bool Entities.IEntity.RegisterComponent<T>(T component)
2023-10-06 23:43:19 +08:00
{
throw new InvalidOperationException("Unity Entity can't register component");
}
2023-11-06 01:17:23 +08:00
IServiceProvider Entities.IEntity.ServiceProvider=> throw new InvalidOperationException("Unity Entity can't register component");
2023-10-24 23:38:22 +08:00
public void Inject(object obj)
{
foreach (var fieldInfo in obj
.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
2024-03-31 23:31:00 +08:00
.Where(fieldInfo=>fieldInfo.GetCustomAttribute<InjectAttribute>(true) is not null))
2023-10-24 23:38:22 +08:00
{
var type = fieldInfo.FieldType;
var attribute = fieldInfo.GetCustomAttribute<InjectAttribute>();
var currentValue = fieldInfo.GetValue(obj);
try
{
switch (currentValue)
{
case null:
break;
2023-11-06 01:17:23 +08:00
case Entities.IEntityComponent entityComponent:
2023-10-24 23:38:22 +08:00
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)
{
2023-11-06 01:17:23 +08:00
BIT4Log.Warning<Entity>($"{name}未找到{obj.GetType().Name}需要的{type.FullName}");
//BIT4Log.Warning<Entity>(genericEvent.GetDiagnostics());
2023-10-24 23:38:22 +08:00
}
}
}
2023-10-06 23:43:19 +08:00
2023-11-06 01:17:23 +08:00
public void AddService<T>(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);
}
2023-08-23 01:59:26 +08:00
private bool isInitialized;
2024-03-31 23:31:00 +08:00
public void WaitForInitializationComplete()
{
if (isInitialized) return;
Start();
isInitialized = true;
}
2023-08-23 01:59:26 +08:00
private void Awake()
2023-06-05 19:57:17 +08:00
{
2024-03-31 23:31:00 +08:00
if (Id.IsDefault())
Id = (ulong)Guid.NewGuid().GetHashCode();
2023-11-06 01:17:23 +08:00
CancellationToken = gameObject.GetCancellationTokenOnDestroy();
Set(CancellationToken);
2023-10-06 23:43:19 +08:00
}
2024-03-31 23:31:00 +08:00
2023-10-06 23:43:19 +08:00
private void Start()
{
2024-03-31 23:31:00 +08:00
if (isInitialized) return;
2023-10-24 23:38:22 +08:00
try
2023-09-01 14:35:05 +08:00
{
2024-03-31 23:31:00 +08:00
AddService<IEntity>(this);
AddService<Entity>(this);
AddService<IUnityEntity>(this);
Behaviors = GetComponentsInChildren<IEntityBehavior>(true).Distinct().ToArray();
2023-10-24 23:38:22 +08:00
var monoBehaviours = GetComponentsInChildren<MonoBehaviour>(true);
2023-11-06 01:17:23 +08:00
Behaviors.ForEach(x => x.Initialize(this));
2023-10-24 23:38:22 +08:00
foreach (var x in monoBehaviours)
2023-09-01 14:35:05 +08:00
{
2023-10-24 23:38:22 +08:00
foreach (var att in x
//.GetCustomAttributes<CustomTypeAttribute>()
.GetType()
//.GetCustomAttributes<CustomTypeAttribute>()
.GetCustomAttributes()
.OfType<CustomTypeAttribute>()
)
2023-10-06 23:43:19 +08:00
{
2024-03-31 23:31:00 +08:00
AddService(att.Type, x);
if (att.AsGlobal)
DI.Register(att.Type, x);
2023-10-06 23:43:19 +08:00
}
2024-03-31 23:31:00 +08:00
2023-10-24 23:38:22 +08:00
genericEvent.Set(x.GetType(),x);
2023-09-01 14:35:05 +08:00
}
2023-10-24 23:38:22 +08:00
foreach (var x in monoBehaviours)
{
Inject(x);
}
2023-11-06 01:17:23 +08:00
2023-10-06 23:43:19 +08:00
2023-11-06 01:17:23 +08:00
Behaviors.ForEach(x => x.OnAwake());
Behaviors.ForEach(x => x.OnStart());
2023-10-24 23:38:22 +08:00
isInitialized = true;
}
catch (Exception e)
{
Debug.LogWarning(name);
Debug.LogException(e);
}
2023-11-30 00:25:43 +08:00
UnityEntitiesService.Register(this);
destroyCancellationToken.Register(() => UnityEntitiesService.UnRegister(this));
_initialized = true;
2023-06-05 19:57:17 +08:00
}
2023-11-30 00:25:43 +08:00
2023-08-23 01:59:26 +08:00
private void OnDestroy()
2023-06-05 19:57:17 +08:00
{
2023-11-30 00:25:43 +08:00
if (!_initialized) return;
foreach (var x in Behaviors)
2023-08-23 01:59:26 +08:00
{
2023-11-30 00:25:43 +08:00
x.OnDestroyComponent();
2023-08-23 01:59:26 +08:00
}
2023-06-05 19:57:17 +08:00
}
2023-11-30 00:25:43 +08:00
2023-08-23 01:59:26 +08:00
private void Update()
2023-06-05 19:57:17 +08:00
{
2024-03-31 23:31:00 +08:00
var deltaTime = Time.fixedDeltaTime;
2023-11-30 00:25:43 +08:00
foreach (var x in Behaviors)
{
2024-03-31 23:31:00 +08:00
x.OnUpdate(deltaTime);
2023-11-30 00:25:43 +08:00
}
2023-06-05 19:57:17 +08:00
}
2023-08-23 01:59:26 +08:00
private void FixedUpdate()
2023-06-05 19:57:17 +08:00
{
2024-03-31 23:31:00 +08:00
var deltaTime = Time.fixedDeltaTime;
2023-11-30 00:25:43 +08:00
foreach (var x in Behaviors)
{
2024-03-31 23:31:00 +08:00
x.OnFixedUpdate(deltaTime);
2023-11-30 00:25:43 +08:00
}
2023-06-05 19:57:17 +08:00
}
2023-08-23 01:59:26 +08:00
private void LateUpdate()
2023-06-05 19:57:17 +08:00
{
2024-03-31 23:31:00 +08:00
var deltaTime = Time.fixedDeltaTime;
2023-11-30 00:25:43 +08:00
foreach (var x in Behaviors)
{
2024-03-31 23:31:00 +08:00
x.OnLateUpdate(deltaTime);
2023-11-30 00:25:43 +08:00
}
2023-06-05 19:57:17 +08:00
}
public void AddListener<T>(Action<T> action) => genericEvent.AddListener<T>(action);
public void Invoke<T>(T value) => genericEvent.Invoke<T>(value);
public void RemoveListener<T>(Action<T> action) => genericEvent.RemoveListener<T>(action);
public void AddListener<T>(string key, Action<T> action) => genericEvent.AddListener<T>(key, action);
public void Invoke<T>(string key, T value) => genericEvent.Invoke<T>(key, value);
public void Invoke<T>() where T : new() => genericEvent.Invoke<T>();
public void RemoveListener<T>(string key, Action<T> action) => genericEvent.RemoveListener<T>(key, action);
2023-11-15 23:55:06 +08:00
public void SetDirect(int key, object value)
{
genericEvent.SetDirect(key, value);
}
public void GetDirect(int key, out object value)
{
genericEvent.GetDirect(key, out value);
}
public void GetDirect<T>(int key, out T value)
{
genericEvent.GetDirect(key, out value);
}
2023-06-05 19:57:17 +08:00
public T Get<T>(string key = Constant.System.Internal)
{
var value = genericEvent.Get<T>(key);
2023-08-23 01:59:26 +08:00
if (value is not null || !typeof(T).IsAssignableFrom(typeof(Component))) return value;
if (!TryGetComponent<T>(out var component)) return default(T);
Set<T>(component);
return component;
2023-06-05 19:57:17 +08:00
}
public void Set<T>(T value) => genericEvent.Set<T>(value);
public void Set<T>(string key = Constant.System.Internal, T value = default) => genericEvent.Set<T>(key, value);
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(Entity))]
public class EntityInspector : BITInspector<Entity>
{
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
2023-08-23 01:59:26 +08:00
CreateSubTitle("Identity");
2023-06-05 19:57:17 +08:00
var idLabel = root.Create<Label>();
idLabel.text = agent.Id.ToString();
return root;
}
}
#endif
}