2023-07-17 10:23:47 +08:00
|
|
|
using System;
|
2023-06-05 19:57:17 +08:00
|
|
|
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;
|
2023-08-11 23:57:37 +08:00
|
|
|
|
2023-06-05 19:57:17 +08:00
|
|
|
[Header(Constant.Header.Settings)]
|
|
|
|
public LayerMask blockLayer;
|
|
|
|
[Header(Constant.Header.InternalVariables)]
|
2023-08-11 23:57:37 +08:00
|
|
|
private FrameUpdate frameUpdater;
|
|
|
|
private readonly Collider[] colliders = new Collider[32];
|
|
|
|
private RaycastHit[] hits;
|
|
|
|
public override IEnumerable<Transform> Get() => detected;
|
2023-07-17 10:23:47 +08:00
|
|
|
|
|
|
|
private void Update()
|
|
|
|
{
|
|
|
|
if (autoUpdate)
|
|
|
|
{
|
|
|
|
Execute().Forget();
|
|
|
|
}
|
|
|
|
}
|
2023-06-29 14:57:11 +08:00
|
|
|
public override UniTask Execute()
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
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();
|
2023-06-05 19:57:17 +08:00
|
|
|
return UniTask.CompletedTask;
|
|
|
|
}
|
2023-08-11 23:57:37 +08:00
|
|
|
|
|
|
|
public override bool IsValid(Collider _collider)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
switch (_collider)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
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;
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
2023-08-11 23:57:37 +08:00
|
|
|
|
2023-06-05 19:57:17 +08:00
|
|
|
public override float GetDistance() => radius;
|
2023-08-11 23:57:37 +08:00
|
|
|
private bool CheckFov(ref Collider _collider)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
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);
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2023-08-11 23:57:37 +08:00
|
|
|
private bool CheckSight(ref Collider _collider)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
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)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
if (hits[0].collider == _collider)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-08-11 23:57:37 +08:00
|
|
|
return true;
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
2023-08-11 23:57:37 +08:00
|
|
|
else return true;
|
2023-06-05 19:57:17 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|