/// <summary>
/// Do a cast when hitting a collider to get the raycast hit data.
/// </summary>
/// <param name="dataStream">The data stream.</param>
/// <param name="hitboxIndex">The index of the hitbox that caused the collision.</param>
/// <param name="hitCollider">The collider that was hit.</param>
/// <returns>A list of raycast hits.</returns>
protected override ListSlice<RaycastHit> DoCollisionCast(MeleeUseDataStream dataStream, int hitboxIndex, Collider hitCollider)
{
var hitCount = 0;
Vector3 direction;
float distance;
var characterTransform = Character.transform;
var center = characterTransform.TransformPoint(m_SphereCenter);
// A RaycastHit should be retrieved based off of the collision.
if (((hitCollider is BoxCollider) || (hitCollider is SphereCollider) || (hitCollider is CapsuleCollider) ||
((hitCollider is MeshCollider) && (hitCollider as MeshCollider).convex))) {
var hitColliderTransform = hitCollider.transform;
direction = characterTransform.position - center;
distance = direction.magnitude;
direction = direction.normalized;
var offset = direction * (distance + CharacterLocomotion.ColliderSpacing * 2);
var closestPoint = Physics.ClosestPoint(center + offset, hitCollider, hitColliderTransform.position, hitColliderTransform.rotation);
hitCount = Physics.SphereCastNonAlloc(closestPoint + offset, CharacterLocomotion.ColliderSpacing, -direction,
m_CollisionsHit,
distance + CharacterLocomotion.ColliderSpacing * 2, 1 << hitCollider.gameObject.layer, m_TriggerInteraction);
// Sphere Cast Non Alloc returns point Vector3.zero when the sphere overlaps, so lets just get the closest point.
for (int i = 0; i < hitCount; i++) {
var hit = m_CollisionsHit[i];
if (hit.point == Vector3.zero) {
hit.point = closestPoint;
hit.distance = (closestPoint - (center + offset)).magnitude;
}
m_CollisionsHit[i] = hit;
}
} else {
// Convert the collider's position to be relative to the character's z location.
var position = center;
var localPosition = CharacterTransform.InverseTransformPoint(position);
distance = localPosition.z + CharacterLocomotion.ColliderSpacing;
localPosition.z = 0;
position = CharacterTransform.TransformPoint(localPosition);
// Perform the raycast from the character's local z position. This will prevent the cast from overlapping the object.
var rotation = CharacterTransform.rotation;
var originPoint = MathUtility.TransformPoint(position, rotation, m_SphereCenter);
hitCount = Physics.SphereCastNonAlloc(originPoint,
m_SphereRadius, CharacterTransform.forward, m_CollisionsHit, distance, 1 << hitCollider.gameObject.layer,
m_TriggerInteraction);
// Sphere Cast Non Alloc returns point Vector3.zero when the sphere overlaps, so lets just get the closest point.
for (int i = 0; i < hitCount; i++) {
var hit = m_CollisionsHit[i];
if (hit.point == Vector3.zero) {
hit.point = originPoint;
hit.distance = (originPoint - center).magnitude;
}
m_CollisionsHit[i] = hit;
}
}
return new ListSlice<RaycastHit>(m_CollisionsHit,0,hitCount);
}