- Home /
FixedUpdate is not called after loading a level for the second time
I'm working on a small prototype for a platformer/RPG hybrid for fun. I've been struggling with this issue for a while, and I can't seem to find a solution.
In my project, I have two scenes. The Main Menu, "mainmenu", and my prototype scene, "experiment". The player can go to and from these scenes: pressing the Continue button in the main menu opens up the prototype scene. In the prototype scene, the player can pause the game, which brings up a pause menu, from which they can choose to go to main menu.
However, when loading the prototype scene a second time, FixedUpdate methods are no longer called. I've checked this by putting print inside a FixedUpdate method on multiple scripts. The Console will print the first time the scene is loaded (either from the main menu or directly from the Editor), but not when it's loaded the second time, by going to the menu from the prototype scene, then reloading the prototype scene.
I don't know what causes this. All objects that should be loaded are there, as well as all components. But anything in FixedUpdate does not work, even if the other methods do.
Here's the code I've made: the MainMenuHandler that's in the "mainmenu" scene, the PauseMenuHandler that's in the "experiment" scene, and the PhysicsObject used to create gravity and movement for the player. I've used the 2D Game Creation tutorials for the PhysicsObject script, with a few additions.
MainMenuHandler:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
public class MainMenuHandler : MonoBehaviour {
//for exit game
/*public GameObject ExitPopup;
protected bool ExitGameMenuOpen;*/
//components
protected SaveDataHandler saveData;
protected GameObject ContinueButton;
protected GameObject NewGameButton;
protected EventSystem eventSystem;
protected PartyHandler party;
//main menu character images
public GameObject FenrysImage;
// Use this for initialization
void Awake ()
{
saveData = SaveDataHandler.saveData;
ContinueButton = GameObject.Find("ContinueButton");
NewGameButton = GameObject.Find("NewGameButton");
eventSystem = GameObject.Find("EventSystem").GetComponent<EventSystem>();
if(saveData.LoadDataAvailable == false)
{
ContinueButton.SetActive(false);
eventSystem.firstSelectedGameObject = NewGameButton;
} else
{
ShowMainMenuCharacters();
}
}
void OnEnable()
{
if(saveData.LoadDataAvailable == true)
{
ShowMainMenuCharacters();
}
}
public void ShowMainMenuCharacters()
{
party = PartyHandler.party;
if(party.FenrysInParty)
{
FenrysImage.SetActive(true);
}
}
public void ExitGame()
{
Application.Quit();
}
public void NewGame()
{
SceneManager.LoadScene("experiment", LoadSceneMode.Single);
}
public void Continue()
{
saveData.LoadData();
SceneManager.LoadScene("experiment", LoadSceneMode.Single);
}
}
PauseMenuHandler:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
[Serializable]
public class PauseMenuHandler : MonoBehaviour {
//components
public GameObject pauseUI;
protected AudioSource bgm;
protected PlayerControl player;
protected SaveDataHandler saveData;
protected bool pauseOn;
// Use this for initialization
void Awake ()
{
bgm = GameObject.Find("BGM").GetComponent<AudioSource>();
player = GameObject.FindWithTag("Player").GetComponent<PlayerControl>();
saveData = SaveDataHandler.saveData;
}
// Update is called once per frame
void Update ()
{
if(Input.GetButtonDown("Menu"))
{
if(Time.timeScale == 1 && !pauseOn)
{
ShowPauseMenu();
}
else if(Time.timeScale == 0 && pauseOn)
{
HidePauseMenu();
}
}
}
public void ShowPauseMenu()
{
pauseOn = true;
Time.timeScale = 0;
bgm.Pause();
pauseUI.SetActive(true);
player.ControlOff();
}
public void HidePauseMenu()
{
pauseOn = false;
Time.timeScale = 1;
bgm.Play();
pauseUI.SetActive(false);
player.Invoke("ControlOn", 0.0f);
}
public void GoToMainMenu()
{
SaveDataHandler.saveData.SaveData();
SceneManager.LoadScene("mainmenu");
}
public void SaveGame()
{
SaveDataHandler.saveData.SaveData();
}
}
PhysicsObject:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsObject : MonoBehaviour {
//public values for easy tweaking
[Header("Generic Physics Settings")]
public float minGroundNormalY = .65f;
public float groundedGravity = 1f;
public float gravityModifier = 1f;
//values used in this script
protected Vector2 velocity;
protected Vector2 targetVelocity;
//[HideInInspector]
public bool grounded;
protected Vector2 groundNormal;
protected Rigidbody2D rb2d;
protected ContactFilter2D contactFilter;
protected RaycastHit2D[] hitBuffer = new RaycastHit2D[16];
protected List<RaycastHit2D> hitBufferList = new List<RaycastHit2D> (16);
protected const float minMoveDistance = 0.0001f;
protected const float shellRadius = 0.01f;
protected bool rightWallTouch = false;
protected bool leftWallTouch = false;
//activated when the game starts
void OnEnable()
{
contactFilter.useTriggers = false;
contactFilter.SetLayerMask (Physics2D.GetLayerCollisionMask (gameObject.layer));
contactFilter.useLayerMask = true;
rb2d = GetComponent<Rigidbody2D> ();
print("PhysicsObjEnable");
}
void Update ()
{
targetVelocity = Vector2.zero;
ComputeVelocity ();
}
//computevelocity is used in the playercontrol script
protected virtual void ComputeVelocity()
{
}
protected void FixedUpdate()
{
print("FixedUpdate running");
if(!grounded)
{
velocity += gravityModifier * Physics2D.gravity * Time.deltaTime;
}
else if (grounded)
{
velocity += groundedGravity * Physics2D.gravity * Time.deltaTime;
}
velocity.x = targetVelocity.x;
grounded = false;
Vector2 deltaPosition = velocity * Time.deltaTime;
Vector2 moveAlongGround = new Vector2 (groundNormal.y, -groundNormal.x);
Vector2 move = moveAlongGround * deltaPosition.x;
Movement (move, false);
move = Vector2.up * deltaPosition.y;
Movement (move, true);
}
void Movement(Vector2 move, bool yMovement)
{
float distance = move.magnitude;
if (distance > minMoveDistance)
{
int count = rb2d.Cast (move, contactFilter, hitBuffer, distance + shellRadius);
hitBufferList.Clear ();
for (int i = 0; i < count; i++) {
hitBufferList.Add (hitBuffer [i]);
}
for (int i = 0; i < hitBufferList.Count; i++)
{
Vector2 currentNormal = hitBufferList [i].normal;
if (currentNormal.y > minGroundNormalY)
{
grounded = true;
if (yMovement)
{
groundNormal = currentNormal;
currentNormal.x = 0;
}
}
float projection = Vector2.Dot (velocity, currentNormal);
if (projection < 0)
{
velocity = velocity - projection * currentNormal;
}
float modifiedDistance = hitBufferList [i].distance - shellRadius;
distance = modifiedDistance < distance ? modifiedDistance : distance;
}
foreach (RaycastHit2D hit in hitBufferList)
{
if (hit.collider.gameObject.tag == "RightWall") {
rightWallTouch = true;
leftWallTouch = false;
} else if (hit.collider.gameObject.tag == "LeftWall") {
rightWallTouch = false;
leftWallTouch = true;
} else {
rightWallTouch = false;
leftWallTouch = false;
}
}
}
rb2d.position = rb2d.position + move.normalized * distance;
}
}
Answer by Harinezumi · May 17, 2018 at 11:08 AM
You forgot to reset Time.timeScale
when you go back to the main menu, and so time doesn't pass and FixedUpdate()
isn't called anymore. Either reset it just before you load the menu scene, or each scene set Time.timeScale
to 1 when it starts.
Your answer
