Untitled
unknown
csharp
a year ago
8.2 kB
9
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("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
}
}Editor is loading...
Leave a Comment