0
\$\begingroup\$

The code below is producing an error message I don't understand:

Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function

I don't know where the problem is in my code or what I need to change - can someone please explain?

var XPos : float = transform.position.x;
var YPos : float = transform.position.y;
var ZPos : float = transform.position.z;
var Waiting : float = 0.02;

function OnTriggerEnter (col : Collider) {
    if (col.gameObject.tag == "Player") {
        this.transform.position = Vector3(XPos, YPos+0.1, ZPos);
        yield WaitForSeconds(Waiting);
        // ...similar code omitted
        transform.GetComponent.<Collider>().isTrigger = true;
        Destroy(gameObject);
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Fix . what.. Problem? \$\endgroup\$ – Gnemlock Nov 22 '16 at 4:04
2
\$\begingroup\$

In newer versions of Unity, the error message for this is helpfully explicit:

get_transform is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'BadJSTest' on game object 'My Object Name'. See "Script Serialization" page in the Unity Manual for further details. UnityEngine.Component:get_transform() BadJSTest:.ctor() (at Assets/Serialization/BadJSTest.js:3)

Let's unpack this a bit...

A field is a variable that you've defined outside of a function, like this:

var Waiting : float;

A field initializer is code that assigns a value to that variable in the same line where it's defined. (Since you're defining an initial value for the variable to hold, we say you're "initializing" it)

var waiting : float = 0.02;

In Unity, these initial assignments happen as the object is loaded, which is done on a loading thread separate from the main game thread.

This is good because it lets us stream in content dynamically in the background while the player enjoys the game, without halting gameplay or stuttering the framerate (if we do it right).

But it has limitations: code that's not running on the main thread is more limited in what it's allowed to do. In this case, Unity lets us know that field initializers and other code on the loading thread aren't allowed to try to read the object's transform - it's likely not ready yet.

So, we can hold off and populate these variables in Awake, Start, or OnEnable instead, like so:

#pragma strict

var XPos : float;
var YPos : float;
var ZPos : float;
var Waiting : float = 0.04;

function Awake() {
    XPos = transform.position.x;
    YPos = transform.position.y;
    ZPos = transform.position.z;
}

These methods run on the main thread after the object is completely loaded (but still before most other events we might want to respond to), so it's safe to reference the transform and other attached scripts here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.