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

218 lines
4.7 KiB
C#

namespace Fusion.Addons.KCC
{
using UnityEngine;
public sealed class KCCShapeCastInfo
{
// PUBLIC MEMBERS
public Vector3 Position;
public float Radius;
public float Height;
public float Extent;
public Vector3 Direction;
public float MaxDistance;
public LayerMask LayerMask;
public QueryTriggerInteraction TriggerInteraction;
public KCCShapeCastHit[] AllHits;
public int AllHitCount;
public KCCShapeCastHit[] ColliderHits;
public int ColliderHitCount;
public KCCShapeCastHit[] TriggerHits;
public int TriggerHitCount;
// PRIVATE MEMBERS
private static readonly float[] _sortDistances = new float[KCC.CACHE_SIZE];
// CONSTRUCTORS
public KCCShapeCastInfo() : this(KCC.CACHE_SIZE)
{
}
public KCCShapeCastInfo(int maxHits)
{
AllHits = new KCCShapeCastHit[maxHits];
TriggerHits = new KCCShapeCastHit[maxHits];
ColliderHits = new KCCShapeCastHit[maxHits];
for (int i = 0; i < maxHits; ++i)
{
AllHits[i] = new KCCShapeCastHit();
}
}
// PUBLIC METHODS
public bool HasCollider(Collider collider)
{
for (int i = 0, count = AllHitCount; i < count; ++i)
{
KCCShapeCastHit hit = AllHits[i];
if (object.ReferenceEquals(hit.Collider, collider) == true)
return true;
}
return false;
}
public bool HasCollider(EColliderType colliderType)
{
for (int i = 0, count = AllHitCount; i < count; ++i)
{
KCCShapeCastHit hit = AllHits[i];
if (hit.Type == colliderType)
return true;
}
return false;
}
public void AddHit(RaycastHit raycastHit)
{
if (AllHitCount == AllHits.Length)
return;
KCCShapeCastHit hit = AllHits[AllHitCount];
if (hit.Set(raycastHit) == true)
{
++AllHitCount;
if (hit.IsTrigger == true)
{
TriggerHits[TriggerHitCount] = hit;
++TriggerHitCount;
}
else
{
ColliderHits[ColliderHitCount] = hit;
++ColliderHitCount;
}
}
}
public void Sort()
{
int count = AllHitCount;
if (count <= 1)
return;
bool isSorted = false;
bool hasChanged = false;
KCCShapeCastHit[] allHits = AllHits;
float[] distances = _sortDistances;
int leftIndex;
int rightIndex;
float leftDistance;
float rightDistance;
KCCShapeCastHit leftHit;
KCCShapeCastHit rightHit;
for (int i = 0; i < count; ++i)
{
distances[i] = allHits[i].RaycastHit.distance;
}
while (isSorted == false)
{
isSorted = true;
leftIndex = 0;
rightIndex = 1;
leftDistance = distances[leftIndex];
while (rightIndex < count)
{
rightDistance = distances[rightIndex];
if (leftDistance <= rightDistance)
{
leftDistance = rightDistance;
}
else
{
distances[leftIndex] = rightDistance;
distances[rightIndex] = leftDistance;
leftHit = allHits[leftIndex];
rightHit = allHits[rightIndex];
allHits[leftIndex] = rightHit;
allHits[rightIndex] = leftHit;
isSorted = false;
hasChanged = true;
}
++leftIndex;
++rightIndex;
}
}
if (hasChanged == true)
{
TriggerHitCount = 0;
ColliderHitCount = 0;
KCCShapeCastHit hit;
for (int i = 0; i < count; ++i)
{
hit = allHits[i];
if (hit.IsTrigger == true)
{
TriggerHits[TriggerHitCount] = hit;
++TriggerHitCount;
}
else
{
ColliderHits[ColliderHitCount] = hit;
++ColliderHitCount;
}
}
}
}
public void Reset(bool deep)
{
Position = default;
Radius = default;
Height = default;
Extent = default;
Direction = default;
MaxDistance = default;
Radius = default;
LayerMask = default;
TriggerInteraction = QueryTriggerInteraction.Collide;
AllHitCount = default;
ColliderHitCount = default;
TriggerHitCount = default;
if (deep == true)
{
for (int i = 0, count = AllHits.Length; i < count; ++i)
{
AllHits[i].Reset();
}
}
}
public void DumpHits(KCC kcc)
{
if (AllHitCount <= 0)
return;
kcc.Log($"ShapeCast Hits ({AllHitCount})");
KCCShapeCastHit[] hits = AllHits;
for (int i = 0, count = AllHitCount; i < count; ++i)
{
KCCShapeCastHit hit = AllHits[i];
kcc.Log($"Collider: {hit.Collider.name}, Type: {hit.Type}, IsTrigger: {hit.IsTrigger}, Distance: {hit.RaycastHit.distance}");
}
}
}
}