ashby-games/Unity/CarsDash/Assets/Scripts/Car/GameplayController.cs

213 lines
6.2 KiB
C#
Raw Normal View History

using System;
using UnityEngine;
using System.Collections;
using System.ComponentModel;
using UnityEngine.SceneManagement;
public class GameplayController : MonoBehaviour
{
[SerializeField] private Transform[] tireTransforms;
[SerializeField] private Transform[] frontTireTransforms;
[SerializeField] private Transform[] tireMeshes;
[SerializeField] private Rigidbody carRigidbody;
// [SerializeField] private GameObject gameOverPanel;
// [SerializeField] private TextMeshProUGUI gameOverText;
// [SerializeField] private TextMeshProUGUI timerText;
[SerializeField] private CarSpecs carSpecs;
[SerializeField] private Vector3 customCenterOfMass;
[SerializeField] private AnimationCurve steerLeftAnimCurve;
[SerializeField] private AnimationCurve steerRightAnimCurve;
[SerializeField] private AnimationCurve accelAnimCurve;
[Category("Input Attributes")]
private float steeringInput;
private float accelInput;
[Category("Global-Script-Attributes")]
private int tiresCount = 0;
private float remTime = 0f;
private float tiresInGround = 0f;
[Category("Script-Object-Refs.")]
private CarSystem carSystem;
private TimerSystem timerSystem;
private LevelManager levelManager;
[Category("Tags.")]
private const string checkpointTag = "Checkpoint";
private const string finishCheckpointTag = "Finish";
[Category("Level-End-Panel-Texts")]
private const string GameOver_Text = "Game Over!";
private const string OutOfTime_Text = "Out Of Time!";
private const string LevelComplete_Text = "Level Complete";
private RaycastHit hitInfo;
private bool isGameOver = false;
private Coroutine GroundCheckCoroutine = null;
[Category("Action Delegates")]
public static Action<float> OnCheckpointReached;
public Action<float, Transform, float, Transform> OnApplyForce;
public Action<float> OnCarRotate;
public Action<string> OnGameOver;
public static GameplayController Instance;
private float prevRemTime = 0;
private void Awake()
{
Instance = this;
Debug.Log($" Default Center of mass: {carRigidbody.centerOfMass} ");
carRigidbody.centerOfMass = customCenterOfMass;
}
private void Start()
{
isGameOver = false;
tiresCount = tireTransforms.Length;
// gameOverPanel.SetActive(false);
timerSystem = new TimerSystem();
remTime = timerSystem.Timer;
carSystem = new CarSystem(carRigidbody, carSpecs, frontTireTransforms, steerLeftAnimCurve: steerLeftAnimCurve, steerRightAnimCurve: steerRightAnimCurve, accelAnimCurve: accelAnimCurve);
// levelManager = new LevelManager(gameOverText, gameOverPanel);
}
/* Apply force to Car's rigidbody for Suspension(Y-Axis),
steering(X-Axis), and acceleration(Z-Axis) for each tire. */
private void FixedUpdate()
{
tiresInGround = 0;
for (int tireIndex = 0; tireIndex < tiresCount; tireIndex++)
{
if (Physics.Raycast(tireTransforms[tireIndex].position, -tireTransforms[tireIndex].up, out hitInfo, carSpecs.hitDist))
{
tiresInGround++;
OnApplyForce?.Invoke(hitInfo.distance, tireTransforms[tireIndex], accelInput, tireMeshes[tireIndex]);
}
}
CheckGameOverStates();
}
// Updates the timer for UI and Rotation of the wheels (transforms) according to input
private void Update()
{
//if (isGameOver || remTime < 1) // TODO :: uncomment after test
// return;
if (Input.GetKeyDown(KeyCode.R))
RestartLevel();
#if UNITY_EDITOR
ProcessInputs();
#endif
DisplayUITimer();
OnCarRotate?.Invoke(steeringInput);
}
// Add additional time when a checkpoint's reached
private void OnTriggerEnter(Collider other)
{
if (isGameOver)
return;
string otherGOTag = other.gameObject.tag;
if (otherGOTag == checkpointTag)
{
OnCheckpointReached?.Invoke(remTime);
remTime = timerSystem.Timer;
}
else if (otherGOTag == finishCheckpointTag && remTime > 0)
{
EnableGameOverState(LevelComplete_Text);
}
}
private void EnableGameOverState(string panelText)
{
return;
OnGameOver?.Invoke(panelText);
isGameOver = true;
}
private void DisplayUITimer()
{
if (remTime < 0) return;
remTime -= Time.deltaTime;
// timerText.text = ((int)remTime).ToString();
}
/* Editor movement inputs */
private void ProcessInputs()
{
accelInput = Input.GetAxis("Vertical");
steeringInput = Input.GetAxis("Horizontal");
}
private void CheckGameOverStates()
{
if (isGameOver)
return;
/* Check for Time run out */
if (remTime < 1)
{
EnableGameOverState(OutOfTime_Text);
return;
}
/* Check for Tires out of bounds (ground/platform) */
if (tiresInGround < 3 && GroundCheckCoroutine == null)
GroundCheckCoroutine = StartCoroutine(CheckTiresInGround());
}
/* Check if car/rigidbody is out of bounds/ground/platform */
private IEnumerator CheckTiresInGround()
{
yield return new WaitForSeconds(3f);
if (tiresInGround >= 3)
{
StopCoroutine();
}
/* Check for dealing with edge cases where
car would be moving through the edge of the platforms */
yield return new WaitForSeconds(2f);
if (tiresInGround < 3 && !isGameOver)
{
EnableGameOverState(GameOver_Text);
StopCoroutine();
}
}
private void StopCoroutine()
{
if (GroundCheckCoroutine != null)
{
StopCoroutine(GroundCheckCoroutine);
GroundCheckCoroutine = null;
}
}
/* Functions mapped to event triggers of associated buttons */
public void MoveInput(float input) => accelInput = input;
public void SteerInput(float input) => steeringInput = input;
public void RestartLevel()
{
StopCoroutine();
SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex);
}
}