1
This commit is contained in:
@@ -7,15 +7,20 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using BITKit.Entities;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.Profiling;
|
||||
using UnityEngine.UIElements;
|
||||
// ReSharper disable RedundantTypeArgumentsOfMethod
|
||||
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
[CustomType(typeof(IUnityEntity))]
|
||||
[CustomType(typeof(IEntity))]
|
||||
public class Entity : MonoBehaviour, IUnityEntity
|
||||
{
|
||||
private readonly GenericEvent genericEvent = new();
|
||||
public ulong Id { get; private set; }
|
||||
|
||||
|
||||
public ulong Id { get; set; }
|
||||
public CancellationToken CancellationToken { get; private set; }
|
||||
public IEntityBehavior[] Behaviors { get;private set; }
|
||||
public IEntityComponent[] Components => Behaviors.Cast<IEntityComponent>().ToArray();
|
||||
@@ -31,7 +36,7 @@ namespace BITKit.Entities
|
||||
foreach (var fieldInfo in obj
|
||||
.GetType()
|
||||
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(fieldInfo=>fieldInfo.GetCustomAttribute<InjectAttribute>() is not null))
|
||||
.Where(fieldInfo=>fieldInfo.GetCustomAttribute<InjectAttribute>(true) is not null))
|
||||
{
|
||||
var type = fieldInfo.FieldType;
|
||||
var attribute = fieldInfo.GetCustomAttribute<InjectAttribute>();
|
||||
@@ -83,19 +88,30 @@ namespace BITKit.Entities
|
||||
}
|
||||
|
||||
private bool isInitialized;
|
||||
|
||||
public void WaitForInitializationComplete()
|
||||
{
|
||||
if (isInitialized) return;
|
||||
Start();
|
||||
isInitialized = true;
|
||||
}
|
||||
private void Awake()
|
||||
{
|
||||
Id = (ulong)Guid.NewGuid().GetHashCode();
|
||||
if (Id.IsDefault())
|
||||
Id = (ulong)Guid.NewGuid().GetHashCode();
|
||||
CancellationToken = gameObject.GetCancellationTokenOnDestroy();
|
||||
Set(CancellationToken);
|
||||
Behaviors = GetComponentsInChildren<IEntityBehavior>(true).Distinct().ToArray();
|
||||
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (isInitialized) return;
|
||||
try
|
||||
{
|
||||
AddService<IEntity>(this);
|
||||
AddService<Entity>(this);
|
||||
AddService<IUnityEntity>(this);
|
||||
|
||||
Behaviors = GetComponentsInChildren<IEntityBehavior>(true).Distinct().ToArray();
|
||||
var monoBehaviours = GetComponentsInChildren<MonoBehaviour>(true);
|
||||
Behaviors.ForEach(x => x.Initialize(this));
|
||||
foreach (var x in monoBehaviours)
|
||||
@@ -108,8 +124,11 @@ namespace BITKit.Entities
|
||||
.OfType<CustomTypeAttribute>()
|
||||
)
|
||||
{
|
||||
AddService(att.Type, x);
|
||||
AddService(att.Type, x);
|
||||
if (att.AsGlobal)
|
||||
DI.Register(att.Type, x);
|
||||
}
|
||||
|
||||
genericEvent.Set(x.GetType(),x);
|
||||
}
|
||||
foreach (var x in monoBehaviours)
|
||||
@@ -143,23 +162,26 @@ namespace BITKit.Entities
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var deltaTime = Time.fixedDeltaTime;
|
||||
foreach (var x in Behaviors)
|
||||
{
|
||||
x.OnUpdate(Time.deltaTime);
|
||||
x.OnUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
private void FixedUpdate()
|
||||
{
|
||||
var deltaTime = Time.fixedDeltaTime;
|
||||
foreach (var x in Behaviors)
|
||||
{
|
||||
x.OnFixedUpdate(Time.fixedDeltaTime);
|
||||
x.OnFixedUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
private void LateUpdate()
|
||||
{
|
||||
var deltaTime = Time.fixedDeltaTime;
|
||||
foreach (var x in Behaviors)
|
||||
{
|
||||
x.OnLateUpdate(Time.deltaTime);
|
||||
x.OnLateUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
public void AddListener<T>(Action<T> action) => genericEvent.AddListener<T>(action);
|
||||
|
17
Src/Unity/Scripts/Entity/Core/EntityAddressableComponent.cs
Normal file
17
Src/Unity/Scripts/Entity/Core/EntityAddressableComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
[CustomType(typeof(IAddressable))]
|
||||
public class EntityAddressableComponent : MonoBehaviour,IAddressable
|
||||
{
|
||||
[SerializeField] private string addressablePath;
|
||||
[SerializeField] private ulong addressableId;
|
||||
|
||||
public string AddressablePath => addressablePath;
|
||||
public ulong AddressableId => addressableId;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22c8a583a4eb6504ab5a732954c0855c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using BITKit.Entities;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
73
Src/Unity/Scripts/Entity/Core/EntityBinaryHeader.cs
Normal file
73
Src/Unity/Scripts/Entity/Core/EntityBinaryHeader.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
[CustomType(typeof(IEntityBinaryHeader))]
|
||||
public class EntityBinaryHeader : EntityBehavior,IEntityBinaryHeader
|
||||
{
|
||||
public int Id => (int)Entity.Id;
|
||||
public IDictionary<int, IEntityBinaryComponent> ComponentDictionary { get; } =
|
||||
new Dictionary<int, IEntityBinaryComponent>();
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
foreach (var component in Entity.Components.OfType<IEntityBinaryComponent>())
|
||||
{
|
||||
ComponentDictionary.Add(component.Id, component);
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
//写入组件数量
|
||||
//写入组件ID
|
||||
//写入组件数据
|
||||
//写入组件数据长度
|
||||
var length = ComponentDictionary.Count;
|
||||
writer.Write(length);
|
||||
foreach (var component in ComponentDictionary.Values)
|
||||
{
|
||||
writer.Write(component.Id);
|
||||
}
|
||||
foreach (var component in ComponentDictionary.Values)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var binaryWriter = new BinaryWriter(ms);
|
||||
component.Serialize(binaryWriter);
|
||||
binaryWriter.Flush();
|
||||
ms.Flush();
|
||||
var bytes = ms.ToArray();
|
||||
writer.Write(bytes.Length);
|
||||
writer.Write(bytes);
|
||||
}
|
||||
}
|
||||
public void Deserialize(BinaryReader reader)
|
||||
{
|
||||
//BIT4Log.Log<EntityBinaryHeader>("源数据长度:"+reader.BaseStream.Length);
|
||||
//读取组件数量
|
||||
//读取组件ID
|
||||
//读取组件数据
|
||||
var count = reader.ReadInt32();
|
||||
//BIT4Log.Log<EntityBinaryHeader>($"count:{count}");
|
||||
var ids = new int[count];
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
ids[i] = reader.ReadInt32();
|
||||
}
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var length = reader.ReadInt32();
|
||||
var bytes = reader.ReadBytes(length);
|
||||
using var stream = new MemoryStream(bytes);
|
||||
using var binaryReader = new BinaryReader(stream);
|
||||
//BIT4Log.Log<EntityBinaryHeader>($"id:{id},length:{length},bytes:\n{JsonHelper.Get(bytes)}");
|
||||
ComponentDictionary[id].Deserialize(binaryReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Entity/Core/EntityBinaryHeader.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Core/EntityBinaryHeader.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ff33423878ac11439fbf15f38dbe628
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -4,21 +4,52 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
|
||||
public interface IEntityOverride
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否正在被覆盖
|
||||
/// </summary>
|
||||
bool IsOvering { get; }
|
||||
void AddOverride(object key);
|
||||
void RemoveOverride(object key);
|
||||
/// <summary>
|
||||
/// 当前对象,用于判断是否是自己的覆盖
|
||||
/// </summary>
|
||||
object CurrentObject { get; }
|
||||
/// <summary>
|
||||
/// 当开始覆盖或者结束覆盖时触发
|
||||
/// </summary>
|
||||
event Action<bool> OnOverride;
|
||||
/// <summary>
|
||||
/// 添加覆盖
|
||||
/// </summary>
|
||||
void AddOverride(object key,int priority=0);
|
||||
/// <summary>
|
||||
/// 移除覆盖
|
||||
/// </summary>
|
||||
void RemoveOverride(object key,int priority=0);
|
||||
|
||||
}
|
||||
[CustomType(typeof(IEntityOverride))]
|
||||
public class EntityOverride : EntityBehavior,IEntityOverride
|
||||
{
|
||||
[SerializeField,ReadOnly] private bool isOvering;
|
||||
[SerializeField, ReadOnly(HideLabel = true)] private string overrideKeys;
|
||||
public bool IsOvering => _allowOverrideHandle;
|
||||
public object CurrentObject => _prioritySelector.Current;
|
||||
private readonly ValidHandle _allowOverrideHandle = new();
|
||||
public void AddOverride(object key) => _allowOverrideHandle.AddElement(key);
|
||||
public void RemoveOverride(object key)=>_allowOverrideHandle.RemoveElement(key);
|
||||
|
||||
private readonly PrioritySelector<object> _prioritySelector = new();
|
||||
public void AddOverride(object key,int priority=0)
|
||||
{
|
||||
_prioritySelector.Set(priority,key);
|
||||
_allowOverrideHandle.AddElement(key);
|
||||
}
|
||||
public void RemoveOverride(object key,int priority=0)
|
||||
{
|
||||
_prioritySelector.Remove(priority);
|
||||
_allowOverrideHandle.RemoveElement(key);
|
||||
}
|
||||
|
||||
public event Action<bool> OnOverride;
|
||||
|
||||
public override void Initialize(IEntity entity)
|
||||
@@ -35,6 +66,7 @@ namespace BITKit.Entities
|
||||
{
|
||||
OnOverride?.Invoke(@override);
|
||||
isOvering=@override;
|
||||
overrideKeys = _allowOverrideHandle.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BITKit.Entities;
|
||||
using BITKit.StateMachine;
|
||||
using UnityEngine;
|
||||
@@ -27,20 +28,27 @@ namespace BITKit.Entities
|
||||
add => stateMachine.OnStateChanged += value;
|
||||
remove => stateMachine.OnStateChanged -= value;
|
||||
}
|
||||
|
||||
public event Action<T> OnStateRegistered;
|
||||
public event Action<T> OnStateUnRegistered;
|
||||
public IDictionary<Type, T> StateDictionary => stateMachine.StateDictionary;
|
||||
public override void Initialize(IEntity entity)
|
||||
public override void OnAwake()
|
||||
{
|
||||
base.Initialize(entity);
|
||||
base.OnAwake();
|
||||
if (stateMachine is null)
|
||||
{
|
||||
Debug.LogWarning(GetType().Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var x in stateMachine.states)
|
||||
{
|
||||
Entity.Inject(x);
|
||||
}
|
||||
stateMachine.Initialize();
|
||||
}
|
||||
}
|
||||
void IStateMachine<T>.Initialize()
|
||||
void IStateMachine<T>.Initialize()
|
||||
{
|
||||
stateMachine.Initialize();
|
||||
}
|
||||
@@ -62,6 +70,23 @@ namespace BITKit.Entities
|
||||
{
|
||||
stateMachine.TransitionState(state);
|
||||
}
|
||||
|
||||
public virtual void Register(T newState)
|
||||
{
|
||||
Entity.Inject(newState);
|
||||
StateMachineUtils.Register(this, newState);
|
||||
}
|
||||
|
||||
public virtual void UnRegister(T newState)=>StateMachineUtils.UnRegister(this,newState);
|
||||
public void InvokeOnStateRegistered(T state)
|
||||
{
|
||||
OnStateRegistered?.Invoke(state);
|
||||
}
|
||||
|
||||
public void InvokeOnStateUnRegistered(T state)
|
||||
{
|
||||
OnStateUnRegistered?.Invoke(state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -39,6 +39,10 @@ public class UnityEntitiesServiceSingleton:IEntitiesService
|
||||
public CancellationToken CancellationToken => UnityEntitiesService.CancellationToken;
|
||||
|
||||
public IEntity Get(ulong id) => UnityEntitiesService.Get(id);
|
||||
public bool TryGetEntity(ulong id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity);
|
||||
|
||||
public IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>UnityEntitiesService.GetOrAdd(id,factory);
|
||||
|
||||
|
||||
public IEntity[] Query<T>()
|
||||
{
|
||||
@@ -124,6 +128,17 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService
|
||||
CancellationToken IEntitiesService.CancellationToken => CancellationToken;
|
||||
public static IEntity Get(ulong id)=>Dictionary[id];
|
||||
IEntity IEntitiesService.Get(ulong id)=>Get(id);
|
||||
public static bool TryGetEntity(ulong id, out IEntity entity)
|
||||
{
|
||||
return Dictionary.TryGetValue(id, out entity);
|
||||
}
|
||||
bool IEntitiesService.TryGetEntity(ulong id, out IEntity entity)=>TryGetEntity(id,out entity);
|
||||
public static IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)
|
||||
{
|
||||
return Dictionary.GetOrAdd(id, factory);
|
||||
}
|
||||
IEntity IEntitiesService.GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>GetOrAdd(id,factory);
|
||||
|
||||
IEntity[] IEntitiesService.Query<T>()=>Query<T>();
|
||||
public static IEntity[] Query<T>()
|
||||
{
|
||||
|
Reference in New Issue
Block a user