Untitled
unknown
csharp
2 days ago
6.1 kB
38
Indexable
using UnityEngine; using UnityEngine.Splines; using Unity.Mathematics; using System.Collections; public class RailGrind : 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