Untitled
unknown
csharp
17 days ago
8.2 kB
4
Indexable
Never
using UnityEngine; public class SonicController : MonoBehaviour { [Header("Movement Variables")] public float acceleration; // How fast Sonic accelerates on the ground public float deceleration; // How fast Sonic slows down when no input is given public float topSpeed; // Maximum speed Sonic can reach while on the ground public float maxSpeed; // Speed Sonic can instantly reach when boosting [Header("Air Movement Variables")] public float airAcceleration; // How fast Sonic accelerates while in the air public float airDeceleration; // How fast Sonic slows down in the air public float airTopSpeed; // Maximum speed Sonic can reach while in the air [Header("Jumping Variables")] public float jumpForce; // Initial force applied when Sonic jumps public float minJumpHeight; // Minimum height Sonic can reach when jump button is released early public float maxJumpHeight; // Maximum height Sonic can reach if the jump button is held [Header("Stomp Variables")] public float stompForce = 20f; // The downward force applied when Sonic stomps [Header("Ground Detection Variables")] public float groundCheckDistance; // Distance to check below Sonic to determine if grounded public LayerMask groundLayer; // Layers considered as ground for detection [Header("Slope Physics Variables")] public float slopeAssistance = 5f; // Multiplier for increasing speed when moving downhill public float slopeDrag = 5f; // Multiplier for decreasing speed when moving uphill public float wallStickSpeedThreshold = 2f; // Speed threshold below which Sonic will stick to walls on steep slopes private Rigidbody rb; // Reference to Sonic's Rigidbody component private bool isGrounded; // Boolean to check if Sonic is currently on the ground private bool isStomping; // Boolean to check if Sonic is currently stomping public float currentSpeed; // Sonic's current movement speed private Vector3 groundNormal; // The normal of the surface Sonic is currently on private Vector3 inputDirection; // The direction of the player's input void Start() { rb = GetComponent<Rigidbody>(); // Initialize the Rigidbody reference } void Update() { HandleInput(); // Capture input before movement and jumping CheckGrounded(); // Check if Sonic is grounded HandleMovement(); // Handle Sonic's movement HandleJump(); // Handle Sonic's jumping HandleStomp(); // Handle Sonic's stomping } void HandleInput() { float horizontalInput = Input.GetAxis("Horizontal"); // Get horizontal input (left/right movement) float verticalInput = Input.GetAxis("Vertical"); // Get vertical input (forward/backward movement) inputDirection = new Vector3(horizontalInput, 0f, verticalInput).normalized; // Combine inputs into a direction vector // Check if the stomp button is pressed and Sonic is airborne if (Input.GetButtonDown("Fire3") && !isGrounded) { isStomping = true; } } void HandleMovement() { bool isBoosting = Input.GetAxis("Fire2") > 0.1f; // Check if the boost button is pressed if (isGrounded) { AlignWithGround(); // Align Sonic with the ground's slope float slopeRotation = Vector3.Dot(inputDirection, groundNormal); // Calculate rotation based on slope if (isBoosting) { currentSpeed = maxSpeed; // Set speed to max if boosting } else { if (inputDirection.magnitude > 0) { currentSpeed += acceleration * Time.deltaTime; // Increase speed based on acceleration currentSpeed = Mathf.Clamp(currentSpeed, 0, topSpeed); // Clamp speed to topSpeed if (slopeRotation > 0) // Moving downhill { currentSpeed += slopeRotation * slopeAssistance * Time.deltaTime; // Increase speed downhill } else if (slopeRotation < 0) // Moving uphill { currentSpeed += slopeRotation * slopeDrag * Time.deltaTime; // Decrease speed uphill } } else { currentSpeed -= deceleration * Time.deltaTime; // Decrease speed when no input if (currentSpeed < 0) currentSpeed = 0; // Prevent speed from going negative } } if (inputDirection.magnitude > 0) { Quaternion inputRotation = Quaternion.LookRotation(inputDirection); // Rotate to face movement direction Quaternion combinedRotation = Quaternion.FromToRotation(transform.up, groundNormal) * inputRotation; // Combine ground and input rotation transform.rotation = Quaternion.Slerp(transform.rotation, combinedRotation, Time.deltaTime * 10f); // Smooth rotation } } else { if (!isStomping) // Only apply normal air movement if not stomping { if (inputDirection.magnitude > 0) { currentSpeed += airAcceleration * Time.deltaTime; // Increase speed in the air currentSpeed = Mathf.Clamp(currentSpeed, 0, airTopSpeed); // Clamp speed to airTopSpeed } } } Vector3 moveDirection = transform.forward * currentSpeed; // Calculate movement direction rb.velocity = new Vector3(moveDirection.x, rb.velocity.y, moveDirection.z); // Apply velocity to Rigidbody } void HandleJump() { if (Input.GetButtonDown("Jump") && isGrounded) { Vector3 jumpDirection = groundNormal * jumpForce; // Calculate jump force based on ground normal rb.velocity = new Vector3(rb.velocity.x, jumpDirection.y, rb.velocity.z); // Apply jump velocity } if (Input.GetButtonUp("Jump") && rb.velocity.y > minJumpHeight) { rb.velocity = new Vector3(rb.velocity.x, minJumpHeight, rb.velocity.z); // Limit jump height when button is released } } void HandleStomp() { if (isStomping) { // Cancel all horizontal movement and apply downward force rb.velocity = new Vector3(0f, -stompForce, 0f); isStomping = false; // Reset the stomping state } } void CheckGrounded() { RaycastHit hit; Vector3 rayDirection = -transform.up; // Raycast in the direction of Sonic's down isGrounded = Physics.Raycast(transform.position, rayDirection, out hit, groundCheckDistance, groundLayer); // Check if grounded if (isGrounded) { groundNormal = hit.normal; // Store the ground normal if (Vector3.Angle(Vector3.up, groundNormal) >= 60f && currentSpeed < wallStickSpeedThreshold) { isGrounded = false; // Disable grounding on steep slopes if speed is low } } } void AlignWithGround() { Quaternion slopeRotation = Quaternion.FromToRotation(transform.up, groundNormal) * transform.rotation; // Align rotation with ground transform.rotation = Quaternion.Slerp(transform.rotation, slopeRotation, Time.deltaTime * 10f); // Smooth rotation alignment } public bool IsGrounded() { return isGrounded; } private void OnDrawGizmosSelected() { Gizmos.color = Color.red; // Set Gizmo color Gizmos.DrawLine(transform.position, transform.position + -transform.up * groundCheckDistance); // Draw ground check line relative to Sonic } }
Leave a Comment