1
This commit is contained in:
@@ -16,7 +16,8 @@
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:be17a8778dbfe454890ed8279279e153",
|
||||
"GUID:96f476e982d6fb945bfc9140ba094b7f",
|
||||
"GUID:4307f53044263cf4b835bd812fc161a4"
|
||||
"GUID:4307f53044263cf4b835bd812fc161a4",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BITKit.PlayerCamera;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
namespace BITKit.Entities.Player.Character
|
||||
{
|
||||
public class EntityCharacter : EntityPlayerBehavior
|
||||
{
|
||||
[Header(Constant.Header.Components)]
|
||||
[SerializeField] private Renderer[] fpvRenderer = Array.Empty<Renderer>();
|
||||
[SerializeField] private Renderer[] tpvRenderer = Array.Empty<Renderer>();
|
||||
[SerializeField] private Renderer[] fpvOverrideRenderers = Array.Empty<Renderer>();
|
||||
[SerializeField] private Transform[] tpvRendererGroup = Array.Empty<Transform>();
|
||||
[Header(Constant.Header.Reference)]
|
||||
[SerializeReference, SubclassSelector] public IReference getDamage;
|
||||
|
||||
[Inject(true)] private IHealth _health;
|
||||
|
||||
[Inject(true)] private IPlayerCameraService _cameraService;
|
||||
|
||||
[Inject(true)] private IEntityOverride _entityOverride;
|
||||
|
||||
private Renderer[] _tpvRendererGroup;
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
if (_health is not null)
|
||||
{
|
||||
_health.OnSetAlive += _ => UpdateMeshState();
|
||||
_health.OnSetHealthPoint += OnSetHP;
|
||||
}
|
||||
|
||||
if (_cameraService is not null)
|
||||
_cameraService.OnCameraActivated += _ => UpdateMeshState();
|
||||
|
||||
if(_entityOverride is not null)
|
||||
_entityOverride.OnOverride += _ => UpdateMeshState();
|
||||
|
||||
_tpvRendererGroup = tpvRendererGroup.SelectMany(x => x.GetComponentsInChildren<Renderer>(true)).ToArray();
|
||||
}
|
||||
public override void OnPlayerInitialized()
|
||||
{
|
||||
UpdateMeshState();
|
||||
}
|
||||
public override void OnPlayerDispose()
|
||||
{
|
||||
SetFPV(false);
|
||||
}
|
||||
private void OnSetHP(int hp)
|
||||
{
|
||||
UnityEntity.Invoke<string>(Constant.Animation.Play, getDamage.Value);
|
||||
}
|
||||
|
||||
private void UpdateMeshState()
|
||||
{
|
||||
switch (_health, _cameraService)
|
||||
{
|
||||
case (null, null):
|
||||
SetFPV(true);
|
||||
break;
|
||||
case (null, not null):
|
||||
SetFPV(_cameraService.IsCameraActivated);
|
||||
break;
|
||||
case (not null, null):
|
||||
SetFPV(_health.IsAlive);
|
||||
break;
|
||||
case (not null, not null):
|
||||
SetFPV(_health.IsAlive && _cameraService.IsCameraActivated);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetFPV(bool isFpv)
|
||||
{
|
||||
var shadowMode = isFpv ?
|
||||
ShadowCastingMode.ShadowsOnly :
|
||||
ShadowCastingMode.On;
|
||||
foreach (var x in fpvRenderer)
|
||||
{
|
||||
x.enabled = isFpv;
|
||||
}
|
||||
foreach (var x in tpvRenderer)
|
||||
{
|
||||
x.shadowCastingMode = shadowMode;
|
||||
}
|
||||
foreach (var x in _tpvRendererGroup)
|
||||
{
|
||||
x.shadowCastingMode =
|
||||
_entityOverride is not null
|
||||
? _entityOverride.IsOvering ? ShadowCastingMode.On : shadowMode
|
||||
: shadowMode;
|
||||
}
|
||||
|
||||
if (_entityOverride is not null)
|
||||
{
|
||||
foreach (var x in fpvOverrideRenderers)
|
||||
{
|
||||
x.enabled = isFpv && _entityOverride.IsOvering;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -62,6 +62,7 @@ namespace BITKit.Entities
|
||||
/// </summary>
|
||||
public interface IEntityMovement:IStateMachine<IEntityMovementState>
|
||||
{
|
||||
float ReferenceSpeed => 2.5f;
|
||||
Vector3 Position { get; set; }
|
||||
Quaternion Rotation { get; set; }
|
||||
Vector3 Forward { get; }
|
||||
@@ -113,12 +114,12 @@ namespace BITKit.Entities
|
||||
/// 基于相对坐标的移动
|
||||
/// </summary>
|
||||
/// <param name="relativeVector"></param>
|
||||
void Movement(Vector3 relativeVector);
|
||||
void OnMovement(Vector3 relativeVector);
|
||||
/// <summary>
|
||||
/// 基于InputAction的移动
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
void Movement(InputAction.CallbackContext context);
|
||||
void OnMovement(InputAction.CallbackContext context);
|
||||
/// <summary>
|
||||
/// 执行命令
|
||||
/// </summary>
|
||||
|
@@ -12,8 +12,8 @@ namespace BITKit.Entities.Movement
|
||||
[SerializeField] private new Rigidbody rigidbody;
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private bool allowRootMotion;
|
||||
|
||||
|
||||
|
||||
|
||||
public Vector3 Position { get; set; }
|
||||
public Quaternion Rotation { get; set; }
|
||||
public Vector3 Forward { get; }
|
||||
@@ -35,11 +35,11 @@ namespace BITKit.Entities.Movement
|
||||
{
|
||||
}
|
||||
|
||||
public void Movement(Vector3 relativeVector)
|
||||
public void OnMovement(Vector3 relativeVector)
|
||||
{
|
||||
}
|
||||
|
||||
public void Movement(InputAction.CallbackContext context)
|
||||
public void OnMovement(InputAction.CallbackContext context)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using BITKit;
|
||||
using BITKit.SubSystems;
|
||||
@@ -9,14 +10,16 @@ namespace BITKit.Entities
|
||||
{
|
||||
|
||||
public interface IDamageType { }
|
||||
|
||||
public interface IDamageService
|
||||
{
|
||||
public event Action<DamageMessage> OnEntityDamaged;
|
||||
public event Action<DamageMessage> OnEntityKilled;
|
||||
void Execute(DamageMessage damageMessage);
|
||||
}
|
||||
public struct MeleeDamageMessage:IDamageType{}
|
||||
public struct MeleeDamageMessage : IDamageType
|
||||
{
|
||||
public bool Bleeding;
|
||||
}
|
||||
public struct BulletDamageMessage:IDamageType{}
|
||||
[Serializable]
|
||||
public class DamageServiceSingleton:IDamageService
|
||||
@@ -71,6 +74,34 @@ namespace BITKit.Entities
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
public IDamageType DamageType;
|
||||
public RaycastHit? RaycastHit;
|
||||
}
|
||||
|
||||
public sealed class DamageMessageNetMessageWriter : NetMessageReader<DamageMessage>
|
||||
{
|
||||
public override DamageMessage ReadBinary(BinaryReader reader)
|
||||
{
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var initiator);
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var target);
|
||||
return new DamageMessage()
|
||||
{
|
||||
Initiator = initiator as Entity,
|
||||
Target = target as Entity,
|
||||
RawDamage = reader.ReadBoolean(),
|
||||
Damage = reader.ReadInt32(),
|
||||
Position = reader.ReadFloat3(),
|
||||
Rotation = reader.ReadQuaternion(),
|
||||
};
|
||||
}
|
||||
public override void WriteBinary(BinaryWriter writer, DamageMessage value)
|
||||
{
|
||||
writer.Write(value.Initiator?.Id ?? 0);
|
||||
writer.Write(value.Target?.Id ?? 0);
|
||||
writer.Write(value.RawDamage);
|
||||
writer.Write(value.Damage);
|
||||
writer.WriteFloat3(value.Position);
|
||||
writer.WriteQuaternion(value.Rotation);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDamageCallback
|
||||
@@ -79,35 +110,65 @@ namespace BITKit.Entities
|
||||
}
|
||||
public interface IDamagable
|
||||
{
|
||||
IHealth Health { get; }
|
||||
IUnityEntity UnityEntity { get; }
|
||||
Rigidbody Rigidbody { get; }
|
||||
void GiveDamage(DamageMessage message);
|
||||
}
|
||||
public class DamageService:MonoBehaviour,IDamageService
|
||||
{
|
||||
internal static IDamageService Singleton { get; set; }
|
||||
public static IDamageService Singleton { get;private set; }
|
||||
private readonly Queue<DamageMessage> Messages = new();
|
||||
|
||||
[SerializeReference,SubclassSelector] private INetClient netClient;
|
||||
[SerializeReference,SubclassSelector] private INetServer netServer;
|
||||
|
||||
private INetProvider netClientProvider => netClient.Source as INetProvider;
|
||||
private INetProvider netServerProvider => netServer.Source as INetProvider;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Singleton = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
netClientProvider.AddCommandListener<DamageMessage>(ExecuteInternal);
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!netServer.IsRunningServer && netClient.IsConnected) return;
|
||||
while (Messages.TryDequeue(out var damageMessage))
|
||||
{
|
||||
var unityEntity = (Entity)damageMessage.Target;
|
||||
if (!unityEntity || !unityEntity.TryGetComponent<IHealth>(out var heal) || !heal.IsAlive) continue;
|
||||
|
||||
damageMessage.Initiator?.Invoke(damageMessage);
|
||||
damageMessage.Target?.Invoke(damageMessage);
|
||||
|
||||
ExecuteInternal(damageMessage);
|
||||
|
||||
netServerProvider?.AllClientCommand(damageMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteInternal(DamageMessage damageMessage)
|
||||
{
|
||||
IHealth heal = null;
|
||||
if (damageMessage.Target?.TryGetComponent<IHealth>(out heal) is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
damageMessage.Initiator?.Invoke(damageMessage);
|
||||
damageMessage.Target?.Invoke(damageMessage);
|
||||
|
||||
if (heal!.IsAlive)
|
||||
{
|
||||
OnEntityDamaged?.Invoke(damageMessage);
|
||||
if (heal.IsAlive is false)
|
||||
{
|
||||
OnEntityKilled?.Invoke(damageMessage);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
OnEntityKilled?.Invoke(damageMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Contexts;
|
||||
using UnityEngine;
|
||||
@@ -20,21 +21,34 @@ namespace BITKit.Entities
|
||||
/// <summary>
|
||||
/// 当受到伤害时的回调
|
||||
/// </summary>
|
||||
public event Func<DamageMessage,int,int> OnDamageFactory;
|
||||
public event Func<DamageMessage,int,int> OnDamageFactory;
|
||||
/// <summary>
|
||||
/// 收到伤害时的回调
|
||||
/// </summary>
|
||||
public event Action<DamageMessage> OnDamageRelease;
|
||||
/// <summary>
|
||||
/// 当伤害被阻止时的回调
|
||||
/// </summary>
|
||||
public event Action<DamageMessage> OnDamageVoid;
|
||||
|
||||
int HealthPoint { get; set; }
|
||||
int MaxHealthPoint { get; set; }
|
||||
bool IsAlive { get; }
|
||||
}
|
||||
[CustomType(typeof(IHealth))]
|
||||
public class EntityHealth : EntityBehavior, IHealth
|
||||
public class EntityHealth : EntityBehavior, IHealth,IEntityBinaryComponent
|
||||
{
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private int healthPoint = 100;
|
||||
[SerializeField] private int maxHealthPoint = 100;
|
||||
|
||||
public int Id { get; } = 84946486;
|
||||
|
||||
public event Action<int> OnSetHealthPoint;
|
||||
public event Action<bool> OnSetAlive;
|
||||
public event Func<DamageMessage,int, int> OnDamageFactory;
|
||||
public event Action<DamageMessage> OnDamageRelease;
|
||||
public event Action<DamageMessage> OnDamageVoid;
|
||||
|
||||
public int HealthPoint
|
||||
{
|
||||
@@ -61,7 +75,7 @@ namespace BITKit.Entities
|
||||
|
||||
private void OnHealthPointChangedInternal(int old, int newHP)
|
||||
{
|
||||
healthPoint = newHP;
|
||||
healthPoint =Mathf.Clamp(newHP,-1,maxHealthPoint) ;
|
||||
var _isAlive = newHP >= 0;
|
||||
if (_isAlive != IsAlive)
|
||||
{
|
||||
@@ -84,15 +98,28 @@ namespace BITKit.Entities
|
||||
private void OnGetDamage(DamageMessage damageMessage)
|
||||
{
|
||||
if (damageMessage.Target != UnityEntity) return;
|
||||
if (IsAlive is false) return;
|
||||
var damage = damageMessage.Damage;
|
||||
foreach (var x in OnDamageFactory.CastAsFunc().Reverse())
|
||||
if (IsAlive is false)
|
||||
{
|
||||
damage = x.Invoke(damageMessage, damage);
|
||||
if (damage <= 0) break;
|
||||
OnDamageVoid?.Invoke(damageMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
var damage = damageMessage.Damage;
|
||||
foreach (var x in OnDamageFactory.CastAsFunc())
|
||||
{
|
||||
damage = x.Invoke(damageMessage, damage);
|
||||
if (damage <= 0)
|
||||
{
|
||||
OnDamageVoid?.Invoke(damageMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Data.Get<bool>("god") is false)
|
||||
AddHP(-damage);
|
||||
|
||||
damageMessage.Damage = damage;
|
||||
OnDamageRelease?.Invoke(damageMessage);
|
||||
}
|
||||
if (Data.Get<bool>("god") is false)
|
||||
AddHP(-damage);
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
@@ -109,6 +136,17 @@ namespace BITKit.Entities
|
||||
OnHealthPointChangedInternal(100, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(HealthPoint);
|
||||
}
|
||||
|
||||
public void Deserialize(BinaryReader reader)
|
||||
{
|
||||
var newHealthPoint = reader.ReadInt32();
|
||||
if (HealthPoint != newHealthPoint)
|
||||
HealthPoint = newHealthPoint;
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,15 +4,52 @@ using UnityEngine;
|
||||
using BITKit;
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
public class EntityHitbox : EntityBehavior,IDamagable
|
||||
public class EntityHitbox : MonoBehaviour,IDamagable
|
||||
{
|
||||
IUnityEntity IDamagable.UnityEntity => UnityEntity;
|
||||
public Rigidbody Rigidbody => m_rigidbody;
|
||||
public IHealth Health
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureConfigure();
|
||||
return _health;
|
||||
}
|
||||
}
|
||||
|
||||
public IUnityEntity UnityEntity
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureConfigure();
|
||||
return _unityEntity;
|
||||
}
|
||||
}
|
||||
public Rigidbody Rigidbody
|
||||
{
|
||||
get=>m_rigidbody;
|
||||
set=>m_rigidbody=value;
|
||||
}
|
||||
|
||||
public void GiveDamage(DamageMessage message)
|
||||
{
|
||||
UnityEntity.Invoke(message);
|
||||
if (_unityEntity is not null)
|
||||
UnityEntity.Invoke(message);
|
||||
}
|
||||
|
||||
[SerializeField]private Rigidbody m_rigidbody;
|
||||
|
||||
|
||||
[Inject(true)]
|
||||
private IHealth _health;
|
||||
|
||||
private IUnityEntity _unityEntity;
|
||||
|
||||
private bool _initialized;
|
||||
|
||||
private void EnsureConfigure()
|
||||
{
|
||||
if (_initialized) return;
|
||||
_unityEntity = GetComponentInParent<IUnityEntity>(true);
|
||||
_unityEntity?.Inject(this);
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITFALL.Rig;
|
||||
using BITKit.Entities;
|
||||
using Cysharp.Threading.Tasks.Triggers;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
public class EntityHitboxBuilder : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Collider[] colliders;
|
||||
[SerializeField] private EntityHitbox[] hitboxes;
|
||||
|
||||
[SerializeReference,SubclassSelector] private IReference[] tagReferences;
|
||||
[BIT]
|
||||
private void Build()
|
||||
{
|
||||
foreach (var x in hitboxes)
|
||||
{
|
||||
DestroyImmediate(x.gameObject);
|
||||
}
|
||||
hitboxes = new EntityHitbox[colliders.Length];
|
||||
for (var i = 0; i < colliders.Length; i++)
|
||||
{
|
||||
var collider = colliders[i];
|
||||
var newGameObject = new GameObject($"Hitbox_{collider.gameObject.name}");
|
||||
|
||||
newGameObject.layer = gameObject.layer;
|
||||
|
||||
newGameObject.transform.SetParent(transform);
|
||||
var transform1 = collider.transform;
|
||||
newGameObject.transform.position = transform1.position;
|
||||
newGameObject.transform.rotation = transform1.rotation;
|
||||
var hitbox =hitboxes[i] = newGameObject.AddComponent<EntityHitbox>();
|
||||
var tag = newGameObject.AddComponent<Tag>();
|
||||
|
||||
var tickOverride = newGameObject.AddComponent<TickOverrideTransform>();
|
||||
|
||||
tickOverride.Source = newGameObject.transform;
|
||||
tickOverride.Target = collider.transform;
|
||||
|
||||
if (collider.TryGetComponent<Rigidbody>(out var newRigidbody))
|
||||
{
|
||||
hitbox.Rigidbody = newRigidbody;
|
||||
}
|
||||
|
||||
switch (collider)
|
||||
{
|
||||
case BoxCollider boxCollider:
|
||||
var box = newGameObject.AddComponent<BoxCollider>();
|
||||
box.size = boxCollider.size;
|
||||
box.center = boxCollider.center;
|
||||
break;
|
||||
case SphereCollider sphereCollider:
|
||||
var sphere = newGameObject.AddComponent<SphereCollider>();
|
||||
sphere.radius = sphereCollider.radius;
|
||||
sphere.center = sphereCollider.center;
|
||||
break;
|
||||
case CapsuleCollider capsuleCollider:
|
||||
var capsule = newGameObject.AddComponent<CapsuleCollider>();
|
||||
capsule.radius = capsuleCollider.radius;
|
||||
capsule.height = capsuleCollider.height;
|
||||
capsule.direction = capsuleCollider.direction;
|
||||
capsule.center = capsuleCollider.center;
|
||||
break;
|
||||
}
|
||||
|
||||
tag.SetTags(tagReferences);
|
||||
EditorUtility.SetDirty(hitbox);
|
||||
EditorUtility.SetDirty(tag);
|
||||
}
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8de7270cf1d43f64fafdc3413158cea3
|
||||
guid: 21e16997211c6f44c837beae9450cb58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -13,7 +13,8 @@ namespace BITKit.Entities.InputSystem
|
||||
{
|
||||
protected readonly InputActionGroup inputActionGroup = new()
|
||||
{
|
||||
allowGlobalActivation = true
|
||||
allowGlobalActivation = true,
|
||||
Source = nameof(EntityInputSystem)
|
||||
};
|
||||
[Inject(true)]
|
||||
private IHealth _health;
|
||||
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "BITKit.Entities.Player.Interactive",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
|
||||
"GUID:f822dbf6fdfd4a5469cccaa2e4eed3b6",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:508392158bd966c4d9c21e19661a441d",
|
||||
"GUID:7efac18f239530141802fb139776f333",
|
||||
"GUID:9354affc93e0f3e4a904785e7d4c0f59"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -1,141 +0,0 @@
|
||||
using System;
|
||||
using BITKit.PlayerCamera;
|
||||
using BITKit.Selection;
|
||||
using BITKit.Sensors;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Interactions;
|
||||
namespace BITKit.Entities.Player
|
||||
{
|
||||
[CustomType(typeof(ISelector))]
|
||||
public class EntityInteractive : EntityPlayerBehavior,ISelector
|
||||
{
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeReference, SubclassSelector] private ISensor sensor;
|
||||
|
||||
[Header(Constant.Header.Gameobjects)]
|
||||
[SerializeField] private Transform sensorTransform;
|
||||
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
private ISelectable selected;
|
||||
private IntervalUpdate cd = new(0.08f);
|
||||
[Inject]
|
||||
private IHealth _health;
|
||||
|
||||
[Inject(true)] private IEntityMovement _movement;
|
||||
|
||||
[Inject(true)] IPlayerCameraService _cameraService;
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
_health.OnSetAlive += OnSetAlive;
|
||||
}
|
||||
|
||||
private void OnSetAlive(bool obj)
|
||||
{
|
||||
TryDeSelected();
|
||||
}
|
||||
|
||||
public override void OnUpdate(float deltaTime)
|
||||
{
|
||||
if (_cameraService is not null && _movement is not null)
|
||||
{
|
||||
if (_cameraService.IsCameraActivated)
|
||||
{
|
||||
sensorTransform.SetPositionAndRotation(_cameraService.CameraPosition, _cameraService.CameraRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
sensorTransform.position = _movement.Position + _movement.Rotation * _movement.ViewCenter;
|
||||
sensorTransform.rotation = _movement.ViewRotation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//if (sensor.Get().TryGetAny(x=>x.TryGetComponentAny<ISelectable>(out _),out var detected))
|
||||
try
|
||||
{
|
||||
if (sensor.Get().TryGetAny(x=>x.GetComponentInParent<ISelectable>() is not null,out var detected))
|
||||
{
|
||||
if (detected.TryGetComponentAny<ISelectable>(out var _detected))
|
||||
{
|
||||
if (_detected == selected)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TryDeSelected();
|
||||
|
||||
Detected(_detected);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TryDeSelected();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TryDeSelected();
|
||||
}
|
||||
}
|
||||
catch(MissingReferenceException e)
|
||||
{}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
private void TryDeSelected()
|
||||
{
|
||||
if (selected is null) return;
|
||||
selected.SetSelectionState(SelectionState.None);
|
||||
OnInactive?.Invoke(selected);
|
||||
selected = null;
|
||||
}
|
||||
private void Detected(ISelectable detected)
|
||||
{
|
||||
selected = detected;
|
||||
detected.SetSelectionState(SelectionState.Hover);
|
||||
OnSelected?.Invoke(selected);
|
||||
}
|
||||
|
||||
public void Interactive(InputAction.CallbackContext context)
|
||||
{
|
||||
if (context.interaction is not PressInteraction || !context.performed ) return;
|
||||
if (cd.AllowUpdate is false) return;
|
||||
var _selected = selected;
|
||||
if (_selected is not MonoBehaviour monoBehaviour) return;
|
||||
if (monoBehaviour.TryGetComponentAny<IAction>(out var action))
|
||||
{
|
||||
action.Execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
selected.SetSelectionState(SelectionState.Active);
|
||||
OnActive?.Invoke(selected);
|
||||
}
|
||||
|
||||
public bool TryGetCurrentSelectable(out ISelectable selectable)
|
||||
{
|
||||
selectable = selected;
|
||||
return selected?.Transform;
|
||||
}
|
||||
|
||||
public event Action<ISelectable> OnNone;
|
||||
public event Action<ISelectable> OnHover;
|
||||
public event Action<ISelectable> OnActive;
|
||||
public event Action<ISelectable> OnInactive;
|
||||
public event Action<ISelectable> OnFocus;
|
||||
public event Action<ISelectable> OnSelected;
|
||||
public event Action<ISelectable> OnEnabled;
|
||||
public event Action<ISelectable> OnChecked;
|
||||
public event Action<ISelectable> OnRoot;
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b8ff0f400ff5fd44b5205e0adaa1969
|
||||
guid: 0dcb052e1b8841743aaa68d522200c5e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
@@ -1,118 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BITKit.Entities.Physics;
|
||||
using UnityEngine;
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
[CustomType(typeof(IEntityPhysics))]
|
||||
public class EntityPhysics : EntityBehavior,IEntityPhysics
|
||||
{
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private Rigidbody[] rigidbodies;
|
||||
[SerializeField] private Collider[] ragdollColliders;
|
||||
[SerializeField] private Joint[] joints;
|
||||
[SerializeField] private new Rigidbody rigidbody;
|
||||
[Inject]
|
||||
private IHealth _health;
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointXMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointYMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointZMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularXMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularYMotions=new();
|
||||
private readonly Dictionary<Joint,ConfigurableJointMotion> _jointAngularZMotions=new();
|
||||
|
||||
public override void OnAwake()
|
||||
{
|
||||
_health.OnSetAlive += OnSetAlive;
|
||||
_health.OnSetHealthPoint += OnSetHP;
|
||||
foreach (var x in joints)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case ConfigurableJoint configurableJoint:
|
||||
_jointXMotions.Add(configurableJoint,configurableJoint.xMotion);
|
||||
_jointYMotions.Add(configurableJoint,configurableJoint.yMotion);
|
||||
_jointZMotions.Add(configurableJoint,configurableJoint.zMotion);
|
||||
_jointAngularXMotions.Add(configurableJoint,configurableJoint.angularXMotion);
|
||||
_jointAngularYMotions.Add(configurableJoint,configurableJoint.angularYMotion);
|
||||
_jointAngularZMotions.Add(configurableJoint,configurableJoint.angularZMotion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSetAlive(bool alive)
|
||||
{
|
||||
IsPhysics = !alive;
|
||||
if (animator)
|
||||
animator.enabled = alive;
|
||||
try
|
||||
{
|
||||
await Task.Delay(10, destroyCancellationToken);
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
rigidbodies.ForEach(x => { x.isKinematic = alive; });
|
||||
ragdollColliders.ForEach(x => { x.enabled = !alive; });
|
||||
OnSetPhysics?.Invoke(!alive);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
foreach (var joint in joints)
|
||||
{
|
||||
switch (joint)
|
||||
{
|
||||
case ConfigurableJoint configurableJoint:
|
||||
configurableJoint.xMotion = alive ? _jointXMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.yMotion = alive ? _jointYMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.zMotion = alive ? _jointZMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularXMotion =
|
||||
alive ? _jointAngularXMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularYMotion =
|
||||
alive ? _jointAngularYMotions[joint] : ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularZMotion =
|
||||
alive ? _jointAngularZMotions[joint] : ConfigurableJointMotion.Free;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void OnSetHP(int hp)
|
||||
{
|
||||
}
|
||||
|
||||
public Vector3 Center => rigidbody.worldCenterOfMass;
|
||||
public bool IsPhysics { get; private set; }
|
||||
public Vector3 Velocity
|
||||
{
|
||||
get=>rigidbody.velocity;
|
||||
set
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.velocity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Action<bool> OnSetPhysics { get; set; }
|
||||
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force)
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.AddForce(force, mode);
|
||||
}
|
||||
}
|
||||
public void AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force)
|
||||
{
|
||||
foreach (var x in rigidbodies)
|
||||
{
|
||||
x.AddTorque(torque, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8cf20e38c0584247ab1573e085274d4
|
||||
guid: 22c8a583a4eb6504ab5a732954c0855c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c78fe9fd58f5efc4abdeb6d193bf258b
|
||||
guid: 4ff33423878ac11439fbf15f38dbe628
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -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>()
|
||||
{
|
||||
|
74
Src/Unity/Scripts/Entity/Editor/UnityEntitiesBinaryEditor.cs
Normal file
74
Src/Unity/Scripts/Entity/Editor/UnityEntitiesBinaryEditor.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace BITKit.Entities.GameEditor
|
||||
{
|
||||
public class UnityEntitiesBinaryEditor : EditorWindow
|
||||
{
|
||||
[MenuItem("Tools/Entities/EntitiesBinaryEditor")]
|
||||
public static void Open()
|
||||
{
|
||||
var window = GetWindow<UnityEntitiesBinaryEditor>();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private Label _base64Label;
|
||||
private void OnEnable()
|
||||
{
|
||||
rootVisualElement.Clear();
|
||||
|
||||
var button = rootVisualElement.Create<Button>();
|
||||
button.clicked += PrintBytes;
|
||||
|
||||
button.text = "获取二进制数据";
|
||||
|
||||
_base64Label = rootVisualElement.Create<Label>();
|
||||
|
||||
var copyButton = rootVisualElement.Create<Button>();
|
||||
copyButton.text = "复制到剪切板";
|
||||
copyButton.clicked += () =>
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = _base64Label.text;
|
||||
};
|
||||
|
||||
var inputField = rootVisualElement.Create<TextField>();
|
||||
inputField.multiline = true;
|
||||
inputField.label = "输入二进制数据";
|
||||
var applyButton = rootVisualElement.Create<Button>();
|
||||
applyButton.text = "应用数据";
|
||||
applyButton.clicked += () =>
|
||||
{
|
||||
|
||||
var bytes = JsonHelper.Get<byte[]>(inputField.value);
|
||||
|
||||
using var ms = new System.IO.MemoryStream(bytes);
|
||||
using var reader = new System.IO.BinaryReader(ms);
|
||||
Debug.Log($"应用数据中,长度为:{ms.Length}");
|
||||
foreach (var header in UnityEntitiesService.QueryComponents<IEntityBinaryHeader>())
|
||||
{
|
||||
header.Deserialize(reader);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void PrintBytes()
|
||||
{
|
||||
using var ms = new System.IO.MemoryStream();
|
||||
using var writer = new System.IO.BinaryWriter(ms);
|
||||
foreach (var header in UnityEntitiesService.QueryComponents<IEntityBinaryHeader>())
|
||||
{
|
||||
header.Serialize(writer);
|
||||
}
|
||||
var bytes = ms.ToArray();
|
||||
writer.Dispose();
|
||||
ms.Dispose();
|
||||
|
||||
_base64Label.text = JsonHelper.Get(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ace44c921aa7cae419c70332a5c75122
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -6,11 +6,11 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace BITKit.Entities.Editor
|
||||
namespace BITKit.Entities.GameEditor
|
||||
{
|
||||
public class UnityEntitiesServiceEditor : EditorWindow
|
||||
{
|
||||
[MenuItem("Tools/Entities/UnityEntitiesService")]
|
||||
[MenuItem("Tools/Entities/EntitiesService")]
|
||||
public static void Open()
|
||||
{
|
||||
var window = GetWindow<UnityEntitiesServiceEditor>();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80d35d9e6778dc84b88662124834dd35
|
||||
guid: 75d594a25b599204691b487a447d6e68
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"name": "BITKit.Entities.Player.Character",
|
||||
"name": "BITKit.Entities.Net",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
|
||||
"GUID:f822dbf6fdfd4a5469cccaa2e4eed3b6",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:7efac18f239530141802fb139776f333",
|
||||
"GUID:9354affc93e0f3e4a904785e7d4c0f59"
|
||||
"GUID:9354affc93e0f3e4a904785e7d4c0f59",
|
||||
"GUID:c56f2ae4d67b9b947a600c84225206a2"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be39401f40b20344a8e59d5ddab532bc
|
||||
guid: c27e9384ceefce34796410b6135e54a5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
172
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs
Normal file
172
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Timers;
|
||||
using BITKit.Entities.Player;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
[Serializable]
|
||||
public struct EntitiesNetSyncCommand
|
||||
{
|
||||
public byte[] Data;
|
||||
}
|
||||
[Serializable]
|
||||
public struct EntitiesNetSyncBatchCommand
|
||||
{
|
||||
public int Length;
|
||||
public ulong[] Ids;
|
||||
public ulong[] AddressablePaths;
|
||||
public EntitiesNetSyncCommand[] Commands;
|
||||
}
|
||||
|
||||
public class EntitiesNetService : MonoBehaviour
|
||||
{
|
||||
[Header(Constant.Header.Services)]
|
||||
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||
[SerializeReference, SubclassSelector] private IEntitiesService entitiesService;
|
||||
[SerializeReference, SubclassSelector] private IPlayerService playerService;
|
||||
|
||||
[SerializeReference, SubclassSelector]private INetClient client;
|
||||
[SerializeReference, SubclassSelector]private INetServer server;
|
||||
|
||||
private INetProvider clientNetProvider => client.Source as INetProvider;
|
||||
private INetProvider serverNetProvider => server.Source as INetProvider;
|
||||
|
||||
[Inject]
|
||||
private IEntityBinaryHeader _playerHeader;
|
||||
[Inject] private IAddressable _playerAddressable;
|
||||
[Inject]
|
||||
private IEntity _playerEntity;
|
||||
|
||||
private readonly ConcurrentQueue<EntitiesNetSyncBatchCommand> _batchCommands = new();
|
||||
private readonly ConcurrentQueue<EntitiesNetSyncCommand> _syncCommands = new();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
ticker.Add(Tick);
|
||||
|
||||
clientNetProvider.AddCommandListener<EntitiesNetSyncBatchCommand>(_batchCommands.Enqueue);
|
||||
|
||||
serverNetProvider.AddCommandListener<EntitiesNetSyncCommand>(_syncCommands.Enqueue);
|
||||
|
||||
playerService.OnPlayerInitialized+=OnPlayerInitialized;
|
||||
playerService.OnPlayerDisposed += OnPlayerDisposed;
|
||||
|
||||
destroyCancellationToken.Register(() =>
|
||||
{
|
||||
ticker.Remove(Tick);
|
||||
playerService.OnPlayerInitialized-=OnPlayerInitialized;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void OnPlayerDisposed(Entity obj)
|
||||
{
|
||||
_playerHeader = null;
|
||||
_playerAddressable = null;
|
||||
_playerEntity = null;
|
||||
}
|
||||
|
||||
private void OnPlayerInitialized(Entity obj)
|
||||
{
|
||||
obj.Inject(this);
|
||||
}
|
||||
|
||||
private void OnSyncCommand(EntitiesNetSyncCommand obj)
|
||||
{
|
||||
using var ms = new MemoryStream(obj.Data);
|
||||
using var reader = new BinaryReader(ms);
|
||||
var id = reader.ReadUInt64();
|
||||
var path = reader.ReadUInt64();
|
||||
entitiesService.GetOrAdd(id, x => AddEntity(id, path)).TryGetComponent<IEntityBinaryHeader>(out var header);
|
||||
header.Deserialize(reader);
|
||||
}
|
||||
private void OnBatchCommand(EntitiesNetSyncBatchCommand obj)
|
||||
{
|
||||
for (var i = 0; i < obj.Length; i++)
|
||||
{
|
||||
var id = obj.Ids[i];
|
||||
var path = obj.AddressablePaths[i];
|
||||
var command = obj.Commands[i];
|
||||
var entity = entitiesService.GetOrAdd(id,x=>AddEntity(id,path));
|
||||
entity.TryGetComponent<IEntityBinaryHeader>(out var header);
|
||||
using var ms = new MemoryStream(command.Data);
|
||||
using var reader = new BinaryReader(ms);
|
||||
header.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
private static IEntity AddEntity(ulong id,ulong addressableId)
|
||||
{
|
||||
var entity = AddressableHelper.Get<GameObject>(addressableId);
|
||||
var instance = Instantiate(entity).GetComponent<Entity>();
|
||||
instance.Id = id;
|
||||
instance.WaitForInitializationComplete();
|
||||
return instance;
|
||||
}
|
||||
private void Tick(float deltaTime)
|
||||
{
|
||||
while (_batchCommands.TryDequeue(out var command))
|
||||
{
|
||||
OnBatchCommand(command);
|
||||
}
|
||||
|
||||
while (_syncCommands.TryDequeue(out var command))
|
||||
{
|
||||
OnSyncCommand(command);
|
||||
}
|
||||
|
||||
|
||||
if (client.IsConnected is false && server.IsRunningServer is false) return;
|
||||
using var memoryStream = new MemoryStream();
|
||||
if (client.IsConnected && _playerEntity as Entity && _playerHeader != null)
|
||||
{
|
||||
using var writer = new BinaryWriter(memoryStream);
|
||||
|
||||
writer.Write(_playerEntity.Id);
|
||||
writer.Write(_playerAddressable.AddressableId);
|
||||
|
||||
_playerHeader.Serialize(writer);
|
||||
var command = new EntitiesNetSyncCommand
|
||||
{
|
||||
Data = memoryStream.ToArray()
|
||||
};
|
||||
clientNetProvider.ServerCommand(command);
|
||||
}
|
||||
else if (server.IsRunningServer)
|
||||
{
|
||||
using var writer = new BinaryWriter(memoryStream);
|
||||
|
||||
var headers = entitiesService.QueryComponents<IEntity, IEntityBinaryHeader, IAddressable>();
|
||||
|
||||
var batchCommand = new EntitiesNetSyncBatchCommand()
|
||||
{
|
||||
Length = headers.Length,
|
||||
Ids = new ulong[headers.Length],
|
||||
AddressablePaths = new ulong[headers.Length],
|
||||
Commands = new EntitiesNetSyncCommand[headers.Length]
|
||||
};
|
||||
|
||||
var count = -1;
|
||||
foreach (var (entity, header, addressable) in headers)
|
||||
{
|
||||
count++;
|
||||
using var ms = new MemoryStream();
|
||||
using var entityWriter = new BinaryWriter(ms);
|
||||
|
||||
header.Serialize(entityWriter);
|
||||
entityWriter.Flush();
|
||||
|
||||
batchCommand.Ids[count] = entity.Id;
|
||||
batchCommand.AddressablePaths[count] = addressable.AddressableId;
|
||||
batchCommand.Commands[count] = new EntitiesNetSyncCommand { Data = ms.ToArray() };
|
||||
}
|
||||
serverNetProvider.AllClientCommand(batchCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eac64f495178d7844bf83d3b03736ea1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
32
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs
Normal file
32
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities
|
||||
{
|
||||
public sealed class EntityNetConfig : EntityBehavior
|
||||
{
|
||||
[SerializeField] private bool serverOnly;
|
||||
[SerializeReference,SubclassSelector] private INetClient netClient;
|
||||
[SerializeReference,SubclassSelector] private INetServer netServer;
|
||||
[SerializeReference,SubclassSelector] private ITicker ticker;
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
ticker?.Add(OnTick);
|
||||
}
|
||||
private void OnDestroy()
|
||||
{
|
||||
ticker?.Remove(OnTick);
|
||||
}
|
||||
private void OnTick(float deltaTime)
|
||||
{
|
||||
if (netClient.IsConnected && serverOnly)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58fae32cecb66cc42925dedf4fde21bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,16 +1,20 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities.Player
|
||||
{
|
||||
public class LocalPlayerBehavior : EntityBehavior
|
||||
public class LocalPlayerBehavior : EntityBehavior,IEntityBinaryComponent
|
||||
{
|
||||
public int Id { get; }= new ConstantHash(nameof(LocalPlayerBehavior));
|
||||
|
||||
private IEntityPlayerComponent[] playerComponents;
|
||||
private CancellationTokenSource initializeCancellationTokenSource;
|
||||
private CancellationTokenSource disposeCancellationTokenSource;
|
||||
|
||||
public override async void OnStart()
|
||||
{
|
||||
initializeCancellationTokenSource = new CancellationTokenSource();
|
||||
@@ -51,5 +55,13 @@ namespace BITKit.Entities.Player
|
||||
disposeCancellationTokenSource.Dispose();
|
||||
UnityPlayerServiceService.UnRegister((Entity)UnityEntity);
|
||||
}
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(0);
|
||||
}
|
||||
public void Deserialize(BinaryReader reader)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
Src/Unity/Scripts/Entity/Player/ProxyPlayerComponent.cs
Normal file
36
Src/Unity/Scripts/Entity/Player/ProxyPlayerComponent.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Entities.Player
|
||||
{
|
||||
public class ProxyPlayerComponent : EntityBehavior,IEntityBinaryComponent
|
||||
{
|
||||
public int Id { get; } = new ConstantHash(nameof(LocalPlayerBehavior));
|
||||
private readonly IntervalUpdate _timeout = new(8);
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
_timeout.Reset();
|
||||
}
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
}
|
||||
public void Deserialize(BinaryReader reader)
|
||||
{
|
||||
reader.ReadInt32();
|
||||
_timeout.Reset();
|
||||
}
|
||||
public override void OnUpdate(float deltaTime)
|
||||
{
|
||||
base.OnUpdate(deltaTime);
|
||||
if (_timeout.AllowUpdate)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Src/Unity/Scripts/Entity/Player/ProxyPlayerComponent.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Player/ProxyPlayerComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e25b0e453185f74428146cbe5a5f99fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BITKit.StateMachine;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -36,6 +37,9 @@ namespace BITKit.Entities.Player
|
||||
remove => stateMachine.OnStateChanged -= value;
|
||||
}
|
||||
|
||||
public event Action<T> OnStateRegistered;
|
||||
public event Action<T> OnStateUnRegistered;
|
||||
|
||||
public IDictionary<Type, T> StateDictionary => stateMachine.StateDictionary;
|
||||
|
||||
void IStateMachine<T>.Initialize()
|
||||
@@ -62,5 +66,16 @@ namespace BITKit.Entities.Player
|
||||
{
|
||||
stateMachine.TransitionState(state);
|
||||
}
|
||||
public virtual void Register(T newState)=>StateMachineUtils.Register(this,newState);
|
||||
public virtual void UnRegister(T newState)=>StateMachineUtils.UnRegister(this,newState);
|
||||
void IStateMachine<T>.InvokeOnStateRegistered(T state)
|
||||
{
|
||||
OnStateRegistered?.Invoke(state);
|
||||
}
|
||||
|
||||
void IStateMachine<T>.InvokeOnStateUnRegistered(T state)
|
||||
{
|
||||
OnStateUnRegistered?.Invoke(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b5481cf34bf4a145898ac81e58abf8f
|
||||
guid: ea9ee800e8536fe45a4868de4bc936d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "BITKit.Entities.Variable",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05850b7e403af6d48bc240ab3c2bc8f4
|
||||
guid: f602b6f914f91d4499383d874af1decd
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
105
Src/Unity/Scripts/Entity/Variable/EntityVariable.cs
Normal file
105
Src/Unity/Scripts/Entity/Variable/EntityVariable.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace BITKit.Entities.Variables
|
||||
{
|
||||
public interface IVariable
|
||||
{
|
||||
string Variable { get; set; }
|
||||
string[] Variables { get; }
|
||||
event Action<string,string> OnVariableChanged;
|
||||
event Func<string,bool> TryChangeVariable;
|
||||
event Func<string> CollectVariables;
|
||||
|
||||
}
|
||||
[Serializable]
|
||||
public sealed class IVariableFromDI : InjectFromDI<IVariable>,IVariable
|
||||
{
|
||||
private IVariable _variableImplementation => Value;
|
||||
public string Variable
|
||||
{
|
||||
get => _variableImplementation.Variable;
|
||||
set => _variableImplementation.Variable = value;
|
||||
}
|
||||
|
||||
public string[] Variables => _variableImplementation.Variables;
|
||||
|
||||
public event Action<string, string> OnVariableChanged
|
||||
{
|
||||
add => _variableImplementation.OnVariableChanged += value;
|
||||
remove => _variableImplementation.OnVariableChanged -= value;
|
||||
}
|
||||
|
||||
public event Func<string, bool> TryChangeVariable
|
||||
{
|
||||
add => _variableImplementation.TryChangeVariable += value;
|
||||
remove => _variableImplementation.TryChangeVariable -= value;
|
||||
}
|
||||
|
||||
public event Func<string> CollectVariables
|
||||
{
|
||||
add => _variableImplementation.CollectVariables += value;
|
||||
remove => _variableImplementation.CollectVariables -= value;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomType(typeof(IVariable),true)]
|
||||
public sealed class EntityVariable:MonoBehaviour,IVariable
|
||||
{
|
||||
public string Variable
|
||||
{
|
||||
get => _variable;
|
||||
set
|
||||
{
|
||||
if (TryChangeVariable is null || TryChangeVariable.CastAsFunc().All(Yes))
|
||||
{
|
||||
OnVariableChanged?.Invoke(_variable, _variable = value);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
bool Yes(Func<string, bool> arg)
|
||||
{
|
||||
return arg.Invoke(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Variables {
|
||||
get
|
||||
{
|
||||
if (CollectVariables is null)
|
||||
{
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
var listPool=ListPool<string>.Get();
|
||||
foreach (var x in CollectVariables.CastAsFunc())
|
||||
{
|
||||
listPool.Add(x.Invoke());
|
||||
}
|
||||
var result = listPool.ToArray();
|
||||
ListPool<string>.Release(listPool);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
public event Action<string,string> OnVariableChanged;
|
||||
public event Func<string,bool> TryChangeVariable;
|
||||
public event Func<string> CollectVariables;
|
||||
|
||||
private string _variable="Default";
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (GetType().GetCustomAttribute<CustomTypeAttribute>() is { AsGlobal: true })
|
||||
{
|
||||
DI.Register<IVariable>(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Entity/Variable/EntityVariable.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Variable/EntityVariable.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0c6c2d406bfdaf46ba4ab9883f71066
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Src/Unity/Scripts/Entity/World.meta
Normal file
8
Src/Unity/Scripts/Entity/World.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14bb579de4539df4caa9a3af10e10715
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "BITKit.Entities.Physics.Runtime",
|
||||
"name": "BITKit.Entities.World.Runtime",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
|
||||
"GUID:a3de65b07192e7d49bad7b4032d681de",
|
||||
"GUID:7efac18f239530141802fb139776f333"
|
||||
"GUID:1193c2664d97cc049a6e4c486c6bce71",
|
||||
"GUID:bdb069e155d2f944cb1bf28602b6d4c1"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e144f3bb79485843b0a2df56bef0900
|
||||
guid: 5835538f89758aa42ab9ebe7a5de98fb
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
24
Src/Unity/Scripts/Entity/World/EntityLOD.cs
Normal file
24
Src/Unity/Scripts/Entity/World/EntityLOD.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITKit.Entities;
|
||||
using Quadtree;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class EntityLOD : EntityBehavior,IWorldChunkObject
|
||||
{
|
||||
public Bounds GetBounds()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public int Lod { get; set; }
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Entity/World/EntityLOD.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/World/EntityLOD.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcd183d2a785322429c5e0e964591d82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user