Andrea Ravasio
Andrea Ravasio

Reputation: 11

Player's jumping compromised after reloading the scene in Unity

First of all, please don't get too technical: I've only been studying Unity coding for two months and I'm not a programmer in general! I'm a total beginner! :-) So, I'm building a game where you control a ball on a treadmill avoiding endless spawning obstacles by shifting left-right and jumping. I set up a restart function after game over with SceneManager.LoadScene method, it works, but after reloading the jumping function gets compromised: it looks like there's an invisible wall above the player blocking its jumps. And it also looks like it's an "additive" issue: if I die and restart again, the player jumps even less, until it just doesn't jump at all. The other functions seem fine. Any idea why that happens?

public class PlayerController : MonoBehaviour
    //Jump code:

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isOnLane)
                {
                    Jump();
                }
    }
void Jump()
        {
            playerRb.AddForce(Vector3.up * forceMult, ForceMode.Impulse);
            isOnLane = false;
        }
private void OnCollisionEnter(Collision other)
        {
            //checks if player is touching the ground
            if (other.gameObject.CompareTag("Lane"))
            {
                isOnLane = true;
            }
        }

Restart code:

public class GameManager : MonoBehaviour

    //restart game by clicking Restart Button
        public void RestartGame()
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

Thanks!

Upvotes: 0

Views: 1289

Answers (2)

Starbugz
Starbugz

Reputation: 131

I met the same issue before. It was due to the gravity modifier, just like code before.

Physics.gravity *= gravityModifier;

Physics was not reset before loading the scene and so its new value from a first game was kept and multiplied at each reload.

Solved it by reseting the gravity before loading the scene

 public void RestartGame()
        {
            Physics.gravity = new Vector3(0, -9.8f, 0); //The default gravity in project settings
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

Upvotes: 0

Selzier
Selzier

Reputation: 101

The problem is that additive scene loading is being used when there is only a single scene. It would be good to break these up into 2 scenes:

  • A scene for GameManager & the Player object
  • A scene for the level itself which is being reloaded

This way the GameManager is not being reloaded and the player is not being reloaded. Upon reload you need to "reset" variables for the player back to 0 and move him to a starting position.

RestartGame needs some logic to reset the player and his physics.

public void RestartGame()
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
            playerController.playerRb.velocity = Vector3.zero;
            playerController.playerRb.angularVelocity = Vector3.zero;
            playerTransform.position = spawnLocation.tranform.position;
        }

You probably want to unload the scene, wait for 1 frame, and then load the scene. This way variables in the scene get reset properly.

public void RestartGame()
{
    SceneManager.UnloadScene(scene);
    playerController.playerRb.isKinematic = true; // Try setting kinematic between scenes
    StartCoroutine(RestartLoad());
}

private IEnumerator RestartLoad() 
{
    yield return new WaitForEndOfFrame();
    // Reset the player here
    SceneManager.LoadScene(scene);
    playerController.playerRb.isKinematic = false; // Player can use physics again
}

Upvotes: 0

Related Questions