Untitled
unknown
csharp
a year ago
6.2 kB
16
Indexable
using UnityEngine;
using UnityEngine.Splines;
using Unity.Mathematics;
using System.Collections;
public class RailGrindTrigger : MonoBehaviour
{
public float grindSpeed = 5f;
public float minGrindSpeed = 0.2f;
public SplineContainer currentSpline;
public bool isGrinding = false;
public float splineProgress = 0f;
public bool isReversing = false;
[SerializeField] private PlayerPhysics playerPhysics;
public float grindHeightOffset = 0.2f;
private static readonly int GrindingHash = Animator.StringToHash("IsGrinding");
private static readonly int LandOnRailHash = Animator.StringToHash("LandOnRail");
private Vector3 previousPosition;
private Vector3 grindVelocity;
private Vector3 initialModelLocalPosition;
private Vector3 targetModelPosition;
private void Start()
{
if (playerModel != null)
{
initialModelLocalPosition = playerModel.localPosition;
}
}
private void Update()
{
if (isGrinding)
{
moveAction.enabled = false;
if (jumpAction != null && jumpAction.currentJumps > 0 && Input.GetButtonDown("Jump"))
{
jumpAction.Jump();
ExitGrind();
return;
}
}
}
private void FixedUpdate()
{
if (isGrinding)
{
if (isReversing)
{
splineProgress -= grindSpeed * Time.fixedDeltaTime;
}
else
{
splineProgress += grindSpeed * Time.fixedDeltaTime;
}
splineProgress = Mathf.Clamp01(splineProgress);
Vector3 railPosition = currentSpline.EvaluatePosition(splineProgress);
playerPhysics.RB.MovePosition(railPosition);
Vector3 tangent = math.normalize(currentSpline.EvaluateTangent(splineProgress));
playerPhysics.RB.MoveRotation(Quaternion.LookRotation(tangent));
grindVelocity = (railPosition - previousPosition) / Time.fixedDeltaTime;
previousPosition = railPosition;
if (splineProgress <= 0f || splineProgress >= 1f)
{
ExitGrind();
}
}
}
private void LateUpdate()
{
if (isGrinding && playerModel != null)
{
Vector3 railWorldPosition = currentSpline.EvaluatePosition(splineProgress);
Vector3 targetWorldPosition = railWorldPosition + (Vector3.up * grindHeightOffset);
playerModel.position = targetWorldPosition;
}
}
private void OnTriggerEnter(Collider other)
{
SplineContainer spline = other.GetComponent<SplineContainer>();
if (spline != null && other is MeshCollider)
{
RailProperties railProperties = other.GetComponent<RailProperties>();
if (railProperties != null)
{
grindSpeed = railProperties.grindSpeed;
}
else
{
grindSpeed = minGrindSpeed;
}
StartGrind(spline);
}
}
private void StartGrind(SplineContainer spline)
{
currentSpline = spline;
Vector3 playerDirection = playerPhysics.RB.velocity.normalized;
splineProgress = FindClosestPointOnSpline(currentSpline, transform.position);
Vector3 splineTangent = math.normalize(currentSpline.EvaluateTangent(splineProgress));
float dotProduct = Vector3.Dot(playerDirection, splineTangent);
isReversing = dotProduct < 0;
isGrinding = true;
playerPhysics.DisableGroundCheck = true;
animator.SetBool("IsJumping", false);
animator.SetBool("IsRising", false);
animator.SetBool("IsFalling", false);
if (risingAndFalling != null)
{
risingAndFalling.IsAnimationOverridden = true;
}
if (bounceAction != null)
{
bounceAction.CancelBounce();
}
jumpAction.currentJumps = jumpAction.jumps;
animator.SetTrigger(LandOnRailHash);
spinBall.SetActive(false);
spinFX.SetActive(false);
previousPosition = currentSpline.EvaluatePosition(splineProgress);
targetModelPosition = initialModelLocalPosition + new Vector3(0, grindHeightOffset, 0);
StartCoroutine(TransitionToGrindAnimation());
}
private IEnumerator TransitionToGrindAnimation()
{
yield return new WaitForSeconds(0.35f);
animator.SetBool(GrindingHash, true);
}
private float FindClosestPointOnSpline(SplineContainer spline, Vector3 position)
{
float closestProgress = 0f;
float closestDistance = float.MaxValue;
for (float t = 0; t <= 1; t += 0.01f)
{
Vector3 splinePosition = spline.EvaluatePosition(t);
float distance = Vector3.Distance(position, splinePosition);
if (distance < closestDistance)
{
closestDistance = distance;
closestProgress = t;
}
}
return closestProgress;
}
public void ExitGrind()
{
isGrinding = false;
Vector3 exitTangent = math.normalize(currentSpline.EvaluateTangent(splineProgress));
Vector3 exitDirection = isReversing ? -exitTangent : exitTangent;
playerPhysics.RB.velocity = (exitDirection * grindSpeed) + playerPhysics.verticalVelocity;
currentSpline = null;
playerPhysics.DisableGroundCheck = false;
moveAction.enabled = true;
animator.SetBool(GrindingHash, false);
animator.ResetTrigger(LandOnRailHash);
if (risingAndFalling != null)
{
risingAndFalling.IsAnimationOverridden = false;
}
if (playerModel != null)
{
playerModel.localPosition = initialModelLocalPosition;
}
}
}
Editor is loading...
Leave a Comment