102 lines
2.8 KiB
C#
102 lines
2.8 KiB
C#
using UnityEngine;
|
|
|
|
namespace KitsuneCafe.Entity
|
|
{
|
|
public class Spring : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private new Rigidbody rigidbody;
|
|
|
|
[SerializeField]
|
|
private float rayLength = 1.5f;
|
|
|
|
[SerializeField]
|
|
private float rideHeight = 1f;
|
|
|
|
[SerializeField]
|
|
private float rideSpringStrength;
|
|
|
|
[SerializeField]
|
|
private float rideSpringDamper;
|
|
|
|
[SerializeField]
|
|
private Vector3 rayOffset = Vector3.zero;
|
|
|
|
[SerializeField]
|
|
private Vector3 down = Vector3.down;
|
|
|
|
[SerializeField]
|
|
private LayerMask layerMask;
|
|
|
|
private bool didRayHit;
|
|
private Vector3 relativeDown;
|
|
private float relativeVelocity;
|
|
private float targetDistance;
|
|
private float springForce;
|
|
|
|
public bool IsSpringColliding => didRayHit;
|
|
|
|
private void Reset()
|
|
{
|
|
rigidbody = GetComponent<Rigidbody>();
|
|
layerMask = LayerMask.NameToLayer("Default");
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
relativeDown = transform.TransformDirection(this.down);
|
|
|
|
didRayHit = Raycast(relativeDown, out var hit);
|
|
|
|
if (didRayHit)
|
|
{
|
|
relativeVelocity = RelativeVelocity(down, rigidbody, hit.rigidbody);
|
|
targetDistance = hit.distance - rideHeight;
|
|
springForce = (targetDistance * rideSpringStrength) - (relativeVelocity * rideSpringDamper);
|
|
rigidbody.AddForce(relativeDown * springForce);
|
|
}
|
|
}
|
|
|
|
private bool Raycast(Vector3 direction, out RaycastHit hit)
|
|
{
|
|
return Physics.Raycast(
|
|
transform.position + rayOffset,
|
|
direction,
|
|
out hit,
|
|
rayLength,
|
|
layerMask
|
|
);
|
|
}
|
|
|
|
private static float RelativeVelocity(Vector3 direction, Rigidbody a, Rigidbody b)
|
|
{
|
|
var aVelocity = GetVelocity(a);
|
|
var bVelocity = GetVelocity(b);
|
|
|
|
var aDirVelocity = Vector3.Dot(direction, aVelocity);
|
|
var bDirVelocity = Vector3.Dot(direction, bVelocity);
|
|
|
|
return aDirVelocity - bDirVelocity;
|
|
|
|
}
|
|
|
|
private static Vector3 GetVelocity(Rigidbody rb)
|
|
{
|
|
return rb == null ? Vector3.zero : rb.linearVelocity;
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
var origin = transform.position + rayOffset;
|
|
|
|
Gizmos.color = didRayHit ? Color.yellow : Color.red;
|
|
Gizmos.DrawRay(origin, relativeDown * rayLength);
|
|
|
|
if (didRayHit)
|
|
{
|
|
Gizmos.color = Color.green;
|
|
Gizmos.DrawRay(origin, relativeDown * rideHeight);
|
|
}
|
|
}
|
|
}
|
|
}
|