1
This commit is contained in:
123
Unity/Scripts/Sensor/RangeSensor.cs
Normal file
123
Unity/Scripts/Sensor/RangeSensor.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.Jobs;
|
||||
using UnityEngine.Pool;
|
||||
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.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;
|
||||
public override UniTask Excute()
|
||||
{
|
||||
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);
|
||||
}
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
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
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user