-1
\$\begingroup\$

I have a class (EnemyBehaviour) which extends MonoBehaviour, this class has the following two methods:

    private Enemy enemy;

    public void set(Enemy enemy)
    {
        this.enemy = enemy;
    }

    public Enemy get()
    {
        return this.enemy;
    }

This class also has the unity method:

    public void Update()
    {
        Debug.Log(this.enemy);
    }

This method always prints Null.

But, If I call the get() method outside the self MonoBehaviour it returns the right instance.

    var eb = enemy.getGameObject().GetComponent<EnemyBehaviour>();
    Debug.Log(eb.get()); // it returns UnityEngine.Debug:Log(Object)

The Enemy class is a class which encapsulates the EnemyBehaviour.

public class Enemy
{
    private GameObject gameObject;
...

Then, I don't understand why inside the Update(), Start(), OnMouseDown(), or any "Unity method" the enemy property is Null. But if I access the property outside these methods (enemy.getGameObject().GetComponent().get()) it works.

I suspect that Unity MonoBehavour has it's own scope and the GetComponent() other scope.

Another strange thing is if instead of storing the "Enemy" class inside the Behaviour I store a string or Vector3, it works like a charm.

Any idea? Thanks

Edit:

Simplification of the problem: I have an Empty Game Object (Kernel) which instantiates all the other game objects, this has a Kernel class which extends the MonoBehaviour:

    public void Start()
    {
        var enemyGameObject = Resources.Load<GameObject>("Prefab/Enemy");
        var enemyBehaviour = enemyGameObject.transform.GetComponent<EnemyBehaviour>();
        var foo = new Foo();
        enemyBehaviour.Foo = foo;
        Instantiate(enemyGameObject);
        Debug.Log(enemyBehaviour.Foo); // OK, This one works
    }

Foo is a dummy class.

public class Foo
{
}

EnemyBehaviour just does:

public class EnemyBehaviour : MonoBehaviour
{
    public Foo Foo;

    public void OnMouseDown()
    {
        Debug.Log(Foo); // When I click on the GameObject, prints Null, it's not working
    }

Strange thing: If I replace the var foo = new Foo(); by var foo new Vector3(5,5,5); (Including chaning the type in EnemyBehaviour of course (public Foo Foo; -> public Vector3 Foo;)) everything works fine :S

Edit 2:

Found the issue, was related with the prefab, I was setting the Foo to the Prefab instead of the instance, Fix:

        var instance = Instantiate(enemyGameObject);
        var enemyBehaviour = instance.transform.GetComponent<EnemyBehaviour>();
\$\endgroup\$
6
  • \$\begingroup\$ Hello, there is a vital missing information there. When do you call set? \$\endgroup\$
    – sebas
    Commented Oct 28, 2017 at 13:04
  • \$\begingroup\$ I'm unable to reproduce the issue from the information given here. In my tests, the update method prints null only before I've assigned an instance of the Enemy class to the enemy member variable, as expected. Once I've assigned a reference to that member variable, the Update method prints non-null from then on. Can you try to construct a complete verifiable test case? \$\endgroup\$
    – DMGregory
    Commented Oct 28, 2017 at 13:09
  • \$\begingroup\$ I load the enemy from a prefab: Resource.load<GameObject>("Prefab/Enemy");, and then I construct the Enemy: new Enemy(gameObject);, and then i Instantiate the GO with ...Instantiate(gameObject);, and finally I set the enemy to the behaviour: enemyGameObject.transform.GetComponent<EnemyBehaviour>().set(this); \$\endgroup\$
    – fj123x
    Commented Oct 28, 2017 at 13:37
  • \$\begingroup\$ updated a bit more \$\endgroup\$
    – fj123x
    Commented Oct 28, 2017 at 14:14
  • \$\begingroup\$ If you've solved the issue, it's better to post the solution as an Answer so it's easy for other devs who have similar issues to find your solution and learn from your experience. \$\endgroup\$
    – DMGregory
    Commented Oct 28, 2017 at 14:37

1 Answer 1

1
\$\begingroup\$

The problem was related with the prefab, I was setting the Foo to the Prefab instead of the instance, Fix:

    var instance = Instantiate(enemyGameObject);
    var enemyBehaviour = instance.transform.GetComponent<EnemyBehaviour>();
\$\endgroup\$
1
  • \$\begingroup\$ Tip: if you define your enemyGameObject variable as being of the type EnemyBehaviour to begin with, you can get your instance of the component directly from Instantate without needing to follow-up with a GetComponent call. This still instantiates the whole object and its hierarchy, not just a free-floating component. \$\endgroup\$
    – DMGregory
    Commented Mar 7, 2018 at 13:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .