This commit is contained in:
CortexCore
2023-08-11 23:57:37 +08:00
parent 936a94c84b
commit 75889ec34f
149 changed files with 6524 additions and 1043 deletions

View File

@@ -18,7 +18,7 @@ namespace BITKit.Sensors
IAudioObject currentAudioObject;
Collider currentCollider;
Collider[] colliders = new Collider[32];
public override IEnumerable<Transform> Get() => detecteds;
public override IEnumerable<Transform> Get() => detected;
public override UniTask Execute()
{
var cacheList = ListPool<Transform>.Get();
@@ -30,15 +30,15 @@ namespace BITKit.Sensors
cacheList.Add(currentCollider.transform);
}
}
detecteds = cacheList.ToArray();
detected = cacheList.ToArray();
ListPool<Transform>.Release(cacheList);
return UniTask.CompletedTask;
}
public override bool IsValid(Collider collider)
public override bool IsValid(Collider _collider)
{
if (ignoreColliders.Contains(collider) is false)
if (Vector3.Distance(transform.position, collider.transform.position) <= radius)
if (collider.TryGetComponent<IAudioObject>(out currentAudioObject))
if (ignoreColliders.Contains(_collider) is false)
if (Vector3.Distance(transform.position, _collider.transform.position) <= radius)
if (_collider.TryGetComponent<IAudioObject>(out currentAudioObject))
{
return currentAudioObject.GetVolume() >= 1;
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -6,12 +7,35 @@ using BITKit;
using Cysharp.Threading.Tasks;
namespace BITKit.Sensors
{
/// <summary>
/// 传感器的接口定义
/// </summary>
public interface ISensor
{
/// <summary>
/// 是否监测到任何目标
/// </summary>
bool Any=>Get().Any();
/// <summary>
/// 获取检测到的目标
/// </summary>
/// <returns></returns>
IEnumerable<Transform> Get();
bool IsValid(Collider collider);
/// <summary>
/// 目标是否有效
/// </summary>
/// <param name="_collider">目标的碰撞体</param>
/// <returns></returns>
bool IsValid(Collider _collider);
/// <summary>
/// 获取传感器的范围
/// </summary>
/// <returns></returns>
float GetDistance();
/// <summary>
/// 传感器执行检测
/// </summary>
/// <returns></returns>
UniTask Execute();
}
[System.Serializable]
@@ -24,9 +48,9 @@ namespace BITKit.Sensors
return _sensorImplementation.Get();
}
public bool IsValid(Collider collider)
public bool IsValid(Collider _collider)
{
return _sensorImplementation.IsValid(collider);
return _sensorImplementation.IsValid(_collider);
}
public float GetDistance()
@@ -43,15 +67,14 @@ namespace BITKit.Sensors
{
[Header(Constant.Header.Settings)]
public LayerMask detectLayer;
public bool autoUpdate;
[Header(Constant.Header.Gameobjects)]
public Collider[] ignoreColliders;
[Header(Constant.Header.Components)]
public Sensor[] subSensors;
[Header(Constant.Header.InternalVariables)]
[System.NonSerialized]
public Transform[] detecteds = new Transform[0];
[NonSerialized]
public Transform[] detected = Array.Empty<Transform>();
public abstract IEnumerable<Transform> Get();
public abstract bool IsValid(Collider collider);
public abstract bool IsValid(Collider _collider);
public abstract UniTask Execute();
public abstract float GetDistance();
}

View File

@@ -5,7 +5,8 @@
"GUID:a209c53514018594f9f482516f2a6781",
"GUID:508392158bd966c4d9c21e19661a441d",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:be17a8778dbfe454890ed8279279e153"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@@ -14,19 +14,14 @@ namespace BITKit.Sensors
public float radius;
public int fov;
public bool requireSight;
public bool autoUpdate;
[Header(Constant.Header.Settings)]
public LayerMask blockLayer;
[Header(Constant.Header.InternalVariables)]
FrameUpdate frameUpdater;
Collider[] colliders = new Collider[32];
RaycastHit[] hits;
Collider currentCollider;
Location location;
int length;
Vector3 dir;
float maxDistance;
public override IEnumerable<Transform> Get() => detecteds;
private FrameUpdate frameUpdater;
private readonly Collider[] colliders = new Collider[32];
private RaycastHit[] hits;
public override IEnumerable<Transform> Get() => detected;
private void Update()
{
@@ -37,100 +32,64 @@ namespace BITKit.Sensors
}
public override UniTask Execute()
{
if (frameUpdater)
{
if (maxDistance is 0)
{
maxDistance = Mathf.Max(subSensors.Select(x => x.GetDistance()).Append(radius).ToArray());
}
location.position = transform.position;
location.rotation = transform.rotation;
var list = ListPool<Transform>.Get();
for (int i = 0; i < Physics.OverlapSphereNonAlloc(location, maxDistance, colliders, detectLayer); i++)
{
currentCollider = colliders[i];
if (IsValid(currentCollider))
list.Add(currentCollider.transform);
else
{
foreach (var sensor in subSensors)
{
if (sensor.IsValid(currentCollider))
{
list.Add(currentCollider.transform);
break;
}
}
}
}
detecteds = list.ToArray();
list.Clear();
ListPool<Transform>.Release(list);
}
if (frameUpdater.Allow is false) return UniTask.CompletedTask;
var location = new Location(transform);
var length = Physics.OverlapSphereNonAlloc(location, radius, colliders, detectLayer);
var list = new List<Transform>();
list.AddRange(from x in colliders.Take(length) where IsValid(x) select x.transform);
detected = list.ToArray();
list.Clear();
// detected = colliders
// .Take(length)
// .Select(x => x.transform)
// .ToArray();
return UniTask.CompletedTask;
}
public override bool IsValid(Collider collider)
public override bool IsValid(Collider _collider)
{
if (ignoreColliders.Contains(collider)
|| CheckFov(ref collider) is false
|| CheckSight(ref collider) is false
|| CheckDistance(ref collider) is false
)
switch (_collider)
{
return false;
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:
return false;
default:
return true;
}
}
public override float GetDistance() => radius;
private bool CheckFov(ref Collider _collider)
{
var _dir = _collider.transform.position - transform.position;
if (_dir.sqrMagnitude <= 0) return false;
var dir = Quaternion.LookRotation(_dir);
return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir);
}
private bool CheckSight(ref Collider _collider)
{
if (!requireSight) return false;
var transform1 = _collider.transform;
var position = transform1.position;
var location = new Location(transform);
var length = Physics.RaycastNonAlloc(
location.position,
position - location,
hits,
Vector3.Distance(location, position),
blockLayer
);
if (length > 0)
{
if (hits[0].collider == _collider)
{
return true;
}
}
else return true;
}
public override float GetDistance() => radius;
bool CheckFov(ref Collider collider)
{
if (fov is not 0)
{
var _dir = collider.transform.position - transform.position;
if (_dir.sqrMagnitude > 0)
{
var dir = Quaternion.LookRotation(_dir);
if (Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir))
{
return true;
}
else return false;
}
else return true;
}
else
{
return true;
}
}
bool CheckSight(ref Collider collider)
{
if (requireSight)
{
length = Physics.RaycastNonAlloc(
location.position,
collider.transform.position - location,
hits,
Vector3.Distance(location, collider.transform.position),
blockLayer
);
if (length > 0)
{
if (hits[0].collider == collider)
{
return true;
}
}
else return true;
}
return false;
}
bool CheckDistance(ref Collider collider)
{
return Vector3.Distance(collider.transform.position, transform.position) <= radius;
}
}
#if UNITY_EDITOR
#endif
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace BITKit.Sensors
@@ -8,22 +10,29 @@ namespace BITKit.Sensors
{
[Header(Constant.Header.Settings)]
public float distance;
public override IEnumerable<Transform> Get() => detecteds;
public override IEnumerable<Transform> Get() => detected;
private readonly RaycastHit[] raycasts = new RaycastHit[16];
public override UniTask Execute()
{
if (Physics.Raycast(transform.position, transform.forward, out var rayhit, distance, detectLayer))
{
detecteds = new Transform[]{
rayhit.transform
};
}
else
{
detecteds = new Transform[0];
}
var _transform = transform;
var ray = new Ray(_transform.position,_transform.forward);
var size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer);
detected = raycasts
.Take(size)
.Select(x => x.collider)
.Where(IsValid)
.Select(x=>x.transform)
.ToArray();
return UniTask.CompletedTask;
}
public override bool IsValid(Collider collider) => true;
public override bool IsValid(Collider _collider) => ignoreColliders.Contains(_collider) is false;
public override float GetDistance() => distance;
private void Update()
{
if (autoUpdate)
{
Execute().Forget();
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9b4a8919533349e4e9bb0cd30005668c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
#endif
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.Sensors
{
/// <summary>
/// 智能目标传感器,根据条件,智能选择目标
/// </summary>
public class SmartTargetSensor :MonoBehaviour,ISensor,IAction
{
/// <summary>
/// 自动更新
/// </summary>
[Header(Constant.Header.Settings)]
[SerializeField] private bool autoUpdate;
/// <summary>
/// 目标有效性验证
/// </summary>
[Header(Constant.Header.Providers)]
[SerializeField,SerializeReference,SubclassSelector] private IValidityProvider validityProvider;
/// <summary>
/// 主传感器
/// </summary>
[Header(nameof(Sensor))]
[SerializeField,SerializeReference,SubclassSelector] private ISensor sensor;
#if UNITY_EDITOR
[Header(Constant.Header.Debug)]
[SerializeField] private Transform sensorTransform;
#endif
public IEnumerable<Transform> Get() =>CurrentTarget is not null ? new[] { CurrentTarget }:Enumerable.Empty<Transform>();
public bool IsValid(Collider _collider) =>validityProvider?.IsValid(_collider) ?? true;
public float GetDistance() => sensor.GetDistance();
public Transform CurrentTarget { get; private set; }
private readonly List<Transform> detected = new();
public async UniTask Execute()
{
await sensor.Execute();
var _detected = sensor.Get().ToList();
if (_detected.Contains(CurrentTarget))
{
if (detected.Count is 1 && detected[0] == CurrentTarget)
{
}
else
{
detected.Clear();
detected.Add(CurrentTarget);
}
return;
}
CurrentTarget = _detected
.Where(_transform => IsValid(_transform.GetComponent<Collider>()))
.OrderBy(_transform => Vector3.Distance(transform.position, _transform.position))
.FirstOrDefault();
}
private void Update()
{
if(autoUpdate)Execute().Forget();
}
void IAction.Execute()
{
Execute().Forget();
}
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
if (CurrentTarget is null) return;
Gizmos.DrawLine(sensorTransform.position,CurrentTarget.position);
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(SmartTargetSensor))]
public class SmartTargetSensorInspector:BITInspector<SmartTargetSensor>
{
private ObjectField _objectField;
public override VisualElement CreateInspectorGUI()
{
FillDefaultInspector();
CreateSubTitle("Editor Debug Field");
_objectField = root.Create<ObjectField>();
_objectField.objectType = typeof(Transform);
_objectField.SetEnabled(false);
return root;
}
protected override void OnUpdate()
{
if (_objectField is not null)
{
_objectField.value = agent.CurrentTarget;
}
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33d6f52a9de8ea149ab70ac4e67a0c36
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -6,7 +6,6 @@ using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
#if UNITY_EDITOR
using System.CodeDom;
using UnityEditor;
using UnityEditor.UIElements;
#endif
@@ -63,18 +62,24 @@ namespace BITKit.Sensors
public bool IsValid(Collider _collider)
{
if(allowStatic is false && _collider.gameObject.isStatic) return false;
if (ignores.Contains(_collider.gameObject)) return false;
var attachedRigidbody = _collider.attachedRigidbody;
var detectedObject = _collider switch
{
var x when attachedRigidbody is not null && useRigidbody => attachedRigidbody.gameObject,
_ => _collider.gameObject,
};
if (ignores.Contains(detectedObject)) return false;
return !detectedLayer.Allow || detectedLayer.Value.Includes(_collider.gameObject.layer);
}
public float GetDistance()
{
throw new System.NotImplementedException();
throw new NotImplementedException();
}
public UniTask Execute()
{
throw new System.NotImplementedException();
throw new NotImplementedException();
}
private void Update()