Untitled

mail@pastecode.io avatar
unknown
csharp
22 days ago
7.3 kB
2
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
    public float gravity = 9.81f;     // Gravity to apply when 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 = 0.1f; // 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 bool isGrounded;          // Boolean to check if Sonic is currently on the ground
    public float currentSpeed;       // Sonic's current movement speed
    private Vector3 groundNormal = Vector3.up; // The normal of the surface Sonic is currently on
    private Vector3 inputDirection;   // The direction of the player's input
    private Vector3 velocity;         // Sonic's current velocity
    private Vector3 targetPosition;   // Target position for smooth movement

    void Update()
    {
        HandleInput(); // Capture input before movement and jumping
        HandleJump();  // Handle Sonic's jumping
    }

    void FixedUpdate()
    {
        CheckGrounded(); // Check if Sonic is grounded
        HandleMovement(); // Handle Sonic's movement
        ApplyMovement();  // Apply the calculated movement to Sonic
    }

    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)
        {
            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 targetRotation = Quaternion.LookRotation(inputDirection, groundNormal); // Calculate target rotation
                transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 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
            }

            // Apply gravity when in the air
            velocity.y -= gravity * Time.deltaTime;
        }

        Vector3 moveDirection = transform.forward * currentSpeed; // Calculate movement direction
        velocity = new Vector3(moveDirection.x, velocity.y, moveDirection.z); // Update velocity with the calculated movement
    }

    void HandleJump()
    {
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = jumpForce; // Apply jump force
        }

        if (Input.GetButtonUp("Jump") && velocity.y > minJumpHeight)
        {
            velocity.y = minJumpHeight; // Limit jump height when button is released
        }
    }

    void CheckGrounded()
    {
        RaycastHit hit;
        Vector3 rayDirection = -transform.up; // Raycast in the direction of Sonic's down

        if (Physics.Raycast(transform.position, rayDirection, out hit, groundCheckDistance, groundLayer))
        {
            isGrounded = true;
            groundNormal = hit.normal; // Store the ground normal
            targetPosition = hit.point; // Target position is the hit point

            if (Vector3.Angle(Vector3.up, groundNormal) >= 90f && currentSpeed < wallStickSpeedThreshold)
            {
                isGrounded = false; // Disable grounding on steep slopes if speed is low
            }
        }
        else
        {
            isGrounded = false;
            groundNormal = Vector3.up; // Default to upwards normal if not grounded
        }
    }

    void ApplyMovement()
    {
        if (isGrounded)
        {
            transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * 10f); // Smoothly move to the target position
        }
        else
        {
            transform.position += velocity * Time.deltaTime; // Apply the velocity to move Sonic
        }
    }

    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