Here’s the code for the rocket ship. I did some searches outside the course to figure out how to program the lighting for the engines. I like the effect.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
// fixed lighting bug from "Object Maps" tab on "Lighting"
public class Rocket2 : MonoBehaviour {
// [SerializeField] reveals the variable in the inspector
[SerializeField] float rotateMultiplier = 120f;
[SerializeField] float thrustMultiplier = 700f;
[SerializeField] float levelLoadTime = 1f;
[SerializeField] AudioClip mainEngine;
[SerializeField] AudioClip impact;
[SerializeField] AudioClip death;
[SerializeField] AudioClip success;
/* This will expose particle system to Inspector
* 1. SerializeField ParticleSystem
* 2. Add particle system Prefab to rocket game object
* 3. Drag child particle system game object to particle system in script
* 4. Code .Play() or .Stop() for particle system
*/
[SerializeField] ParticleSystem mainEngineParticlesL;
[SerializeField] ParticleSystem mainEngineParticlesR;
[SerializeField] ParticleSystem deathParticle;
[SerializeField] ParticleSystem successParticle;
[SerializeField] Light mainEngineLightL;
[SerializeField] Light mainEngineLightR;
GameObject leftThrustLight;
GameObject rightThrustLight;
Rigidbody rigidBody;
AudioSource audioSource;
int totalScenes;
int nextScene;
int currentScene; // create an integer variable for storing the current scene index
bool collisionsEnabled = true; // for debug code
enum State { Alive, Dying, Transcending };
State currentState = State.Alive;
// Interpolate light color between two colors back and forth
[SerializeField] float flickerDuration = 1.0f;
Color color0 = Color.red;
Color color1 = Color.yellow;
// Use this for initialization
void Start()
{
/* Accesses the RigidBody component within the context of where
* this script is being executed. In this case, <RigidBody> will
* find the RigidBody component of the GameObject where Rocket.cs
* is applied.
*/
totalScenes = SceneManager.sceneCountInBuildSettings -1; // # scenes in build settings
rigidBody = GetComponent<Rigidbody>(); // instantiating a variable
audioSource = GetComponent<AudioSource>();
currentScene = SceneManager.GetActiveScene().buildIndex; // get the active scene's index, stored as int
mainEngineLightL.enabled = !mainEngineLightL.enabled;
mainEngineLightR.enabled = !mainEngineLightR.enabled;
print("currentScene = " + currentScene);
print("totalScenes = " + totalScenes);
}
// Update is called once per frame
void Update()
{
Controls(); // player controls
SetEngineLightColor(); // cycles engine light color
if (Debug.isDebugBuild) {DebugGame();} // debug controls for build settings
}
void OnCollisionEnter(Collision collision) // detects collider contact of GameObject
{
if (!collisionsEnabled) { return;} // part of debug logic
if (currentState == State.Alive)
{
switch (collision.gameObject.tag)
{
case "Friendly":
//do nothing
print("Touched friendly");
break;
case "Finish":
//add Finished Level
StartLevelAdvanceSequence();
break;
case "FinalPad":
// todo create game completion scene
print("You have completed the game!");
break;
default:
//die
StartDeathSequence();
break;
}
}
}
private static void DestroyOutHouse() // currently unused
{
// destroy OutHouse. This also destroys the scripts currently running on the outhouse.
// It means my game logic disappears with the outhouse...
// todo separate game logic from player GameObject
string name = "OutHouse";
GameObject go = GameObject.Find(name);
if (go)
{
Destroy(go.gameObject);
Debug.Log(name + " has been destroyed");
}
}
private void StartLevelAdvanceSequence()
{
print("Touched LandingPad");
currentState = State.Transcending;
audioSource.Stop();
Invoke("LoadNextLevel", levelLoadTime); // run coroutine
audioSource.PlayOneShot(success);
successParticle.Play();
}
private void StartDeathSequence()
{
print("Bad touching. Dry death.");
currentState = State.Dying;
audioSource.Stop();
audioSource.PlayOneShot(death);
audioSource.PlayOneShot(impact);
deathParticle.Play();
Invoke("LoadNextLevel", 1f);
}
private void LoadNextLevel()
{
switch (currentState)
{
case State.Dying: // Dead, go back to beginning
currentScene = 0;
SceneManager.LoadScene(0);
break;
case State.Transcending: // Advance to next scene
if (currentScene == totalScenes)
{
currentScene = 0;
SceneManager.LoadScene(0);
}
else
{
currentScene = SceneManager.GetActiveScene().buildIndex;
nextScene = ++currentScene; // increase the current level integer by one
SceneManager.LoadScene(nextScene); // load the next level, which is current level increased by 1
audioSource.Stop();
print("currentScene = " + currentScene);
print("nextScene = " + nextScene);
print("totalScenes = " + totalScenes);
}
break;
default:
Debug.LogError("Invalid State Entered");
break;
}
}
void DebugGame()
{
if (Input.GetKeyDown(KeyCode.L))
{
currentState = State.Transcending;
LoadNextLevel();
}
else if (Input.GetKeyDown(KeyCode.C))
{
collisionsEnabled = !collisionsEnabled; // toggle collision enable/disable
}
}
private void Controls() // player controls
{
if (currentState == State.Alive)
{
RespondToThrustInput();
RespondToRotateInput();
}
}
void RespondToThrustInput()
{
float thrustThisFrame = thrustMultiplier * Time.deltaTime;
ApplyTrust(thrustThisFrame); // control thrust vector
ApplyThrustLights(); // control thrust lights
ApplyThrustParticles(); // control thrust particle
}
private void ApplyTrust(float thrustThisFrame)
{
if (Input.GetKey(KeyCode.Space))
{
rigidBody.AddRelativeForce(Vector3.up * thrustThisFrame);
if (!audioSource.isPlaying)
{
audioSource.PlayOneShot(mainEngine);
}
}
else
{
audioSource.Stop();
}
}
private void ApplyThrustParticles()
{
if (Input.GetKey(KeyCode.Space))
{
mainEngineParticlesL.Play(); // Left Engine
mainEngineParticlesR.Play(); // Right Engine
}
else
{
mainEngineParticlesL.Stop();
mainEngineParticlesR.Stop();
}
}
void ApplyThrustLights()
{
if (Input.GetKeyDown(KeyCode.Space))
{
mainEngineLightL.enabled = !mainEngineLightL.enabled;
mainEngineLightR.enabled = !mainEngineLightR.enabled;
}
if (Input.GetKeyUp(KeyCode.Space))
{
mainEngineLightL.enabled = !mainEngineLightL.enabled;
mainEngineLightR.enabled = !mainEngineLightR.enabled;
}
}
private void SetEngineLightColor()
{
// set light color
float t = Mathf.PingPong(Time.time, flickerDuration) / flickerDuration;
mainEngineLightL.color = Color.Lerp(color0, color1, t);
mainEngineLightR.color = Color.Lerp(color0, color1, t);
}
private void RespondToRotateInput()
{
float rotateThisFrame = rotateMultiplier * Time.deltaTime;
if (Input.GetKey(KeyCode.A)) //rotate LEFT
{
RotateManually(rotateThisFrame);
}
else if (Input.GetKey(KeyCode.D)) //rotate RIGHT
{
RotateManually(-rotateThisFrame);
}
}
private void RotateManually(float rotateThisFrame)
{
rigidBody.freezeRotation = true; // take manual control of rotation
transform.Rotate(Vector3.forward * rotateThisFrame);
rigidBody.freezeRotation = false; // release manual control of rotation
}
}