Net.Like.Xue.Tokyo/Assets/Plugins/KINEMATION/MotionWarping/Runtime/Examples/HangComponent.cs

137 lines
4.0 KiB
C#
Raw Normal View History

2025-03-10 18:06:44 +08:00
// 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();
}
}
}