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

131 lines
4.1 KiB
C#

// Designed by KINEMATION, 2024.
using Kinemation.MotionWarping.Runtime.Core;
using Kinemation.MotionWarping.Runtime.Utility;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Kinemation.MotionWarping.Runtime.Examples
{
public class MantleComponent : MonoBehaviour, IWarpPointProvider
{
[SerializeField] private MotionWarpingAsset mantleHigh;
[SerializeField] private MotionWarpingAsset mantleLow;
[SerializeField] private MantleSettings settings;
private Vector3 _targetPosition;
private Quaternion _targetRotation;
public WarpInteractionResult Interact(GameObject instigator)
{
WarpInteractionResult result = new WarpInteractionResult()
{
points = null,
asset = null,
success = false
};
if (settings == null)
{
return result;
}
var motionWarping = instigator.GetComponent<Core.MotionWarping>();
Vector3 start = transform.position;
Vector3 end = start;
start.y += settings.minHeight + settings.characterCapsuleRadius;
end.y += settings.maxHeight;
Vector3 direction = transform.forward;
float distance = settings.maxDistance;
bool bHit = Physics.CapsuleCast(start, end, settings.characterCapsuleRadius, direction,
out var hit, distance, settings.layerMask);
if (!bHit)
{
return result;
}
_targetRotation = Quaternion.LookRotation(-hit.normal, transform.up);
distance = (end - start).magnitude;
start = hit.point;
start += (_targetRotation * Vector3.forward) * settings.forwardOffset;
start.y = end.y;
bHit = Physics.SphereCast(start, settings.sphereEdgeCheckRadius, -transform.up, out hit,
distance, settings.layerMask);
start = hit.point;
if (!bHit)
{
return result;
}
Vector3 surfaceNormal = hit.normal;
start += surfaceNormal * (0.02f + settings.characterCapsuleRadius);
end = start + surfaceNormal * settings.characterCapsuleHeight;
bHit = Physics.CheckCapsule(start, end, settings.characterCapsuleRadius, settings.layerMask);
if (bHit)
{
return result;
}
float surfaceIncline = Mathf.Clamp(Vector3.Dot(transform.up, surfaceNormal), -1f, 1f);
surfaceIncline = Mathf.Acos(surfaceIncline) * Mathf.Rad2Deg;
if (surfaceIncline > settings.maxSurfaceInclineAngle)
{
return result;
}
Vector3 forwardVector = _targetRotation * Vector3.forward;
_targetRotation = Quaternion.LookRotation(forwardVector);
_targetPosition = hit.point;
result.points = new[]
{
new WarpPoint()
{
transform = hit.transform,
position = hit.transform.InverseTransformPoint(_targetPosition),
rotation = Quaternion.Inverse(hit.transform.rotation) * _targetRotation
}
};
float height = _targetPosition.y - transform.position.y;
result.asset = height > settings.lowHeight ? mantleHigh : mantleLow;
result.success = true;
#if UNITY_EDITOR
Core.MotionWarping.AddWarpDebugData(motionWarping, new WarpDebugData()
{
duration = 5f,
onDrawGizmos = () =>
{
var color = Gizmos.color;
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(_targetPosition, 0.1f);
Handles.Label(_targetPosition, "Mantle Target Point");
Gizmos.color = color;
}
});
#endif
return result;
}
}
}