Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
c1f51826b3 |
|
@ -3,12 +3,15 @@
|
|||
namespace BITKit
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class BITCommandAttribute : Attribute { }
|
||||
public class BITCommandAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动注入依赖
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class InjectAttribute : System.Attribute
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class InjectAttribute : Attribute
|
||||
{
|
||||
public static void Clear(object obj)
|
||||
{
|
||||
|
|
|
@ -125,6 +125,29 @@ namespace BITKit
|
|||
/// <param name="obj"></param>
|
||||
public static void Inject(object obj)
|
||||
{
|
||||
foreach (var propertyInfo in obj.GetType().GetProperties(ReflectionHelper.Flags))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (propertyInfo.GetCustomAttribute<ObsoleteAttribute>() is null &&
|
||||
propertyInfo.GetCustomAttribute<InjectAttribute>() is not null)
|
||||
{
|
||||
lock (dictionary)
|
||||
{
|
||||
if(dictionary!.TryGetValue(propertyInfo.PropertyType,out var value))
|
||||
{
|
||||
BIT4Log.Log<DI>($"已为{obj.GetType().Name}.{propertyInfo.Name}注入{value.GetType().Name}");
|
||||
propertyInfo.SetValue(obj,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
foreach (var field in obj.GetType().GetFields(ReflectionHelper.Flags))
|
||||
{
|
||||
try
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace BITKit.Entities
|
|||
/// 等待初始化完成,通常用于其他系统需要等待实体初始化完成
|
||||
/// </summary>
|
||||
void WaitForInitializationComplete();
|
||||
ulong Id { get; }
|
||||
int Id { get; }
|
||||
CancellationToken CancellationToken { get; }
|
||||
bool TryGetComponent<T>(out T component);
|
||||
IEntityComponent[] Components { get; }
|
||||
|
@ -81,18 +81,18 @@ namespace BITKit.Entities
|
|||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
IEntity Get(ulong id);
|
||||
IEntity Get(int id);
|
||||
/// <summary>
|
||||
/// 尝试通过Id获取Entity
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
bool TryGetEntity(ulong id, out IEntity entity);
|
||||
bool TryGetEntity(int id, out IEntity entity);
|
||||
/// <summary>
|
||||
/// 通过Id获取或添加Entity
|
||||
/// </summary>
|
||||
IEntity GetOrAdd(ulong id,Func<ulong,IEntity> factory);
|
||||
IEntity GetOrAdd(int id,Func<int,IEntity> factory);
|
||||
|
||||
/// <summary>
|
||||
/// 查询Entity,例如
|
||||
|
|
|
@ -220,7 +220,6 @@ namespace BITKit.Mod
|
|||
private static Thread _Thread;
|
||||
private static bool _IsRunning;
|
||||
private static bool _IsLocked;
|
||||
private static AppDomain _ModDomain;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
|
@ -241,8 +240,6 @@ namespace BITKit.Mod
|
|||
|
||||
try
|
||||
{
|
||||
_ModDomain = AppDomain.CreateDomain("ModDomain");
|
||||
|
||||
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\");
|
||||
PathHelper.EnsureDirectoryCreated(modPath);
|
||||
var directoryInfo = new DirectoryInfo(modPath);
|
||||
|
@ -383,7 +380,6 @@ namespace BITKit.Mod
|
|||
_UnRegisterQueue.Clear();
|
||||
Mods = Array.Empty<IMod>();
|
||||
_InstalledMods.Clear();
|
||||
AppDomain.Unload(_ModDomain);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,15 @@
|
|||
"interactions": "Press,Tap",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "Crawl",
|
||||
"type": "Button",
|
||||
"id": "350ae177-bf96-40b1-aff0-e10865947df9",
|
||||
"expectedControlType": "Button",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "HoldCrouch",
|
||||
"type": "Button",
|
||||
|
@ -570,6 +579,17 @@
|
|||
"action": "Inspect",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "a533436d-c3bf-4cb3-93b2-1ca02791e6d1",
|
||||
"path": "<Keyboard>/leftCtrl",
|
||||
"interactions": "Press,Hold",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "Crawl",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -6,10 +6,10 @@ namespace BITKit
|
|||
public class AnimatorHelper : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform root;
|
||||
|
||||
[SerializeField] private bool allowAnimatorMove;
|
||||
private void OnAnimatorMove()
|
||||
{
|
||||
if (root)
|
||||
if (root && allowAnimatorMove)
|
||||
root.SendMessageUpwards(nameof(OnAnimatorMove),SendMessageOptions.DontRequireReceiver);
|
||||
}
|
||||
private void AIAnimationEvent(string actionName)
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace BITKit.Entities
|
|||
/// </summary>
|
||||
public interface IEntityMovement:IStateMachine<IEntityMovementState>
|
||||
{
|
||||
Vector3 Size => Vector3.one;
|
||||
float ReferenceSpeed => 2.5f;
|
||||
Vector3 Position { get; set; }
|
||||
Quaternion Rotation { get; set; }
|
||||
|
@ -138,5 +139,6 @@ namespace BITKit.Entities
|
|||
void BeforeUpdateMovement(float deltaTime);
|
||||
void AfterUpdateMovement(float deltaTime);
|
||||
void ExecuteCommand<T>(T command);
|
||||
void DrawGizmos();
|
||||
}
|
||||
}
|
|
@ -81,8 +81,8 @@ namespace BITKit.Entities
|
|||
{
|
||||
public override DamageMessage ReadBinary(BinaryReader reader)
|
||||
{
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var initiator);
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var target);
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var initiator);
|
||||
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var target);
|
||||
return new DamageMessage()
|
||||
{
|
||||
Initiator = initiator as Entity,
|
||||
|
|
|
@ -3,7 +3,9 @@ using System.Collections.Generic;
|
|||
using BITFALL.Rig;
|
||||
using BITKit.Entities;
|
||||
using Cysharp.Threading.Tasks.Triggers;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit
|
||||
|
@ -14,6 +16,7 @@ namespace BITKit
|
|||
[SerializeField] private EntityHitbox[] hitboxes;
|
||||
|
||||
[SerializeReference,SubclassSelector] private IReference[] tagReferences;
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
private void Build()
|
||||
{
|
||||
|
@ -73,5 +76,6 @@ namespace BITKit
|
|||
}
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace BITKit.Entities
|
|||
private readonly GenericEvent genericEvent = new();
|
||||
|
||||
|
||||
public ulong Id { get; set; }
|
||||
public int Id { get; set; }
|
||||
public CancellationToken CancellationToken { get; private set; }
|
||||
public IEntityBehavior[] Behaviors { get;private set; }
|
||||
public IEntityComponent[] Components => Behaviors.Cast<IEntityComponent>().ToArray();
|
||||
|
@ -33,9 +33,43 @@ namespace BITKit.Entities
|
|||
IServiceProvider Entities.IEntity.ServiceProvider=> throw new InvalidOperationException("Unity Entity can't register component");
|
||||
public void Inject(object obj)
|
||||
{
|
||||
foreach (var propertyInfo in obj
|
||||
.GetType()
|
||||
.GetProperties(ReflectionHelper.Flags)
|
||||
.Where(x=>x.GetCustomAttribute<InjectAttribute>(true) is not null))
|
||||
{
|
||||
var type = propertyInfo.PropertyType;
|
||||
var attribute = propertyInfo.GetCustomAttribute<InjectAttribute>();
|
||||
var currentValue = propertyInfo.GetValue(obj);
|
||||
try
|
||||
{
|
||||
switch (currentValue)
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case 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))
|
||||
{
|
||||
propertyInfo.SetValue(obj,value,null);
|
||||
}
|
||||
else if(attribute?.CanBeNull is false)
|
||||
{
|
||||
BIT4Log.Warning<Entity>($"{name}未找到{obj.GetType().Name}需要的{type.FullName}");
|
||||
}
|
||||
}
|
||||
foreach (var fieldInfo in obj
|
||||
.GetType()
|
||||
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.GetFields(ReflectionHelper.Flags)
|
||||
.Where(fieldInfo=>fieldInfo.GetCustomAttribute<InjectAttribute>(true) is not null))
|
||||
{
|
||||
var type = fieldInfo.FieldType;
|
||||
|
@ -97,7 +131,7 @@ namespace BITKit.Entities
|
|||
private void Awake()
|
||||
{
|
||||
if (Id.IsDefault())
|
||||
Id = (ulong)Guid.NewGuid().GetHashCode();
|
||||
Id = GetInstanceID();
|
||||
CancellationToken = gameObject.GetCancellationTokenOnDestroy();
|
||||
Set(CancellationToken);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,13 @@ namespace BITKit.Entities
|
|||
stateMachine.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDestroyComponent()
|
||||
{
|
||||
base.OnDestroyComponent();
|
||||
CurrentState?.OnStateExit(CurrentState,null);
|
||||
}
|
||||
|
||||
void IStateMachine<T>.Initialize()
|
||||
{
|
||||
stateMachine.Initialize();
|
||||
|
|
|
@ -38,10 +38,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 Get(int id) => UnityEntitiesService.Get(id);
|
||||
public bool TryGetEntity(int id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity);
|
||||
|
||||
public IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>UnityEntitiesService.GetOrAdd(id,factory);
|
||||
public IEntity GetOrAdd(int id, Func<int, IEntity> factory)=>UnityEntitiesService.GetOrAdd(id,factory);
|
||||
|
||||
|
||||
public IEntity[] Query<T>()
|
||||
|
@ -85,7 +85,7 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService
|
|||
return false;
|
||||
}
|
||||
public static CancellationToken CancellationToken;
|
||||
private static readonly ConcurrentDictionary<ulong,IEntity> Dictionary=new();
|
||||
private static readonly ConcurrentDictionary<int,IEntity> Dictionary=new();
|
||||
private static readonly Queue<IEntity> RegisterQueue = new();
|
||||
private static readonly Queue<IEntity> UnRegisterQueue = new();
|
||||
private void Awake()
|
||||
|
@ -126,18 +126,18 @@ 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)
|
||||
public static IEntity Get(int id)=>Dictionary[id];
|
||||
IEntity IEntitiesService.Get(int id)=>Get(id);
|
||||
public static bool TryGetEntity(int 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)
|
||||
bool IEntitiesService.TryGetEntity(int id, out IEntity entity)=>TryGetEntity(id,out entity);
|
||||
public static IEntity GetOrAdd(int id, Func<int, IEntity> factory)
|
||||
{
|
||||
return Dictionary.GetOrAdd(id, factory);
|
||||
}
|
||||
IEntity IEntitiesService.GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>GetOrAdd(id,factory);
|
||||
IEntity IEntitiesService.GetOrAdd(int id, Func<int, IEntity> factory)=>GetOrAdd(id,factory);
|
||||
|
||||
IEntity[] IEntitiesService.Query<T>()=>Query<T>();
|
||||
public static IEntity[] Query<T>()
|
||||
|
|
|
@ -7,14 +7,14 @@ namespace BITKit.Entities
|
|||
{
|
||||
public interface IdComponent
|
||||
{
|
||||
ulong Id { get; }
|
||||
int Id { get; }
|
||||
string Name { get; }
|
||||
}
|
||||
public class UnityIdComponent : EntityBehavior,IdComponent
|
||||
{
|
||||
[SerializeField] private ulong id;
|
||||
[SerializeField] private int id;
|
||||
[SerializeField] private string unityName;
|
||||
public ulong Id => id;
|
||||
public int Id => id;
|
||||
public string Name => unityName;
|
||||
public override void Initialize(IEntity _entity)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace BITKit.Entities
|
|||
public struct EntitiesNetSyncBatchCommand
|
||||
{
|
||||
public int Length;
|
||||
public ulong[] Ids;
|
||||
public int[] Ids;
|
||||
public ulong[] AddressablePaths;
|
||||
public EntitiesNetSyncCommand[] Commands;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ namespace BITKit.Entities
|
|||
{
|
||||
using var ms = new MemoryStream(obj.Data);
|
||||
using var reader = new BinaryReader(ms);
|
||||
var id = reader.ReadUInt64();
|
||||
var id = reader.ReadInt32();
|
||||
var path = reader.ReadUInt64();
|
||||
entitiesService.GetOrAdd(id, x => AddEntity(id, path)).TryGetComponent<IEntityBinaryHeader>(out var header);
|
||||
header.Deserialize(reader);
|
||||
|
@ -100,7 +100,7 @@ namespace BITKit.Entities
|
|||
header.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
private static IEntity AddEntity(ulong id,ulong addressableId)
|
||||
private static IEntity AddEntity(int id,ulong addressableId)
|
||||
{
|
||||
var entity = AddressableHelper.Get<GameObject>(addressableId);
|
||||
var instance = Instantiate(entity).GetComponent<Entity>();
|
||||
|
@ -146,7 +146,7 @@ namespace BITKit.Entities
|
|||
var batchCommand = new EntitiesNetSyncBatchCommand()
|
||||
{
|
||||
Length = headers.Length,
|
||||
Ids = new ulong[headers.Length],
|
||||
Ids = new int[headers.Length],
|
||||
AddressablePaths = new ulong[headers.Length],
|
||||
Commands = new EntitiesNetSyncCommand[headers.Length]
|
||||
};
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace BITKit.Entities.Player
|
|||
[SerializeField] private MonoStateMachine<T> stateMachine;
|
||||
public override void OnAwake()
|
||||
{
|
||||
stateMachine?.Initialize();
|
||||
base.OnAwake();
|
||||
stateMachine?.Initialize();
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
|
|
|
@ -3,57 +3,121 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
public interface IClosePoint
|
||||
{
|
||||
Vector3 CurrentPoint { get; }
|
||||
Collider Collider { get; }
|
||||
bool TryGetClosePoint(out Vector3 vector3);
|
||||
}
|
||||
[System.Serializable]
|
||||
[Serializable]
|
||||
public class GetClosePointFromCollider : IClosePoint
|
||||
{
|
||||
public Transform root;
|
||||
public LayerMask layerMask;
|
||||
public float distance;
|
||||
[SerializeField] private string name;
|
||||
[SerializeField] private Transform transform;
|
||||
[SerializeField] private Vector3 offset = Vector3.one;
|
||||
[SerializeField] private LayerMask layerMask;
|
||||
[SerializeField] private float distance;
|
||||
[SerializeField] private float minHeight=0.32f;
|
||||
[SerializeField] private float maxHeight = 1f;
|
||||
public Vector3 CurrentPoint { get; set; }
|
||||
public Collider Collider { get; set; }
|
||||
|
||||
private Collider[] _colliders=new Collider[8];
|
||||
private Collider[] _mainCollider=new Collider[8];
|
||||
public bool TryGetClosePoint(out Vector3 vector3)
|
||||
{
|
||||
vector3 = default;
|
||||
if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask))
|
||||
StringBuilder reportBuilder = new();
|
||||
reportBuilder.AppendLine($"检测任务:{name}");
|
||||
var position = transform.position + transform.rotation * offset;
|
||||
var detectedLength = Physics.OverlapSphereNonAlloc(position, distance, _mainCollider, layerMask);
|
||||
reportBuilder.AppendLine($"检测到了{detectedLength}个碰撞体");
|
||||
for (var i = 0; i <detectedLength ; i++)
|
||||
{
|
||||
var collider = raycastHit.collider;
|
||||
if (collider.isTrigger) return false;
|
||||
reportBuilder.AppendLine($"----------------------------检测到了碰撞体{_mainCollider[i].name}");
|
||||
var collider = _mainCollider[i];
|
||||
if (collider.isTrigger)
|
||||
{
|
||||
reportBuilder?.AppendLine("碰撞体是触发器");
|
||||
continue;
|
||||
}
|
||||
switch (collider)
|
||||
{
|
||||
case MeshCollider meshCollider:
|
||||
if (meshCollider.convex is false)
|
||||
return false;
|
||||
{
|
||||
reportBuilder?.AppendLine("MeshCollider未勾选Convex");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
vector3 = collider.ClosestPoint(root.position + Vector3.up);
|
||||
var top = collider.bounds.center + collider.bounds.extents;
|
||||
var bounds = collider.bounds;
|
||||
vector3 = collider.ClosestPoint(transform.position + Vector3.up*64);
|
||||
var top = bounds.center.y + bounds.extents.y;
|
||||
Debug.DrawLine(transform.position,transform.position + Vector3.up * top,Color.blue,8f);
|
||||
if (transform.position.y + minHeight > top)
|
||||
{
|
||||
reportBuilder?.AppendLine("高度不足");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Mathf.Abs(vector3.y - top.y) > 0.16f) return false;
|
||||
|
||||
if (UnityEngine.Physics.Linecast(root.position, vector3, out var raycastHit2, layerMask))
|
||||
var nextPos = position;
|
||||
nextPos.y = collider.bounds.center.y;
|
||||
if (collider.Raycast(new Ray(nextPos, transform.forward), out _, distance) is false)
|
||||
{
|
||||
reportBuilder?.AppendLine("未检测到前方");
|
||||
continue;
|
||||
}
|
||||
var height = Mathf.Abs(top - transform.position.y);
|
||||
if (height > maxHeight)
|
||||
{
|
||||
reportBuilder?.AppendLine($"高度差距过大:{height}");
|
||||
continue;
|
||||
}
|
||||
if (Physics.Linecast(transform.position, vector3, out var raycastHit2, layerMask))
|
||||
{
|
||||
if (raycastHit2.collider != collider)
|
||||
return false;
|
||||
};
|
||||
foreach(var hit in UnityEngine.Physics.OverlapSphere(vector3, 0.1f, layerMask))
|
||||
{
|
||||
if(hit!= collider)
|
||||
return false;
|
||||
reportBuilder?.AppendLine($"检测到了其他碰撞体:{raycastHit2.transform.name}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
var length = Physics.OverlapSphereNonAlloc(vector3, 0.01f, _colliders, layerMask);
|
||||
switch (length)
|
||||
{
|
||||
case 1:
|
||||
if (_colliders[0] != collider)
|
||||
{
|
||||
reportBuilder.AppendLine($"检测到了其他碰撞体{_colliders[0].name}");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case > 1:
|
||||
reportBuilder.AppendLine("检测到了更多碰撞体");
|
||||
for (var ii = 0; ii < length; ii++)
|
||||
{
|
||||
//Debug.DrawLine(vector3, _colliders[ii].ClosestPoint(vector3), Color.red, 8);
|
||||
reportBuilder.AppendLine($"\t{_colliders[ii].name}");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Collider = collider;
|
||||
|
||||
vector3.y = top;
|
||||
CurrentPoint = vector3;
|
||||
|
||||
|
||||
|
||||
reportBuilder.AppendLine("<color=green>成功</color>");
|
||||
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
|
||||
return true;
|
||||
//return vector3.y >= collider.bounds.center.y + collider.bounds.extents.y;
|
||||
//return true;
|
||||
}
|
||||
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +138,7 @@ namespace BITKit
|
|||
public Vector3 StartPosition;
|
||||
public Vector3 EndPosition;
|
||||
|
||||
public Vector3 CurrentPoint { get; set; }
|
||||
public Collider Collider { get; set; }
|
||||
private Rigidbody rigidbody;
|
||||
|
||||
|
@ -92,7 +157,8 @@ namespace BITKit
|
|||
if (rigidbody.velocity.GetLength() < 0.1f) return false;
|
||||
}
|
||||
|
||||
var reportBuilder = new System.Text.StringBuilder();
|
||||
//var reportBuilder = new System.Text.StringBuilder();
|
||||
StringBuilder reportBuilder=null;
|
||||
|
||||
var forward = root.forward;
|
||||
var sourceStartPosition = groundReference.position;
|
||||
|
@ -101,7 +167,7 @@ namespace BITKit
|
|||
|
||||
var collider = UnityEngine.Physics.OverlapSphere(startPosition, radius, layerMask);
|
||||
|
||||
reportBuilder.AppendLine($"检测到了{collider.Length}个碰撞体");
|
||||
reportBuilder?.AppendLine($"检测到了{collider.Length}个碰撞体");
|
||||
|
||||
foreach (var hit in collider)
|
||||
{
|
||||
|
@ -112,12 +178,12 @@ namespace BITKit
|
|||
continue;
|
||||
}
|
||||
|
||||
reportBuilder.AppendLine();
|
||||
reportBuilder.AppendLine($">{hit.name}");
|
||||
reportBuilder?.AppendLine();
|
||||
reportBuilder?.AppendLine($">{hit.name}");
|
||||
|
||||
if(top.y>groundReference.transform.position.y+maxHeight)
|
||||
{
|
||||
reportBuilder.AppendLine("高度超出可翻越高度");
|
||||
reportBuilder?.AppendLine("高度超出可翻越高度");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -128,9 +194,9 @@ namespace BITKit
|
|||
|
||||
if (hit.Raycast(ray, out var colliderHit, 8) is false)
|
||||
{
|
||||
reportBuilder.AppendLine("未检测到背面,算法错误");
|
||||
reportBuilder?.AppendLine("未检测到背面,算法错误");
|
||||
|
||||
Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8);
|
||||
//Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -151,15 +217,15 @@ namespace BITKit
|
|||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
reportBuilder.AppendLine(e.Message);
|
||||
reportBuilder?.AppendLine(e.Message);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(UnityEngine.Physics.Raycast(EndPosition,Vector3.down,out _,1.6f,layerMask) is false)
|
||||
{
|
||||
Debug.DrawRay(EndPosition, Vector3.down*1.6f, Color.red, 8);
|
||||
reportBuilder.AppendLine("未检测到地面,跳过");
|
||||
//Debug.DrawRay(EndPosition, Vector3.down*1.6f, Color.red, 8);
|
||||
reportBuilder?.AppendLine("未检测到地面,跳过");
|
||||
continue;
|
||||
//Debug.DrawRay(EndPosition, Vector3.down, Color.red, 8);
|
||||
}
|
||||
|
@ -174,7 +240,7 @@ namespace BITKit
|
|||
end2.y -= 0.1f;
|
||||
if(UnityEngine.Physics.Linecast(start2,end2,out var downHit,layerMask))
|
||||
{
|
||||
reportBuilder.AppendLine($"检测到了障碍物{downHit.collider.name}");
|
||||
reportBuilder?.AppendLine($"检测到了障碍物{downHit.collider.name}");
|
||||
|
||||
//BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
||||
continue;
|
||||
|
@ -186,8 +252,8 @@ namespace BITKit
|
|||
ray = new Ray(start, forward);
|
||||
if(hit.Raycast(ray,out colliderHit,8) is false)
|
||||
{
|
||||
reportBuilder.AppendLine("未检测到正面,算法错误");
|
||||
Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8);
|
||||
reportBuilder?.AppendLine("未检测到正面,算法错误");
|
||||
//Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -200,14 +266,26 @@ namespace BITKit
|
|||
var lineDistance = Vector3.Distance(closeStart, closeEnd);
|
||||
if(lineDistance > maxVaultDistance)
|
||||
{
|
||||
reportBuilder.AppendLine($"长度{lineDistance}超出可翻越距离{maxVaultDistance}");
|
||||
reportBuilder?.AppendLine($"长度{lineDistance}超出可翻越距离{maxVaultDistance}");
|
||||
|
||||
Debug.DrawLine(closeStart,closeEnd, Color.yellow, 4);
|
||||
//Debug.DrawLine(closeStart,closeEnd, Color.yellow, 4);
|
||||
|
||||
//BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(Physics.Linecast(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f,out var _hit,layerMask))
|
||||
{
|
||||
|
||||
//Debug.DrawLine(closeStart+Vector3.up*0.1f,_hit.point, Color.red, 4);
|
||||
reportBuilder?.AppendLine("检测到了障碍物");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Debug.DrawLine(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f, Color.green, 4);
|
||||
}
|
||||
|
||||
vector3 = colliderHit.point;
|
||||
|
||||
|
||||
|
@ -215,14 +293,19 @@ namespace BITKit
|
|||
|
||||
vector3 += colliderHit.normal * 0.4f;
|
||||
|
||||
reportBuilder.AppendLine();
|
||||
reportBuilder?.AppendLine();
|
||||
|
||||
if(reportBuilder is not null)
|
||||
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
||||
|
||||
CurrentPoint = vector3;
|
||||
Collider = hit;
|
||||
return true;
|
||||
}
|
||||
|
||||
reportBuilder.AppendLine($"failed");
|
||||
reportBuilder?.AppendLine($"failed");
|
||||
|
||||
if(reportBuilder is not null)
|
||||
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
||||
|
||||
vector3 = default;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Quadtree
|
||||
{
|
||||
|
@ -405,10 +407,12 @@ namespace Quadtree
|
|||
|
||||
public void DrawBounds(bool displayNumberOfItems = false)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (displayNumberOfItems)
|
||||
Handles.Label(Bounds.center, _items.Count.ToString());
|
||||
|
||||
Gizmos.DrawWireCube(Bounds.center, Bounds.size);
|
||||
#endif
|
||||
foreach (var subNode in SubNodes)
|
||||
subNode.DrawBounds(displayNumberOfItems);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ using Cysharp.Threading.Tasks;
|
|||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using System.Linq;
|
||||
using UnityEditor.Search;
|
||||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
|
@ -19,6 +18,8 @@ namespace BITKit.Sensors
|
|||
[SerializeField] private bool autoUpdate;
|
||||
[SerializeField]private float radius;
|
||||
private readonly CacheList<Transform> cache = new();
|
||||
private readonly CacheList<AudioSensorService.AudioSensorData> data = new();
|
||||
public AudioSensorService.AudioSensorData[] Noises => data.ValueArray;
|
||||
private void OnEnable()
|
||||
{
|
||||
Id = GetInstanceID();
|
||||
|
@ -32,14 +33,19 @@ namespace BITKit.Sensors
|
|||
{
|
||||
var position = transform.position;
|
||||
cache.Clear();
|
||||
data.Clear();
|
||||
foreach (var x in AudioSensorService.QuadtreeRoot.Find(new Bounds(position, Vector3.one * radius)))
|
||||
{
|
||||
var distance = Vector3.Distance(position, x.Position);
|
||||
if (distance > radius) continue;
|
||||
if (x.Transform)
|
||||
cache.Add(x.Transform);
|
||||
data.Add(x);
|
||||
}
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
public HashSet<int> Ignores { get; } = new();
|
||||
public int Id { get; set; }
|
||||
public IEnumerable<Transform> Get() => cache.ValueArray;
|
||||
public bool IsValid(Collider _collider) => false;
|
||||
|
|
|
@ -10,6 +10,7 @@ using UnityEngine.Pool;
|
|||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
public struct ClassicNoise{}
|
||||
public class AudioSensorService : MonoBehaviour
|
||||
{
|
||||
public class AudioSensorData:IItem<AudioSensorData,Node<AudioSensorData>>
|
||||
|
@ -20,6 +21,7 @@ namespace BITKit.Sensors
|
|||
public Transform Transform;
|
||||
public Bounds Bounds;
|
||||
public ITag Tag;
|
||||
public object NoiseType;
|
||||
public Bounds GetBounds() => Bounds;
|
||||
public Node<AudioSensorData> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<AudioSensorData, Node<AudioSensorData>> root){}
|
||||
|
@ -29,20 +31,25 @@ namespace BITKit.Sensors
|
|||
|
||||
private static Pool<AudioSensorData> pool = new(()=>new(), x=>{}, 1000);
|
||||
private static int count;
|
||||
public static async void MakeNoise(Vector3 position,Transform transform)
|
||||
|
||||
public static async void MakeNoise(Vector3 position, Transform transform, float radius = 1,
|
||||
object noiseType = null)
|
||||
{
|
||||
var data = pool.Take();
|
||||
data.Id = count++;
|
||||
data.Position = position;
|
||||
data.Transform = transform;
|
||||
data.Bounds = new Bounds(position, Vector3.one * 1);
|
||||
if (transform)
|
||||
data.Tag = transform.GetComponent<ITag>();
|
||||
data.Radius = radius;
|
||||
QuadtreeRoot.Insert(data);
|
||||
await UniTask.Delay(3000);
|
||||
if (disposed) return;
|
||||
QuadtreeRoot.Remove(data);
|
||||
pool.Return(data);
|
||||
}
|
||||
|
||||
private static bool disposed;
|
||||
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||
private void Start()
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace BITKit.Sensors
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
UniTask Execute(float delta);
|
||||
HashSet<int> Ignores{ get; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@ -74,6 +75,7 @@ namespace BITKit.Sensors
|
|||
{
|
||||
return _sensorImplementation.Execute(delta);
|
||||
}
|
||||
public HashSet<int> Ignores => _sensorImplementation.Ignores;
|
||||
}
|
||||
[System.Serializable]
|
||||
public class SensorMonoProxy:ISensor
|
||||
|
@ -101,6 +103,7 @@ namespace BITKit.Sensors
|
|||
{
|
||||
return _sensorImplementation.Execute(delta);
|
||||
}
|
||||
public HashSet<int> Ignores => _sensorImplementation.Ignores;
|
||||
}
|
||||
public abstract class Sensor : MonoBehaviour, ISensor
|
||||
{
|
||||
|
@ -109,13 +112,11 @@ namespace BITKit.Sensors
|
|||
public bool autoUpdate;
|
||||
[Header(Constant.Header.Gameobjects)]
|
||||
public Collider[] ignoreColliders;
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
[SerializeField,ReadOnly]
|
||||
public Transform[] detected = Array.Empty<Transform>();
|
||||
public abstract IEnumerable<Transform> Get();
|
||||
public abstract bool IsValid(Collider _collider);
|
||||
public abstract float GetDistance();
|
||||
public virtual UniTask Execute(float delta)=>UniTask.CompletedTask;
|
||||
public HashSet<int> Ignores { get; } = new();
|
||||
public int Id { get; private set; }
|
||||
bool ISensor.AutoUpdate => autoUpdate;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine.Jobs;
|
||||
using UnityEngine.Pool;
|
||||
using UnityEngine.Profiling;
|
||||
|
@ -13,18 +14,22 @@ namespace BITKit.Sensors
|
|||
{
|
||||
public class RangeSensor : Sensor
|
||||
{
|
||||
[Header(Constant.Header.Settings)] public float radius;
|
||||
public int fov;
|
||||
public bool requireSight;
|
||||
|
||||
[Header(Constant.Header.Settings)] public LayerMask blockLayer;
|
||||
|
||||
[Header(Constant.Header.Debug)] [Header(Constant.Header.InternalVariables)]
|
||||
private FrameUpdate frameUpdater;
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private float radius;
|
||||
[SerializeField] private float detectedHeightWeight=0.5f;
|
||||
[Header(Constant.Header.Optional)]
|
||||
[SerializeField] private Optional<int> fov;
|
||||
[SerializeField] private Optional<LayerMask> requireSight;
|
||||
[SerializeField] private Optional<float> perceptionRadius;
|
||||
|
||||
public float DetectedHeightWeight
|
||||
{
|
||||
get=>detectedHeightWeight;
|
||||
set=>detectedHeightWeight=value;
|
||||
}
|
||||
private readonly Collider[] colliders = new Collider[32];
|
||||
private RaycastHit[] hits = new RaycastHit[32];
|
||||
private readonly HashSet<int> tempHashSet = new();
|
||||
private readonly RaycastHit[] hits = new RaycastHit[32];
|
||||
private float _delta;
|
||||
|
||||
public override IEnumerable<Transform> Get()
|
||||
{
|
||||
|
@ -40,7 +45,7 @@ namespace BITKit.Sensors
|
|||
|
||||
public override UniTask Execute(float delta)
|
||||
{
|
||||
tempHashSet.Clear();
|
||||
_delta = delta;
|
||||
var length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer);
|
||||
Profiler.BeginSample("Filter Detected Colliders");
|
||||
var _newDetected = from x in colliders.Take(length) where IsValid(x) select x.transform;
|
||||
|
@ -53,10 +58,21 @@ namespace BITKit.Sensors
|
|||
{
|
||||
switch (_collider)
|
||||
{
|
||||
case var _ when Ignores.Contains(_collider.GetInstanceID()):
|
||||
case var _ when ignoreColliders.Contains(_collider):
|
||||
return false;
|
||||
case var _ when fov > 0 && CheckFov(ref _collider) is false:
|
||||
case var _ when requireSight && CheckSight(ref _collider) is false:
|
||||
}
|
||||
|
||||
if (perceptionRadius.Allow)
|
||||
{
|
||||
var distance = Vector3.Distance(Transform.position, _collider.bounds.center);
|
||||
if(distance<=perceptionRadius.Value) return !requireSight.Allow || CheckSight(ref _collider);
|
||||
}
|
||||
switch (_collider)
|
||||
{
|
||||
|
||||
case var _ when fov.Allow && CheckFov(ref _collider) is false:
|
||||
case var _ when requireSight.Allow && CheckSight(ref _collider) is false:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
@ -75,23 +91,21 @@ namespace BITKit.Sensors
|
|||
|
||||
private bool CheckSight(ref Collider _collider)
|
||||
{
|
||||
if (!requireSight) return false;
|
||||
var position = _collider.bounds.center;
|
||||
//是检测bounds的顶部
|
||||
position.y += _collider.bounds.extents.y;
|
||||
var location = new Location(Transform);
|
||||
var bounds = _collider.bounds;
|
||||
var position = bounds.center;
|
||||
position.y += bounds.size.y * detectedHeightWeight /2;
|
||||
var selfPosition = Transform.position;
|
||||
var length = Physics.RaycastNonAlloc(
|
||||
location.position,
|
||||
position - location,
|
||||
selfPosition,
|
||||
position - selfPosition,
|
||||
hits,
|
||||
Vector3.Distance(location, position),
|
||||
blockLayer
|
||||
Vector3.Distance(selfPosition, position),
|
||||
requireSight.Value
|
||||
);
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case 0:
|
||||
Debug.DrawLine(location, position, Color.green, 1);
|
||||
Debug.DrawLine(selfPosition, position, Color.green,_delta);
|
||||
return true;
|
||||
case 1:
|
||||
return hits[0].collider == _collider;
|
||||
|
@ -107,7 +121,8 @@ namespace BITKit.Sensors
|
|||
var result = ignoreColliders.Contains(x.collider) is false && x.collider != collider1;
|
||||
if (result)
|
||||
{
|
||||
Debug.DrawLine(location, x.point, Color.red, 1);
|
||||
Debug.DrawLine(selfPosition, x.point, Color.yellow,_delta);
|
||||
Debug.DrawLine(selfPosition, position, Color.red,_delta);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
|
@ -11,8 +13,11 @@ namespace BITKit.Sensors
|
|||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private float radius = 0.16f;
|
||||
public float distance;
|
||||
public override IEnumerable<Transform> Get() => detected;
|
||||
public override IEnumerable<Transform> Get() => detected.ValueArray;
|
||||
private readonly RaycastHit[] raycasts = new RaycastHit[16];
|
||||
private readonly Queue<(Vector3,Vector3)> _drawGizmosQueue = new();
|
||||
private readonly CacheList<Transform> detected = new();
|
||||
|
||||
public override UniTask Execute(float delta)
|
||||
{
|
||||
var _transform = transform;
|
||||
|
@ -31,22 +36,40 @@ namespace BITKit.Sensors
|
|||
var ray = new Ray(_transform.position, _transform.forward);
|
||||
size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer);
|
||||
}
|
||||
//var reportBuilder = new StringBuilder();
|
||||
|
||||
detected = raycasts
|
||||
detected.Clear();
|
||||
foreach (var hit in raycasts
|
||||
.Take(size)
|
||||
.Select(x => x.collider)
|
||||
.Where(IsValid)
|
||||
.Select(x=>x.transform)
|
||||
.ToArray();
|
||||
return UniTask.CompletedTask;
|
||||
.OrderBy(ByDistance))
|
||||
{
|
||||
detected.Add(hit.transform);
|
||||
}
|
||||
|
||||
//Debug.Log(reportBuilder);
|
||||
return UniTask.CompletedTask;
|
||||
|
||||
float ByDistance(RaycastHit arg)
|
||||
{
|
||||
var x = Vector3.Distance(arg.point, position);
|
||||
//_drawGizmosQueue.Enqueue(new(arg.collider.bounds.center, arg.point));
|
||||
//reportBuilder.AppendLine($"Name:{arg.collider.name},Distance:{x}");
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid(RaycastHit hit) => IsValid(hit.collider);
|
||||
public override bool IsValid(Collider _collider) => ignoreColliders.Contains(_collider) is false;
|
||||
public override float GetDistance() => distance;
|
||||
private void Update()
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (autoUpdate)
|
||||
while (_drawGizmosQueue.TryDequeue(out var p))
|
||||
{
|
||||
Execute(Time.deltaTime).Forget();
|
||||
var (closePoint, point) = p;
|
||||
Gizmos.DrawWireCube(point,Vector3.one*0.01f);
|
||||
Gizmos.DrawLine(closePoint,point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ namespace BITKit.Sensors
|
|||
|
||||
[SerializeField,ReadOnly] private int _position;
|
||||
|
||||
private static int[] _keys;
|
||||
|
||||
public static void Register(int id,ISensor sensor)
|
||||
{
|
||||
Sensors.Add(id,sensor);
|
||||
|
@ -33,7 +31,6 @@ namespace BITKit.Sensors
|
|||
IsDirty = true;
|
||||
}
|
||||
|
||||
[SerializeField] private MonoBehaviour[] sensors;
|
||||
[SerializeReference,SubclassSelector] private ITicker ticker;
|
||||
|
||||
private bool _isBusy;
|
||||
|
@ -56,9 +53,7 @@ namespace BITKit.Sensors
|
|||
if(IsDirty)
|
||||
{
|
||||
_position = 0;
|
||||
_keys = Sensors.Where(IsEnabled).Select(x=>x.Key).ToArray();
|
||||
IsDirty = false;
|
||||
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
|
||||
}
|
||||
|
||||
if (Sensors.Count is 0)
|
||||
|
@ -68,26 +63,22 @@ namespace BITKit.Sensors
|
|||
}
|
||||
|
||||
var current = Sensors.ElementAt(_position++).Value;
|
||||
if (current.AutoUpdate)
|
||||
{
|
||||
|
||||
var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time);
|
||||
await current.Execute(Time.time-currentUpdateTime);
|
||||
float UpdateValueFactory(int key, float old) => Time.time;
|
||||
LastDetectedTime.AddOrUpdate(current.Id,Time.time,UpdateValueFactory);
|
||||
|
||||
if (destroyCancellationToken.IsCancellationRequested) {
|
||||
_isBusy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
_position %= Sensors.Count;
|
||||
_isBusy = false;
|
||||
}
|
||||
private bool IsEnabled(ISensor sensor)
|
||||
{
|
||||
return sensor.AutoUpdate;
|
||||
}
|
||||
private bool IsEnabled(KeyValuePair<int,ISensor> pair)
|
||||
{
|
||||
return pair.Value.AutoUpdate;
|
||||
return;
|
||||
float UpdateValueFactory(int key, float old) => Time.time;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace BITKit.Sensors
|
|||
[SerializeField] private AudioSensor audioSensor;
|
||||
public int Id { get; set; }
|
||||
private readonly CacheList<Transform> _detected=new();
|
||||
public HashSet<int> Ignores { get; } = new();
|
||||
private void OnEnable()
|
||||
{
|
||||
Id = GetInstanceID();
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace BITKit.Sensors
|
|||
[Header(Constant.Header.InternalVariables)]
|
||||
// ReSharper disable once FieldCanBeMadeReadOnly.Local
|
||||
private List<Collider> detected = new();
|
||||
public HashSet<int> Ignores { get; } = new();
|
||||
|
||||
private readonly Queue<Collider> triggerEnterQueue = new();
|
||||
private readonly Queue<Collider> triggerExitQueue = new();
|
||||
|
@ -171,7 +172,7 @@ namespace BITKit.Sensors
|
|||
if (!agent || detectedContainer is null) return;
|
||||
if (BITAppForUnity.IsPlaying is false) return;
|
||||
detectedContainer.Clear();
|
||||
foreach (var x in agent.detected)
|
||||
foreach (var x in agent.Get())
|
||||
{
|
||||
ObjectField objectField = new()
|
||||
{
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494"
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494",
|
||||
"GUID:1c2aa13aa706ffc49a1a0044cad55436"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using SkiaSharp;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.UX
|
||||
{
|
||||
public class SKPaintComponent : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Texture2D texture;
|
||||
[SerializeField] private float[] data;
|
||||
|
||||
[BIT]
|
||||
private void Draw()
|
||||
{
|
||||
var info = new SKImageInfo(
|
||||
width: 384,
|
||||
height: 128,
|
||||
colorType: SKColorType.Rgba8888,
|
||||
alphaType: SKAlphaType.Premul
|
||||
);
|
||||
|
||||
using var surface = SKSurface.Create(info);
|
||||
|
||||
|
||||
using var canvas = surface.Canvas;
|
||||
|
||||
//canvas.Clear(new Color32(31,31,31,255).ToSKColor());
|
||||
|
||||
using var linePaint = new SKPaint();
|
||||
linePaint.Color = new SKColor(255, 0, 0, 255);
|
||||
linePaint.StrokeWidth = 8;
|
||||
linePaint.IsAntialias = true;
|
||||
linePaint.Style = SKPaintStyle.Stroke;
|
||||
|
||||
using var helpLinePaint = new SKPaint();
|
||||
helpLinePaint.Color = new SKColor(200, 200, 200, 200);
|
||||
helpLinePaint.StrokeWidth = 4;
|
||||
helpLinePaint.Style = SKPaintStyle.Stroke;
|
||||
|
||||
using var textPaint = new SKPaint();
|
||||
textPaint.TextAlign = SKTextAlign.Center;
|
||||
textPaint.TextSize = 14;
|
||||
textPaint.ColorF = new SKColor(0, 255, 0, 255);
|
||||
|
||||
using var filePaint = new SKPaint();
|
||||
filePaint.Color = new SKColor(200, 200, 200, 200);
|
||||
filePaint.Style=SKPaintStyle.Fill;
|
||||
|
||||
var min = data.Min();
|
||||
var max = data.Max();
|
||||
|
||||
DoubleBuffer<SKPoint> buffer = new();
|
||||
|
||||
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
|
||||
path.MoveTo(0,0);
|
||||
path.LineTo(0,0);
|
||||
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
var value = data[i];
|
||||
var posX = (float)info.Width / (data.Length - 1) * (i);
|
||||
var d = max - min;
|
||||
var p = (value - min) / d;
|
||||
var poxY = info.Height * p;
|
||||
|
||||
var currentPoint = new SKPoint(posX, poxY);
|
||||
if (buffer.TryGetRelease(out var previousPoint))
|
||||
{
|
||||
canvas.DrawLine(previousPoint, currentPoint, linePaint);
|
||||
}
|
||||
|
||||
canvas.DrawText(
|
||||
value.ToString()
|
||||
, currentPoint
|
||||
, new SKFont(
|
||||
SKTypeface.FromFile(@"D:\Iris\Documents\GitHub\iFactory-YL106.Unity\Assets\BITKit\Unity\Art\Fonts\TTF\Roboto\Roboto-Regular.ttf")
|
||||
), textPaint);
|
||||
canvas.DrawLine(posX, 0, posX, poxY, helpLinePaint);
|
||||
|
||||
path.LineTo(posX,poxY);
|
||||
|
||||
buffer.Release(currentPoint);
|
||||
}
|
||||
|
||||
path.LineTo(info.Width,0);
|
||||
path.Close();
|
||||
|
||||
|
||||
//canvas.DrawPath(path,filePaint);
|
||||
|
||||
texture = info.ToTexture2D(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "BITKit.UX.Chart.Tests",
|
||||
"name": "BITKit.UX.Painter.Runtime",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
|
@ -9,7 +9,7 @@
|
|||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494",
|
||||
"GUID:994a3fb33a5627740b0712e7c483cc1f"
|
||||
"GUID:1c2aa13aa706ffc49a1a0044cad55436"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
|
@ -0,0 +1,104 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets.Kcp;
|
||||
using SkiaSharp;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace BITKit.UX
|
||||
{
|
||||
public class SkiaPainter : VisualElement
|
||||
{
|
||||
public new class UxmlFactory : UxmlFactory<SkiaPainter, UxmlTraits> { }
|
||||
public SkiaPainter()
|
||||
{
|
||||
RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
RegisterCallback<MouseDownEvent>(OnMouseDown);
|
||||
RegisterCallback<MouseUpEvent>(OnMouseUp);
|
||||
RegisterCallback<MouseMoveEvent>(OnMouseMove);
|
||||
}
|
||||
private bool _isPainting;
|
||||
private readonly List<Vector2> _points = new();
|
||||
private SKImageInfo _info;
|
||||
private SKCanvas _canvas;
|
||||
private SKSurface _surface;
|
||||
private Rect _rect;
|
||||
private readonly SKPaint _linePaint = new()
|
||||
{
|
||||
Style = SKPaintStyle.Stroke,
|
||||
Color = SKColors.Red,
|
||||
StrokeWidth = 5
|
||||
};
|
||||
public void ClearCanvas()
|
||||
{
|
||||
_points.Clear();
|
||||
Rebuild();
|
||||
}
|
||||
private void OnMouseMove(MouseMoveEvent evt)
|
||||
{
|
||||
if (_isPainting is false) return;
|
||||
var pos = evt.localMousePosition;
|
||||
pos.y = layout.height - pos.y;
|
||||
if (_rect.Contains(pos) is false)
|
||||
{
|
||||
var last = _points.LastOrDefault();
|
||||
if (last == default) return;
|
||||
_points.Add(default);
|
||||
return;
|
||||
}
|
||||
_points.Add(pos);
|
||||
Rebuild();
|
||||
}
|
||||
|
||||
private void OnMouseUp(MouseUpEvent evt)
|
||||
{
|
||||
_isPainting = false;
|
||||
var last = _points.LastOrDefault();
|
||||
if (last != default)
|
||||
_points.Add(default);
|
||||
}
|
||||
|
||||
private void OnMouseDown(MouseDownEvent evt)
|
||||
{
|
||||
_isPainting = true;
|
||||
}
|
||||
private void OnGeometryChanged(GeometryChangedEvent evt)
|
||||
{
|
||||
if(float.IsNaN(layout.width) || float.IsNaN(layout.height))
|
||||
return;
|
||||
_linePaint.Color = resolvedStyle.color.ToSKColor();
|
||||
_surface?.Dispose();
|
||||
_info = new SKImageInfo((int)layout.width, (int)layout.height);
|
||||
_surface = SKSurface.Create(_info);
|
||||
_canvas = _surface.Canvas;
|
||||
_rect = new Rect(0, 0, layout.width, layout.height);
|
||||
Rebuild();
|
||||
}
|
||||
private void Rebuild()
|
||||
{
|
||||
if (_canvas is null) return;
|
||||
_canvas.Clear();
|
||||
DoubleBuffer<Vector2> buffer = new();
|
||||
foreach (var pos in _points)
|
||||
{
|
||||
if (pos == default)
|
||||
{
|
||||
buffer.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer.TryGetRelease(out var previousPoint))
|
||||
{
|
||||
_canvas.DrawLine(previousPoint.x, previousPoint.y, pos.x, pos.y, _linePaint);
|
||||
}
|
||||
buffer.Release(pos);
|
||||
}
|
||||
}
|
||||
var texture = _info.ToTexture2D(_surface);
|
||||
style.backgroundImage = texture;
|
||||
}
|
||||
public string Base64 => _surface?.GetBase64();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,17 +4,12 @@ using UnityEngine;
|
|||
using UnityEngine.Events;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine.Networking;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text;
|
||||
using System.IO.Compression;
|
||||
using System.Data;
|
||||
using UnityEngine.UIElements;
|
||||
namespace BITKit
|
||||
{
|
||||
|
@ -402,18 +397,6 @@ namespace BITKit
|
|||
text = text.Remove(0, text.Split('\n')[0].Length + 1);
|
||||
return text;
|
||||
}
|
||||
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
asyncOp.completed += obj => { tcs.SetResult(null); };
|
||||
return ((Task)tcs.Task).GetAwaiter();
|
||||
}
|
||||
public static TaskAwaiter GetAwaiter(this System.Action action)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
action += () => { tcs.SetResult(null); };
|
||||
return ((Task)tcs.Task).GetAwaiter();
|
||||
}
|
||||
public static float GetDifference(this IEnumerable<float> self)
|
||||
{
|
||||
return self.Max() - self.Min();
|
||||
|
@ -665,14 +648,33 @@ namespace BITKit
|
|||
|
||||
public static Vector2 GetScreenPosition(this VisualElement self, Vector3 worldPosition)
|
||||
{
|
||||
try
|
||||
{
|
||||
var panel = self.panel;
|
||||
if (panel is null)
|
||||
{
|
||||
panel = self.parent.panel;
|
||||
}
|
||||
|
||||
if (panel is null)
|
||||
{
|
||||
panel = self.parent.parent.panel;
|
||||
}
|
||||
|
||||
var pos = RuntimePanelUtils
|
||||
.CameraTransformWorldToPanel(self.panel, worldPosition, Camera.main);
|
||||
.CameraTransformWorldToPanel(panel, worldPosition, Camera.main);
|
||||
|
||||
pos.x -= self.layout.width / 2;
|
||||
pos.y -= self.layout.height / 2;
|
||||
|
||||
return pos;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
public static Vector2 GetPosition(this VisualElement self)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace BITKit.OpenWorld
|
|||
base.OnLodChanged(oldLod, newLod);
|
||||
OnLodChangedEvent?.Invoke(oldLod,newLod);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
private void CalculateBounds()
|
||||
{
|
||||
|
@ -41,6 +41,7 @@ namespace BITKit.OpenWorld
|
|||
offset = bounds.center - transform.position;
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Quadtree;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.SceneManagement;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using YooAsset;
|
||||
|
@ -16,9 +18,7 @@ namespace BITKit.OpenWorld
|
|||
[SerializeField] private Vector3 size;
|
||||
[SerializeField] private Vector3 position;
|
||||
[SerializeField, ReadOnly] private int lod = -1;
|
||||
|
||||
private SceneHandle _sceneHandle;
|
||||
|
||||
[BIT]
|
||||
public async void Load()
|
||||
{
|
||||
|
|
|
@ -314,3 +314,6 @@ Label {
|
|||
.armorPlate-container:hover {
|
||||
background-color: rgba(255, 255, 255, 0.78);
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "BITKit.Extensions.SkiaSharp",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:6ef4ed8ff60a7aa4bb60a8030e6f4008",
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"_SkiaSharp"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SkiaSharp;
|
||||
using UnityEngine;
|
||||
|
||||
|
@ -31,5 +34,31 @@ namespace BITKit.UX
|
|||
{
|
||||
return new SKColor(color.r, color.g, color.b, color.a);
|
||||
}
|
||||
public static string GetBase64(this SKSurface self)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var image = self.Snapshot();
|
||||
using var data = image.Encode(SKEncodedImageFormat.Png, 50);
|
||||
//using var stream = File.OpenWrite(exportPath.Value);
|
||||
var ms = new MemoryStream();
|
||||
// save the data to a stream
|
||||
data.SaveTo(ms);
|
||||
|
||||
var bytes = ms.ToArray();
|
||||
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
|
||||
return "data:image/jpeg;base64," + base64;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringBuilder exceptionBuilder = new();
|
||||
exceptionBuilder.AppendLine($"Surface:{self is not null}");
|
||||
BIT4Log.LogException( new InGameException(exceptionBuilder.ToString(),e));
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue