Untitled

mail@pastecode.io avatar
unknown
csharp
5 months ago
7.2 kB
2
Indexable
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("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
    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
    }

    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
    }

    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 (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 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) >= 90f && 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
    }

    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