Hello everyone,
I have a very strange issue where the rocket thrust will not work after I have exported my finished game to either WebGL or a Windows executable.
I believe it is connected to another issue I encountered yesterday which I resolved at the time. The issue I encountered was the same as this, and I referred to Nina’s Github pull request fix to get the solution. Here’s the link to the first issue for reference:
Time.deltaTime problems
However, in Nina’s solution in the above link, she created a FixedUpdate method and placed the new ForceMode.Acceleration (which replaced Time.deltaTime) in it. When I did the same, plus created a isThrusting boolean etc, it didn’t work for me. The rocket still didn’t thrust.
However, I found in my code that if I simply replaced Time.deltaTime with ForceMode.Acceleration in the original ApplyThrust method - which is called in the original Update method (as opposed to FixedUpdate), it worked for me.
So all was good until today when I finished the game and tried exporting it.
Boom! Now the rocket isn’t thrusting again in the exported versions, exactly the same way it wasn’t yesterday before my initial fix. It’s working fine in the editor.
I have attempted to use Nina’s original solution for the first issue again (using FixedUpdate etc.) as I thought that might be what’s causing it to not work when the project is exported. “Perhaps WebGL or an .exe require FixedUpdate but the editor doesn’t require it?” But no, it didn’t solve it (not working in the editor again)
I have included the code file for reference (it uses the Update method currently)
Can anybody please help me?
using UnityEngine;
using UnityEngine.SceneManagement;
public class Rocket : MonoBehaviour
{
[SerializeField] float rcsThrust = 300f; // rotation speed
[SerializeField] float mainThrust = 30000000f; // thrust amount
[SerializeField] float levelLoadDelay = 2f;
[SerializeField] AudioClip mainEngine;
[SerializeField] AudioClip success;
[SerializeField] AudioClip death;
[SerializeField] ParticleSystem mainEngineParticles;
[SerializeField] ParticleSystem successParticles;
[SerializeField] ParticleSystem deathParticles;
Rigidbody rigidBody;
AudioSource audioSource;
enum State { Alive, Dying, Transcending }
State state = State.Alive;
bool collisionsDisabled = false;
// Start is called before the first frame update
void Start()
{
rigidBody = GetComponent<Rigidbody>(); // Gets the rocket's rigidbody component
audioSource = GetComponent<AudioSource>(); // Gets the rocket's audio source component
}
// Update is called once per frame
void Update()
{
if (state == State.Alive)
{
RespondToThrustInput();
RespontToRotateInput();
}
if (Debug.isDebugBuild)
{
RespondToDebugKeys();
}
}
private void RespondToDebugKeys()
{
if (Input.GetKeyDown(KeyCode.L))
{
LoadNextScene();
}
if (Input.GetKeyDown(KeyCode.C))
{
collisionsDisabled = !collisionsDisabled;
}
}
private void RespondToThrustInput()
{
if (Input.GetKey(KeyCode.Space))
{
ApplyThrust();
}
else
{
StopApplyingThrust();
}
}
private void StopApplyingThrust()
{
audioSource.Stop(); // Stops audio when space not down
mainEngineParticles.Stop();
}
private void ApplyThrust()
{
// ForceMode.Acceleration used because using deltatime made the rocket not move. Strange issue.
rigidBody.AddRelativeForce(Vector3.up * mainThrust, ForceMode.Acceleration);
if (!audioSource.isPlaying) // Prevents audio from layering
{
audioSource.PlayOneShot(mainEngine);
}
mainEngineParticles.Play();
}
private void RespontToRotateInput()
{
rigidBody.angularVelocity = Vector3.zero; // remove rotation due to physics
float rotationThisFrame = rcsThrust * Time.deltaTime;
if (Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.forward * rotationThisFrame);
}
else if (Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(-Vector3.forward * rotationThisFrame);
}
}
void OnCollisionEnter(Collision collision)
{
if (state != State.Alive || collisionsDisabled)
return; // ignore collisions when dead or when in debug mode
switch (collision.gameObject.tag)
{
case "Friendly":
break;
case "Finish":
StartSuccessSequence();
break;
default:
StartDeathSequence();
break;
}
}
private void StartSuccessSequence()
{
state = State.Transcending;
audioSource.Stop(); // stops main engine sound
audioSource.PlayOneShot(success);
successParticles.Play();
Invoke("LoadNextScene", levelLoadDelay); // loads next level after levelLoadDelay seconds
}
private void StartDeathSequence()
{
state = State.Dying;
audioSource.Stop(); // stops main engine sound
audioSource.PlayOneShot(death);
deathParticles.Play();
Invoke("LoadCurrentLevel", levelLoadDelay);
}
private void LoadCurrentLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex);
}
private void LoadNextScene()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
int nextSceneIndex = currentSceneIndex + 1;
if (nextSceneIndex == SceneManager.sceneCountInBuildSettings)
{
nextSceneIndex = 0; // loop back to first level
}
SceneManager.LoadScene(nextSceneIndex);
}
}