Created
March 30, 2025 07:29
-
-
Save RH2/09170bb50f77d75a710d54dd8fa849f7 to your computer and use it in GitHub Desktop.
Absolutely going to break all boundaries lol (UNITY)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class CharacterMovement10 : MonoBehaviour | |
{ | |
public Camera playerCamera; | |
public float mouseSensitivity = 2f; | |
private float verticalLookRotation; | |
private CharacterController controller; | |
private Vector3 velocity; | |
private bool isGrounded; | |
private MovementState currentState; | |
private Dictionary<MovementState, List<Transition>> stateTransitions; | |
// Additional properties for transition conditions | |
public int maxJumpCount = 2; | |
private int currentJumpCount = 0; | |
public float maxStamina = 100f; | |
public float staminaRunCost = 10f; | |
private float currentStamina; | |
private float stateTimer = 0f; | |
[System.Serializable] | |
public class MovementSettings | |
{ | |
public float speed; | |
public float duration; | |
public float fov; | |
public float gravityMultiplier; | |
public AnimationCurve cameraShake; | |
} | |
public MovementSettings walkSettings = new MovementSettings { speed = 3f, fov = 70f, gravityMultiplier = 1f }; | |
public MovementSettings runSettings = new MovementSettings { speed = 6f, fov = 80f, gravityMultiplier = 1f }; | |
public MovementSettings crouchSettings = new MovementSettings { speed = 1.5f, fov = 65f, gravityMultiplier = 1.2f }; | |
public MovementSettings slideSettings = new MovementSettings { speed = 8f, duration = 1f, fov = 85f, gravityMultiplier = 0.5f }; | |
public MovementSettings wallRunSettings = new MovementSettings { speed = 7f, duration = 2f, fov = 90f, gravityMultiplier = 0f }; | |
public MovementSettings jumpSettings = new MovementSettings { speed = 4f, duration = 0.5f, fov = 75f, gravityMultiplier = 0.8f }; | |
public MovementSettings fallSettings = new MovementSettings { fov = 70f, gravityMultiplier = 1.5f }; | |
public MovementSettings climbSettings = new MovementSettings { speed = 2.5f, fov = 70f, gravityMultiplier = 0f }; | |
public MovementSettings landSettings = new MovementSettings { duration = 0.3f, fov = 70f, gravityMultiplier = 1f }; | |
private enum MovementState { Idle, Walk, Run, Crouch, Slide, WallRun, Jump, DoubleJump, Climb, Fall, Land } | |
private class Transition | |
{ | |
public MovementState toState; | |
public System.Func<bool> condition; | |
} | |
void Start() | |
{ | |
controller = GetComponent<CharacterController>(); | |
Cursor.lockState = CursorLockMode.Locked; | |
currentStamina = maxStamina; | |
InitializeStateTransitions(); | |
currentState = MovementState.Idle; | |
} | |
void Update() | |
{ | |
HandleMouseLook(); | |
HandleMovement(); | |
UpdateStateTimer(); | |
UpdateStamina(); | |
CheckStateTransitions(); | |
} | |
void HandleMouseLook() | |
{ | |
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; | |
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; | |
transform.Rotate(Vector3.up * mouseX); | |
verticalLookRotation -= mouseY; | |
verticalLookRotation = Mathf.Clamp(verticalLookRotation, -90f, 90f); | |
playerCamera.transform.localEulerAngles = new Vector3(verticalLookRotation, 0, 0); | |
} | |
void HandleMovement() | |
{ | |
isGrounded = controller.isGrounded; | |
Vector3 move = transform.right * Input.GetAxis("Horizontal") + transform.forward * Input.GetAxis("Vertical"); | |
MovementSettings settings = GetCurrentMovementSettings(); | |
controller.Move(move * settings.speed * Time.deltaTime); | |
velocity.y += Physics.gravity.y * settings.gravityMultiplier * Time.deltaTime; | |
if (isGrounded && velocity.y < 0) velocity.y = -2f; | |
controller.Move(velocity * Time.deltaTime); | |
} | |
void UpdateStateTimer() | |
{ | |
MovementSettings settings = GetCurrentMovementSettings(); | |
if (settings.duration > 0) | |
{ | |
stateTimer += Time.deltaTime; | |
if (stateTimer >= settings.duration) | |
{ | |
switch (currentState) | |
{ | |
case MovementState.Slide: | |
TransitionToState(MovementState.Crouch); | |
break; | |
case MovementState.Land: | |
TransitionToState(MovementState.Idle); | |
break; | |
case MovementState.WallRun: | |
TransitionToState(MovementState.Fall); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
} | |
void UpdateStamina() | |
{ | |
// Decrease stamina while running | |
if (currentState == MovementState.Run) | |
{ | |
currentStamina -= staminaRunCost * Time.deltaTime; | |
} | |
// Regenerate stamina when not running | |
else if (currentState != MovementState.Run && currentStamina < maxStamina) | |
{ | |
currentStamina += (maxStamina / 15f) * Time.deltaTime; // Regenerate full stamina in about 15 seconds | |
} | |
currentStamina = Mathf.Clamp(currentStamina, 0f, maxStamina); | |
} | |
void CheckStateTransitions() | |
{ | |
if (stateTransitions.ContainsKey(currentState)) | |
{ | |
foreach (var transition in stateTransitions[currentState]) | |
{ | |
if (transition.condition()) | |
{ | |
TransitionToState(transition.toState); | |
break; | |
} | |
} | |
} | |
} | |
// Transition condition functions | |
bool CanIdle() | |
{ | |
// Check if there's enough headspace to stand | |
return !Physics.Raycast(transform.position, Vector3.up, 2f) && isGrounded; | |
} | |
bool CanWalk() | |
{ | |
return isGrounded && Input.GetAxis("Vertical") != 0 && CanIdle(); | |
} | |
bool CanRun() | |
{ | |
return isGrounded && Input.GetKey(KeyCode.LeftShift) && currentStamina > 0 && | |
Input.GetAxis("Vertical") > 0 && CanIdle(); | |
} | |
bool CanCrouch() | |
{ | |
return isGrounded && Input.GetKey(KeyCode.C); | |
} | |
bool CanSlide() | |
{ | |
return isGrounded && currentState == MovementState.Run && Input.GetKeyDown(KeyCode.C); | |
} | |
bool CanJump() | |
{ | |
return isGrounded && Input.GetKeyDown(KeyCode.Space) && currentJumpCount < maxJumpCount; | |
} | |
bool CanDoubleJump() | |
{ | |
return !isGrounded && Input.GetKeyDown(KeyCode.Space) && currentJumpCount < maxJumpCount; | |
} | |
bool CanWallRun() | |
{ | |
return !isGrounded && DetectWall() && Input.GetAxis("Vertical") > 0; | |
} | |
bool CanClimb() | |
{ | |
return DetectWallFront() && Input.GetKey(KeyCode.W); | |
} | |
bool CanFall() | |
{ | |
return !isGrounded && velocity.y < 0; | |
} | |
bool CanLand() | |
{ | |
return currentState == MovementState.Fall && isGrounded; | |
} | |
bool ShouldStopCrouching() | |
{ | |
return !Input.GetKey(KeyCode.C) && CanIdle(); | |
} | |
bool ShouldStopWallRun() | |
{ | |
return !DetectWall() || Input.GetAxis("Vertical") <= 0; | |
} | |
bool DetectWall() | |
{ | |
return Physics.Raycast(transform.position, transform.right, 1f) || Physics.Raycast(transform.position, -transform.right, 1f); | |
} | |
bool DetectWallFront() | |
{ | |
return Physics.Raycast(transform.position, transform.forward, 1f); | |
} | |
void TransitionToState(MovementState newState) | |
{ | |
// Exit actions | |
switch (currentState) | |
{ | |
case MovementState.Land: | |
currentJumpCount = 0; // Reset jump counter when landing | |
break; | |
} | |
// Enter actions | |
switch (newState) | |
{ | |
case MovementState.Jump: | |
case MovementState.DoubleJump: | |
currentJumpCount++; | |
velocity.y = Mathf.Sqrt(jumpSettings.speed * -2f * Physics.gravity.y); | |
break; | |
case MovementState.Land: | |
case MovementState.Slide: | |
case MovementState.WallRun: | |
stateTimer = 0f; // Reset timer for timed states | |
break; | |
} | |
currentState = newState; | |
} | |
void InitializeStateTransitions() | |
{ | |
stateTransitions = new Dictionary<MovementState, List<Transition>>(); | |
// Idle state transitions | |
stateTransitions[MovementState.Idle] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Walk, condition = CanWalk }, | |
new Transition { toState = MovementState.Crouch, condition = CanCrouch }, | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = CanFall } | |
}; | |
// Walk state transitions | |
stateTransitions[MovementState.Walk] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Idle, condition = () => Input.GetAxis("Vertical") == 0 && Input.GetAxis("Horizontal") == 0 }, | |
new Transition { toState = MovementState.Run, condition = CanRun }, | |
new Transition { toState = MovementState.Crouch, condition = CanCrouch }, | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = CanFall } | |
}; | |
// Run state transitions | |
stateTransitions[MovementState.Run] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Walk, condition = () => !Input.GetKey(KeyCode.LeftShift) || currentStamina <= 0 }, | |
new Transition { toState = MovementState.Slide, condition = CanSlide }, | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = CanFall }, | |
new Transition { toState = MovementState.WallRun, condition = CanWallRun } | |
}; | |
// Crouch state transitions | |
stateTransitions[MovementState.Crouch] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Idle, condition = ShouldStopCrouching }, | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = CanFall } | |
}; | |
// Slide state transitions | |
stateTransitions[MovementState.Slide] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Crouch, condition = () => stateTimer >= slideSettings.duration }, | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = CanFall } | |
}; | |
// WallRun state transitions | |
stateTransitions[MovementState.WallRun] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.DoubleJump, condition = CanDoubleJump }, | |
new Transition { toState = MovementState.Fall, condition = ShouldStopWallRun }, | |
new Transition { toState = MovementState.Fall, condition = () => stateTimer >= wallRunSettings.duration } | |
}; | |
// Jump state transitions | |
stateTransitions[MovementState.Jump] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.DoubleJump, condition = CanDoubleJump }, | |
new Transition { toState = MovementState.Fall, condition = () => velocity.y < 0 }, | |
new Transition { toState = MovementState.WallRun, condition = CanWallRun }, | |
new Transition { toState = MovementState.Climb, condition = CanClimb } | |
}; | |
// DoubleJump state transitions | |
stateTransitions[MovementState.DoubleJump] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Fall, condition = () => velocity.y < 0 }, | |
new Transition { toState = MovementState.WallRun, condition = CanWallRun }, | |
new Transition { toState = MovementState.Climb, condition = CanClimb } | |
}; | |
// Climb state transitions | |
stateTransitions[MovementState.Climb] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Jump, condition = CanJump }, | |
new Transition { toState = MovementState.Fall, condition = () => !CanClimb() } | |
}; | |
// Fall state transitions | |
stateTransitions[MovementState.Fall] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Land, condition = CanLand }, | |
new Transition { toState = MovementState.WallRun, condition = CanWallRun }, | |
new Transition { toState = MovementState.Climb, condition = CanClimb }, | |
new Transition { toState = MovementState.DoubleJump, condition = CanDoubleJump } | |
}; | |
// Land state transitions | |
stateTransitions[MovementState.Land] = new List<Transition> | |
{ | |
new Transition { toState = MovementState.Idle, condition = () => stateTimer >= landSettings.duration } | |
}; | |
} | |
MovementSettings GetCurrentMovementSettings() | |
{ | |
switch (currentState) | |
{ | |
case MovementState.Walk: return walkSettings; | |
case MovementState.Run: return runSettings; | |
case MovementState.Crouch: return crouchSettings; | |
case MovementState.Slide: return slideSettings; | |
case MovementState.WallRun: return wallRunSettings; | |
case MovementState.Jump: | |
case MovementState.DoubleJump: return jumpSettings; | |
case MovementState.Fall: return fallSettings; | |
case MovementState.Climb: return climbSettings; | |
case MovementState.Land: return landSettings; | |
default: return walkSettings; | |
} | |
} | |
void OnGUI() | |
{ | |
GUI.Label(new Rect(10, 10, 300, 20), "Current State: " + currentState); | |
GUI.Label(new Rect(10, 30, 300, 20), "Stamina: " + Mathf.Round(currentStamina) + " / " + maxStamina); | |
GUI.Label(new Rect(10, 50, 300, 20), "Jump Count: " + currentJumpCount + " / " + maxJumpCount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment