- Home /
Fixed update called before start
Hello guys I have problem where my FixedUpdate() on movment is called before the Start() function. Afterwards the game runs fine. But there is an exception thrown. From the Documentation it should be clear however that Start() will always be called before the FixedUpdate(). The GameObject this happens on is instantiated if that makes a difference. Help would greatly appreciated and maybe it will help someone else too.
Here is the Error I get:
UnassignedReferenceException: The variable rb2d of CharacterMovement has not been assigned.
You probably need to assign the rb2d variable of the CharacterMovement script in the inspector.
UnityEngine.Rigidbody2D.get_velocity () <0x151247b0 + 0x0005f> in <0938a4547c9748338e40726420dfbb1d>:0
CharacterMovement.move (UnityEngine.Vector2 velocity) (at Assets/Scripts/CharacterMovement.cs:25)
PlayerMovement.move () (at Assets/Scripts/PlayerMovement.cs:20)
PlayerMovement.FixedUpdate () (at Assets/Scripts/PlayerMovement.cs:12)
Here are the relevant code snippets: Class Movement
using UnityEngine;
[RequireComponent(typeof(CharacterMovement))]
public class PlayerMovement : MonoBehaviour {
private CharacterMovement characterMovement;
private void Start() {
characterMovement = GetComponent<CharacterMovement>();
}
private void FixedUpdate() {
move();
}
public void move() {
float horizontalMovement = Input.GetAxisRaw("Horizontal");
float verticalMovement = Input.GetAxisRaw("Vertical");
characterMovement.resolveDirection(horizontalMovement, verticalMovement);
characterMovement.move(new Vector2(horizontalMovement, verticalMovement));
}
Class CharacterMovement
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class CharacterMovement : MonoBehaviour {
[SerializeField] protected float moveSpeed;
[HideInInspector] public Rigidbody2D rb2d;
[SerializeField] public Direction direction;
[HideInInspector] public bool readyToMove;
[HideInInspector] public Animator animator;
private void Start() {
animator = GetComponent<Animator>();
rb2d = GetComponent<Rigidbody2D>();
readyToMove = true;
}
public void move(Vector2 velocity) {
if (readyToMove) {
rb2d.velocity = velocity * moveSpeed;
rb2d.velocity = Vector2.ClampMagnitude(rb2d.velocity, moveSpeed);
playWalkingAnimation();
}
//Stop animation if player doesn't move
if (rb2d.velocity == Vector2.zero) {
animator.speed = 0;
}
}
public void stopMovement() {
rb2d.velocity = Vector2.zero;
}
I can't believe that FixedUpdate() is called before Start().
It seems that rb2d = GetComponent<Rigidbody2D>()
isn't finding a Rigidbody2D
component for some reason.
Also, put some debug statements in your code to see which gets called first:
bool fixedUpdateCalled;
private void FixedUpdate() {
if(!fixedUpdateCalled){
Debug.Log(name + " FixedUpdate() was called");
fixedUpdateCalled = true;
}
move();
}
private void Start() {
Debug.Log(name + " - Start() called");
animator = GetComponent<Animator>();
rb2d = GetComponent<Rigidbody2D>();
readyTo$$anonymous$$ove = true;
}
Answer by pako · Mar 26, 2018 at 11:43 AM
Since PlayerMovement.FixedUpdate() executes before CharacterMovement.Start() on the instantiated GameObject, you should move the code that you currently have in CharacterMovement.Start() inside CharacterMovement.Awake() :
private void Awake() {
animator = GetComponent<Animator>();
rb2d = GetComponent<Rigidbody2D>();
readyToMove = true;
}
All Awake() calls are always made before any Start() calls, even for Instantiated GameObjects.
@pako Yes this is correct. This will fix the problem however I was hoping I could avoid having it to run on Awake() since that is the way I set up the control flow in my game. (Game$$anonymous$$anagers are on Awake() etc, Physics and Rendering on Start()).
However the problem is that Unity is not very transparent as why Player$$anonymous$$ovement gets executed before Character$$anonymous$$ovement, my best guess is creation time of the script. Something like sorting layer mechanic would be neat to get around that.
Why do you insist of that control flow? Awake should be used for the objects initialization. It could be seen as the objects constructor. So Awake should handle all internal references while Start should be used to setup references between different objects.
How is that object actually "created"? Is it placed in a scene and loaded with the scene or do you instantiate it manually? If you instantiate it manually, when do you instantiate it (from which callback)? Are both components already attached and enabled or do you enable it later from code?
You can generally change the script execution order if it's necessary. However it's better to avoid relying on such explicit settings. It's better when the component just works on its own
@Bunny83 What you suggest seems like better practice than what I do actually. Thank you.
I have a basic version of the Player saved as prefab with the main components. The scripts in my question are also on this prefab. The prefab gets Instantiated and then further adjusted from a deserialized SaveGame.
And yes I really try to change the script execution order as little as possible to avoid further complications with the engine itself.
However the problem is that Unity is not very transparent as why Player$$anonymous$$ovement gets executed before Character$$anonymous$$ovement, my best guess is creation time of the script. Something like sorting layer mechanic would be neat to get around that.
It's just random execution order, i.e. you can't rely on a specific order of execution, unless you set it explicitly, but even then, there are certain occasions that the explicitly set order of execution is ignored by Unity. Personally, I prefer to find a solution without explicitly setting the order of execution of scripts.
Answer by cvid · Mar 25, 2018 at 04:07 PM
Hi, @perikless
Here is a mistake in CharacterMovement.cs line 25. Correct version for move method will be:
public void move(Vector2 velocity) {
if (readyToMove)
{
rb2d.velocity = velocity * moveSpeed;
rb2d.velocity = Vector2.ClampMagnitude(rb2d.velocity, moveSpeed);
playWalkingAnimation();
//Stop animation if player doesn't move
if (rb2d.velocity == Vector2.zero)
{
animator.speed = 0;
}
}
}
Please note, that in your case FixedUpdate() called for PlayerMovement behaviour, so it's guaranteed to be after Start() but only for PlayerMovement, not for CharacterMovement.
Could you please pinpoint the mistake you have spotted. As I see it your code is identical to the OP's code. What am I missing?
Please note, that in your case FixedUpdate() called for Player$$anonymous$$ovement behaviour, so it's guaranteed to be after Start() but only for Player$$anonymous$$ovement, not for Character$$anonymous$$ovement
This is not so. FixedUpdate()
is always called after Start()
has been called in all scripts.
What you are saying is valid only for Awake() - OnEnabled()
: OnEnabled()
is always called immediately after the Awake()
of the same script, but before the Awake()
of other scripts.
O$$anonymous$$, I see what you mean by "mistake". You moved the if (rb2d.velocity == Vector2.zero)
block inside the if (readyTo$$anonymous$$ove)
block.
That's not a mistake. It's good as it is, and it any case, it has nothing to do with the problem.
@pako That is correct , thanks for pointing it out.
@pako You are right. But only in case of objects that already exist on scene load. FixedUpdate for some behaviour can be called earlier than Start for another in case of instanciating.
Thanks for pointing out. That, would explain the problem. As I said in my other comment, I have never tested this, because I generally use pooling rather than "Instantiate on demand", and I have all pooled objects pre-existing in the scene, i.e. they all exist on scene load.
Answer by perikless · Mar 25, 2018 at 05:09 PM
Thank you very much for your answer. @cvid
If I see this correctly you suggest the second if
statement to be nested. However other parts of the game interact with the bool readyToMove
and I need it outside.
My current workaround to the problem is to remove the [HideInInspector]
tag and drop the components of the prefab into that field. I was unware that is possible with components on the same object.
Nonetheless I am a bit confused as to why this issue happens. The Unity Manual states the following:
For objects added to the scene, the Start function will be called on all scripts before Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.
However I would assume the Start()
in the Instantiated Object would run before the FixedUpdate()
on the same Object
@perikless have you seen the comment I posted just below your question? I have to ask this, because it seems that you haven't, and many times the system automatically hides these comments, and you have to click on the "Show" link to see them.
@perikless I'm not sure, but I would think that this is applicable for scripts on different GameObjects:
... Naturally, this cannot be enforced when an object is instantiated during gameplay
If you include the debug statements I mentioned in my comment, we'll see if it's applicable for scripts on the same GameObject too. If so, it would explain the problem.
I avoid Instantiating GameObjects during gameplay, this is why I have never come across this issue. Instantiation is rather heavy on performance. I prefer to pool all the necessary GameObjects, and enable/disable them when I need them. Enabling/Disabling is "light" on performance, especially when compared to Instantiated/Destroy.
@pako Yes I did miss your comment below the question. With the Debug Statements I was able find out that the script Player$$anonymous$$ovement.cs is executed before the Character$$anonymous$$ovement.cs But since Player$$anonymous$$ovement depends on my Character$$anonymous$$ovement character$$anonymous$$ovement = GetComponent<Character$$anonymous$$ovement>();
Is there some way to work around that besides Unitys Script Execution Order, because I don´t want to put Character$$anonymous$$ovement before default time.
This is only one object: The players character. Thats why I don't have object pooling here. But would you even recommend object pooling for single objects? I don't know what the best practice is here.
Pooling is for multiple GamObjects. However, since you always need a player in the scene :-) you could have the player GameObject preexisting in the scene. This player GameObject could be disabled by default, if you need it so before action starts, and enable it when the action starts.
I wanted to get to the bottom of this, so I made some tests.
If all GameObjects are already in the scene, Start() is always called before Update() and FixedUpdate() (as expected)
If not all GameObjects are already in the scene, Start() is called first for the Objects that are in the scene, and then Start() is called for Objects that get Instantiated. Also, Start() always gets called before Update() (as expected), but not FixedUpdate(). FixedUpdate() for instantiated objects is called immediately after their Start(). So, if an object pre-exists in the scene and has an Update() but an instantiated objects has a FixedUpdate(), the Start() of the preexisting object will be called first, followed by the Start() of the Instantiated object, immediately followed by the FixedUpdate() of the Instantiated object, and finally the Update() of the preexisting object.
If the Instantiated object has 2 scripts as in this case, again, the FixedUpdate() of each script will follow immediately after the Start() of the same script. The order of execution of these 2 scripts seem random.
If the Instantiated object has 2 scripts with Update() ins$$anonymous$$d of FixedUpdate() the Start() of each script would execute first and then the Update() of each script (as expected).
@pako Thank you so much for your research. This clears a lot of things up. I further elaborated in a comment to your answer.