PlayerController.cs
Description
This script is used for controlling the player and handling all the player-relevant logic.
Script
using System;
using System.Collections;
using Cameras;
using Unity.Cinemachine;
using input;
using Player.FSM.States;
using Tutorial;
using UI;
using UnityEngine;
using UnityEngine.InputSystem;
using Weapons;
namespace Player
{
public static class TransformExtensions
{
public static GameObject FindGameObjectInChildWithTag(this Transform parent, string tag)
{
GameObject foundChild = null;
for (var i = 0; i < parent.childCount; i++)
{
var child = parent.GetChild(i);
if (child.CompareTag(tag))
foundChild = child.gameObject;
}
if (foundChild)
{
return foundChild;
}
throw new Exception("No child object with tag!");
}
}
public class PlayerController : MonoBehaviour
{
#region Required Components
[HideInInspector] public GameObject eventSystem;
[HideInInspector] public inputSystem inputSystem;
[HideInInspector] public PlayerInput playerInput;
[HideInInspector] public MainCamera mainCamera;
[HideInInspector] public CharacterController characterController;
[HideInInspector] public GameObject playerMesh;
[HideInInspector] public PlayerShooting playerShooting;
[HideInInspector] public PlayerHealth playerHealth;
[HideInInspector] public CanvasScript canvasScript;
[HideInInspector] public AudioSource audioSource;
#endregion
#region Player States
private PlayerStateMachine _playerStateMachine;
[HideInInspector] public Idle IdleState;
[HideInInspector] public Walking WalkingState;
[HideInInspector] public Jumping JumpingState;
[HideInInspector] public Airborne AirborneState;
[HideInInspector] public WallJumping WallJumpingState;
[HideInInspector] public WallRunning WallRunState;
[HideInInspector] public Sliding SlidingState;
#endregion
#region Configurable Settings
[Header("Player Movement")]
[SerializeField] private float playerSpeed;
[SerializeField] private float sprintingSpeed;
[SerializeField] private Quaternion maxWallRotation;
[Header("Player Look")] [Range(0, 200)]
[SerializeField] private float mouseSensitivity;
[SerializeField] private float xClamp;
[SerializeField] private float rotationSpeed;
[Header("Player Jump")]
[SerializeField] private float playerJumpHeight;
[SerializeField] private float playerGravity;
[SerializeField] private float playerJumpCooldown;
[Header("Layer Mask Settings")]
[SerializeField] private LayerMask groundMask;
[SerializeField] private LayerMask whatIsWall;
[SerializeField] private LayerMask raycastLayers;
[Header("Wall Run Settings")]
[SerializeField] private float wallRunSpeed;
[SerializeField] private float wallRunForce;
[SerializeField] private float wallRunMaxDuration;
[SerializeField] private float wallRunExitTime;
[SerializeField] private float wallRunCooldown;
[Header("Wall Run Detection Settings")]
[SerializeField] private float maxWallDistance;
[Header("Wall Jump Settings")]
[SerializeField] private float wallJumpUpForce;
[SerializeField] private float wallJumpSideForce;
[SerializeField] private float wallMemoryTime;
[SerializeField] private float wallJumpCooldown;
[Header("Sliding Settings")]
[SerializeField] private float maxSlideTime;
[SerializeField] private float slideForce;
[SerializeField] private float slideYScale;
[SerializeField] private float slideCooldown;
[Header("Interact Settings")]
[SerializeField] private float maxInteractDistance;
[Header("Weapons")]
[SerializeField] private Pistol pistol;
[SerializeField] private Shotgun shotgun;
[Header("Tutorial Settings")]
[SerializeField] private bool isTutorial;
[SerializeField] private GameObject lineRender;
#endregion
#region Public References to private vars
public Transform PlayerTransform => characterController.transform;
public float JumpHeight => playerJumpHeight;
public float PlayerSpeed => playerSpeed;
public float SlideCooldown => slideCooldown;
public float PlayerGravity => playerGravity;
public float WallRunForce => wallRunForce;
public LayerMask WhatIsWall => whatIsWall;
public float MaxSlideTime => maxSlideTime;
public float SlideForce => slideForce;
public float SlideYScale => slideYScale;
public float JumpCooldown => playerJumpCooldown;
public float WallRunCooldown => wallRunCooldown;
public float WallJumpCooldown => wallJumpCooldown;
public float WallJumpUpForce => wallJumpUpForce;
public float WallJumpSideForce => wallJumpSideForce;
public float MaxWallDistance => maxWallDistance;
public bool IsTutorial => isTutorial;
public PlayerStateMachine PlayerFsm => _playerStateMachine;
#endregion
#region Public Vars
public bool isGrounded;
public bool canSlide;
public bool canJump;
public bool checkForWallsWhenAirborne;
public bool canWallJump;
public bool jumpingFromLeftWall;
public bool jumpingFromRightWall;
public bool leftWall;
public bool rightWall;
public RaycastHit JumpingLeftWallHit;
public RaycastHit JumpingRightWallHit;
public RaycastHit LeftWallHit;
public RaycastHit RightWallHit;
public CinemachineBrain activeCinemachineBrain;
public TutorialController tutorialController;
#endregion
public void Awake()
{
audioSource = GetComponent<AudioSource>();
characterController = GetComponentInChildren<CharacterController>();
eventSystem = GameObject.FindGameObjectWithTag("EventSystem");
mainCamera = eventSystem.GetComponent<MainCamera>();
inputSystem = eventSystem.GetComponent<inputSystem>();
playerMesh = transform.FindGameObjectInChildWithTag("PlayerMesh");
playerInput = GetComponent<PlayerInput>();
playerHealth = GetComponent<PlayerHealth>();
canvasScript = GameObject.FindGameObjectWithTag("Canvas").GetComponent<CanvasScript>();
_playerStateMachine = new PlayerStateMachine();
activeCinemachineBrain = GetComponentInChildren<CinemachineBrain>();
playerShooting = GetComponent<PlayerShooting>();
if (isTutorial) tutorialController = eventSystem.GetComponent<TutorialController>();
IdleState = new Idle("Idle", this, _playerStateMachine);
WalkingState = new Walking("Walking", this, _playerStateMachine);
JumpingState = new Jumping("Jumping", this, _playerStateMachine);
WallRunState = new WallRunning(this, _playerStateMachine);
AirborneState = new Airborne("Airborne", this, _playerStateMachine);
SlidingState = new Sliding("Sliding", this, _playerStateMachine);
WallJumpingState = new WallJumping(this, _playerStateMachine);
playerInput.actions["Shoot"].performed += _ => playerShooting.Fire();
playerInput.actions["Interact"].performed += _ => Interact();
playerInput.actions["Reload"].performed += _ => playerShooting.Reload();
canSlide = true;
canJump = true;
canWallJump = true;
_playerStateMachine.Initialize(IdleState);
Cursor.lockState = CursorLockMode.Locked;
SetMouseSensitivity();
}
private void Update()
{
_playerStateMachine.CurrentState.HandleInput();
_playerStateMachine.CurrentState.LogicUpdate();
}
private void SetMouseSensitivity()
{
mainCamera.SetSensitivity(mouseSensitivity);
}
private void FixedUpdate()
{
isGrounded = characterController.isGrounded;
_playerStateMachine.CurrentState.PhysicsUpdate();
}
public static IEnumerator ActionCooldown(Action cooldownComplete, float timeToTake)
{
yield return new WaitForSeconds(timeToTake);
cooldownComplete?.Invoke();
}
private void Interact()
{
activeCinemachineBrain.gameObject.TryGetComponent<Camera>(out var activeCam);
var rayOrigin = new Ray(activeCam.transform.position, activeCam.transform.forward);
if (!Physics.Raycast(rayOrigin, out var hit, maxInteractDistance)) return;
switch (hit.transform.tag)
{
case "Pistol":
var collidedPistol = hit.transform.gameObject;
playerShooting.EquipWeapon(pistol);
pistol.gameObject.SetActive(true);
if (collidedPistol.TryGetComponent<Outline>(out _))
Destroy(collidedPistol.GetComponent<Outline>());
Destroy(collidedPistol);
if (isTutorial) tutorialController.PistolCollected();
break;
case "Shotgun":
var collidedShotgun = hit.transform.gameObject;
playerShooting.EquipWeapon(shotgun);
shotgun.gameObject.SetActive(true);
Destroy(collidedShotgun);
break;
case "Computer":
tutorialController.ComputerInteracted();
break;
}
}
}
}
Public Methods
- ActionCooldown()
Waits for a specified amount of time, then invokes the cooldown action passed into the function.
Private Methods
- Awake()
Gets all the required components for the script to function. Also creates the states for the Player State Machine, and creates the bindings linked in with the Input System.
- FindGameObjectInChildWithTag()
Static function that finds a child object of a specified Game Object with a matching tag.
- FixedUpdate()
Checks if the player is grounded, and calls the current state within the Player State Machine to handle Physics Updates.
- Interact()
Handles the player interacting with objects within the scene. Raycasts, then checks the tag of the hit object, and does the relevant logic.
- SetMouseSensitivity()
Calls the Main Camera within the scene and sets the mouse sensitivity.
- Update()
Calls the current state within the Player State Machine to handle Player Input and Logic Updates.
Variables
Components
- audioSource
The Audio Source component attached to the player.
- canvasScript
The script with is used to handle UI elements within the scene.
- characterController
The character controller component attached to the player Game Object.
- eventSystem
The event system Game Object that handles logic within the scene.
- inputSystem
The component that handles Player Input.
- mainCamera
The Main Camera script that controls the Games camera components.
- playerHealth
The script that manages the players health system.
- playerInput
The input map for the Player Controls.
- playerMesh
The Player's Mesh / visual model.
- playerShooting
The script that controls the players weapon system.
Player States
- AirborneState
The Airborne state script for the player.
- IdleState
The Idle state script for the player.
- JumpingState
The Jumping state script for the player.
- SlidingState
The Sliding state script for the player.
- SprintingState
The Sprinting state script for the player.
- WalkingState
The Walking state script for the player.
- WallJumpingState
The Wall Jumping state script for the player.
- WallRunState
The Wall Running state script for the player.
- _playerStateMachine
The script that controls the current player state.
Player Settings
Player Movement
- playerSpeed
The value of the player's movement speed.
- sprintingSpeed
The value of the player's sprinting speed.
Player Look
- mouseSensitivity
The mouse sensitivity of the cameras in-game.
- xClamp
The limits of the X axis for the camera.
Player Jump
- playerGravity
The strength of gravity for the player.
- playerJumpCooldown
The time determining the length when the player can jump again.
- playerJumpHeight
How high the player can jump.
Layer Masks
- raycastLayers
The Layers in-game that can receive raycasts.
- whatIsWall
A LayerMask to determine what walls can be wall ran on.
Wall Running
- maxWallDistance
The max distance between the player and the walls that can be detected during ray casting.
- wallRunCooldown
The time determining when the player can wall run again.
- wallRunForce
The force applied onto the side of the player during wall running.
- wallRunMaxDuration
The length of how long the player can wall run for.
- wallRunSpeed
The speed that the player can run walls at.
Wall Jumping
- wallJumpCooldown
The time determining when the player can wall jump again.
- wallJumpSideForce
The amount of force applied to the player's X Axis when wall jumping.
- wallJumpUpForce
The amount of force applied to the player's Y Axis when wall jumping.
Sliding
- maxSlideTime
The max time the player is able to slide for.
- slideCooldown
The time determining when the player can slide again.
- slideForce
The force applied onto the player when sliding.
- slideYScale
The scale applied to the Y Axis of the player when sliding.
Interaction
- maxInteractDistance
The max distance for raycasts.
Weapons
- pistol
The pistol object childed to the player.
- shotgun
The shotgun object childed to the player.
Tutorial
- isTutorial
Determines if the player is in the tutorial stage or not.
Encapsulated Public Variables
Player
- PlayerGravity
Reference to the player's gravity.
- PlayerSpeed
Reference to the player's speed.
- PlayerTransform
Reference to the Character Controllers transform component.
Wall Run Settings
- WallRunForce
Reference to the player's wall run force.
- WallRunSpeed
Reference to the player's wall run speed.
- WhatIsWall
Reference to the layer mask determining what can be wall ran on.
Slide Settings
- MaxSlideTime
Reference to the player's max slide time.
- SlideCooldown
Reference to the player's slide cooldown.
- SlideForce
Reference to the player's slide force.
- SlideYScale
Reference to the player's Y Scale when sliding.
Jump Settings
- JumpCooldown
Reference to the player's jump cooldown length.
- JumpHeight
Reference to the player's jump height.
- WallJumpCooldown
Reference to the player's wall jump cooldown length.
- WallJumpSideForce
Reference to the player's wall jump X Axis force.
- WallJumpUpForce
Reference to the player's wall jump Y Axis force.
- WallRunCooldown
Reference to the player's wall run cooldown length.
Interaction Settings
- MaxWallDistance
Reference to the max wall distance from the player.
Tutorial Settings
- IsTutorial
Reference to the check determining if the player is in a tutorial.
Player State Machine
- PlayerFsm
Reference to the player's state machine.
Public Variables
- JumpingLeftWallHit
The RaycastHit value of the wall detected to the left of the player while wall jumping.
- JumpingRightWallHit
The RaycastHit value of the wall detected to the right of the player while wall jumping.
- LeftWallHit
The RaycastHit value of the wall detected to the left of the player.
- RightWallHit
The RaycastHit value of the wall detected to the right of the player.
- activeCinemachineBrain
The active Cinemachine Brain component in the scene.
- canJump
Reference to if the player can jump.
- canSlide
Reference to if the player can slide.
- canWallJump
Reference to if the player can wall jump.
- canWallRun
Reference to if the player can wall run.
- checkForWallsWhenAirborne
Reference to if the script should detect walls when the player is airborne.
- isGrounded
Reference to if the player is grounded.
- jumpingFromLeftWall
Reference to if the player is jumping from a wall on the left.
- jumpingFromRightWall
Reference to if the player is jumping from a wall on the right.
- leftWall
Reference to if a wall is detected on the left of the player.
- rightWall
Reference to if a wall is detected on the right of the player.
- tutorialController
The tutorial controller within the tutorial scene.
Last modified: 30 April 2024