137 lines
4.0 KiB
C#
137 lines
4.0 KiB
C#
|
// Designed by KINEMATION, 2024.
|
|||
|
|
|||
|
using Kinemation.MotionWarping.Runtime.Core;
|
|||
|
using Kinemation.MotionWarping.Runtime.Utility;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Kinemation.MotionWarping.Runtime.Examples
|
|||
|
{
|
|||
|
public class HangComponent : MonoBehaviour, IWarpPointProvider
|
|||
|
{
|
|||
|
[SerializeField] private MotionWarpingAsset hangAsset;
|
|||
|
[SerializeField] private MotionWarpingAsset jumpDownAsset;
|
|||
|
|
|||
|
[Header("Trace Settings")]
|
|||
|
[SerializeField] [Min(0f)] private float capsuleRadius;
|
|||
|
[SerializeField] [Min(0f)] private float sphereCheckRadius;
|
|||
|
[SerializeField] [Min(0f)] private float minLedgeLength;
|
|||
|
[SerializeField] [Min(0f)] private LayerMask layerMask;
|
|||
|
|
|||
|
[Header("Hanging")]
|
|||
|
[SerializeField] [Min(0f)] private float maxAllowedDistance;
|
|||
|
[SerializeField] [Min(0f)] private float maxAllowedHeight;
|
|||
|
[SerializeField] [Min(0f)] private float minAllowedHeight;
|
|||
|
|
|||
|
private bool _isHanging;
|
|||
|
|
|||
|
private WarpInteractionResult TryToJumpDown()
|
|||
|
{
|
|||
|
WarpInteractionResult result = new WarpInteractionResult()
|
|||
|
{
|
|||
|
success = false,
|
|||
|
points = null,
|
|||
|
asset = null,
|
|||
|
};
|
|||
|
|
|||
|
Vector3 start = transform.position;
|
|||
|
bool bHit = Physics.SphereCast(start, sphereCheckRadius, -transform.up, out var hit,
|
|||
|
maxAllowedHeight, layerMask);
|
|||
|
|
|||
|
if (!bHit)
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
Quaternion resultRotation = transform.rotation;
|
|||
|
Vector3 resultPosition = hit.point;
|
|||
|
|
|||
|
result.points = new[]
|
|||
|
{
|
|||
|
new WarpPoint()
|
|||
|
{
|
|||
|
position = resultPosition,
|
|||
|
rotation = resultRotation
|
|||
|
}
|
|||
|
};
|
|||
|
result.asset = jumpDownAsset;
|
|||
|
result.success = true;
|
|||
|
|
|||
|
_isHanging = false;
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
private WarpInteractionResult TryToHang()
|
|||
|
{
|
|||
|
WarpInteractionResult result = new WarpInteractionResult()
|
|||
|
{
|
|||
|
success = false,
|
|||
|
points = null,
|
|||
|
asset = null,
|
|||
|
};
|
|||
|
|
|||
|
Vector3 start = transform.position;
|
|||
|
Vector3 end = start;
|
|||
|
|
|||
|
start.y += minAllowedHeight;
|
|||
|
end.y += minAllowedHeight + maxAllowedHeight;
|
|||
|
|
|||
|
Vector3 direction = transform.forward;
|
|||
|
float distance = maxAllowedDistance;
|
|||
|
|
|||
|
bool bHit = Physics.CapsuleCast(start, end, capsuleRadius, direction,
|
|||
|
out var hit, distance, layerMask);
|
|||
|
|
|||
|
if (!bHit)
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
Quaternion targetRotation = Quaternion.LookRotation(-hit.normal, transform.up);
|
|||
|
|
|||
|
distance = (end - start).magnitude;
|
|||
|
|
|||
|
start = hit.point;
|
|||
|
start.y = end.y;
|
|||
|
|
|||
|
bHit = Physics.SphereCast(start, sphereCheckRadius, -transform.up, out hit, distance,
|
|||
|
layerMask);
|
|||
|
|
|||
|
if (!bHit)
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
start = hit.point;
|
|||
|
start.y += sphereCheckRadius + 0.01f;
|
|||
|
|
|||
|
Vector3 targetPosition = hit.point;
|
|||
|
|
|||
|
bHit = Physics.SphereCast(start, sphereCheckRadius, targetRotation * Vector3.forward, out hit,
|
|||
|
minLedgeLength, layerMask);
|
|||
|
|
|||
|
if (bHit)
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
result.success = true;
|
|||
|
result.asset = hangAsset;
|
|||
|
result.points = new[]
|
|||
|
{
|
|||
|
new WarpPoint()
|
|||
|
{
|
|||
|
position = targetPosition,
|
|||
|
rotation = targetRotation
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
_isHanging = true;
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public WarpInteractionResult Interact(GameObject instigator)
|
|||
|
{
|
|||
|
return _isHanging ? TryToJumpDown() : TryToHang();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|