After Rick’s ship crashed immediately upon restarting the level I played with mine and found it very easy to crash right away as well. I didn’t want to change where the ship started though, so I decided to not give the player control right away upon loading, and to only give control once I passed through a plane that I added to the scene, which you can see below.
Nothing special about the plane, except I replaced the default Mesh Collider with a Box Collider.
In the CollisionHandler script I added a serialized field called PlayerControlStartPlane that we can drag the 3D object onto in the Unity editor. I also added in a Start method that gets the plane’s Mesh Renderer component and disables it (I like having it enabled in the editor so I can see where it is easily, but want it to be invisible when actually playing the game) and I remove control from the player for the time being. Then, in OnTriggerEnter, I check other’s gameObject.name and see if it equals “PlayerControlStartPlane” and if so I give the player control of the ship. Any other gameObject.name starts the crash sequence like normal.
The full CollisionHandler script ends up looking like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour {
[SerializeField] GameObject PlayerControlStartPlane;
[Header("Win/Lose Settings")]
[SerializeField] float SceneResetTimerInSeconds = 3.0f;
PlayerControls PlayerControls;
private void Start() {
PlayerControls = GetComponent<PlayerControls>();
PlayerControlStartPlane.GetComponent<MeshRenderer>().enabled = false; ;
PlayerControls.AdjustPlayerControl(false);
}
private void OnTriggerEnter(Collider other) {
//Debug.Log($@"{this.name} triggered by {other.gameObject.name}.");
if (other.gameObject.name == "PlayerControlStartPlane") {
PlayerControls.AdjustPlayerControl(true);
} else {
StartCrashSequence();
}
}
public void StartCrashSequence() {
PlayerControls.AdjustPlayerControl(false);
StartCoroutine(ReloadSceneAfterDelay(SceneResetTimerInSeconds));
}
IEnumerator ReloadSceneAfterDelay(float delay) {
yield return new WaitForSeconds(delay);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
I may tweak it slightly as I go through the rest of the course/play through the game, but I like how it works so far and it gives me an easy way to adjust it in the future if necessary.