2025-09-24 11:24:38 +05:00

90 lines
2.4 KiB
C#

using Fusion;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace TPSBR
{
public static partial class RaycastUtility
{
// PRIVATE MEMBERS
private static Collider[] _colliders = new Collider[64];
private static RaycastHit[] _raycastHits = new RaycastHit[64];
// PUBLIC METHODS
public static int ConeCast(Vector3 origin, Quaternion rotation, float angle, float maxDistance, int targetLayerMask, int blockingLayerMask, RaycastHit[] hits, Func<Collider, bool> filter = null)
{
if (hits == null || hits.Length == 0)
return 0;
Vector3 forward = rotation * new Vector3(0.0f, 0.0f, maxDistance);
Vector3 center = origin + forward * 0.5f;
Vector3 corner = Quaternion.Euler(0.0f, angle, 0.0f) * new Vector3(0.0f, 0.0f, maxDistance);
Vector3 extents = new Vector3(Mathf.Abs(corner.x), Mathf.Abs(corner.x), maxDistance * 0.5f);
int hitCount = 0;
int overlapHitCount = Physics.OverlapBoxNonAlloc(center, extents, _colliders, rotation, targetLayerMask, QueryTriggerInteraction.Ignore);
for (int i = 0; i < overlapHitCount; ++i)
{
Collider collider = _colliders[i];
Vector3 direction = collider.transform.position - origin;
if (Vector3.Angle(forward, direction) > angle)
continue;
if (filter != null && filter(collider) == false)
continue;
int raycastHitCount = Physics.RaycastNonAlloc(origin, direction, _raycastHits, direction.magnitude, blockingLayerMask, QueryTriggerInteraction.Ignore);
if (raycastHitCount > 0)
{
Sort(_raycastHits, raycastHitCount);
RaycastHit hit = _raycastHits[0];
if (((1 << hit.collider.gameObject.layer) & targetLayerMask) != 0)
{
hits[hitCount] = hit;
++hitCount;
if (hitCount >= hits.Length)
break;
}
}
}
for (int i = 0; i < _colliders.Length; ++i) { _colliders[i] = default; }
for (int i = 0; i < _raycastHits.Length; ++i) { _raycastHits[i] = default; }
return hitCount;
}
public static void Sort(RaycastHit[] hits, int maxHits)
{
while (true)
{
bool swap = false;
for (int i = 0; i < maxHits; ++i)
{
for (int j = i + 1; j < maxHits; ++j)
{
if (hits[j].distance < hits[i].distance)
{
RaycastHit hit = hits[i];
hits[i] = hits[j];
hits[j] = hit;
swap = true;
}
}
}
if (swap == false)
return;
}
}
}
}