Parent Class unable to refer to player script

Parent Class Code:

    public Sprite physical;
    public Sprite spirit;
    playerController playerScript;
    void Awake()
    {
        playerScript = GameObject.FindWithTag("Player").GetComponent<playerController>();
    }

    public void formHandler(SpriteRenderer enemyRenderer)
    {
        if(playerScript.spiritForm)
        {
            enemyRenderer.sprite = spirit;
        }
        else
        {
            enemyRenderer.sprite = physical;
        }
    }

Child Class Code:

    SpriteRenderer myRenderer
    void Awake()
    {
        myRenderer = GetComponent<SpriteRenderer>();
    }

    void Update()
    {
        formHandler(myRenderer);
    }

Error:
NullReferenceException: Object reference not set to an instance of an object
allEnemies.formHandler (UnityEngine.SpriteRenderer enemyRenderer) (at Assets/-Scripts/allEnemies.cs:96)
enemyController.Update () (at Assets/-Scripts/enemyController.cs:29)

The error is referring to my ‘playerScript’ variable in the if-statement of formHandler in the parent class I believe. Seems to think that ‘playerScript’ doesn’t exist or something.

A different function in the parent class was successfully used in the child class so I’m a little lost as to why this function does not work since it’s so simple. I was able to put the code for formHandler into the Update function of the child class and it successfully worked. Am I not seeing something about inheritance?

I’m still new to Unity so I would appreciate any insight.

If playerScript is null, then you might not have what you need there properly setup. But from the error, your null value is on line 96 and seems to point to enemyRenderer. Which actually suggest your update call is passing in a null value. Is the myRenderer you are passing in actually being set to something?

I think the error message is saying the error occurs on line 96 for function formHandler with parameter UnityEngine.SpriteRenderer enemyRenderer. I’m fairly certain it’s complaining about my playerScript because if I remove the if-statement then I get no complaints. I’m also certain myRenderer is being set properly as I’m able to change the color of the object via myRenderer.material.color

Debug.Log everything until you figure out what is null.

If you only have 1 gameobject with the playerController script, you can use this instead:

playerScript = GameObject.FindObjectOfType<playerController>();

If this does not work, then the issue is not in defining playerScript. I have no idea what the relationship between these 2 scripts are. the only common names between them is the “formHandler” function. If you are indeed trying to access the “formHandler” function of the parent class from the child class, it should be done like this:

//in the child script
transform.parent.GetComponent<ParentClassName>().formHandler(myRenderer);
//I dont know what the the name of the class is on your parent object, but you need to substitute ParentClassName for whatever its name is.
1 Like

Interesting, some reason when I use that line to call the formHandler function in the child class it works. However, I don’t understand why I’m able to call a different function without the extra information at the beginning. I’ll post the code for the other function below for the parent and child classes.

Parent Class (allEnemies):

    /*
    INPUT:  enemyPosition  - current position of enemy
            tetherPoint    - center point of patrol
            enemyRigidbody - rigidbody2d component of enemy
            patrolDistance - length from tether point to edge of patrol
    OUTPUT: turningAround  - true if leaving current endpoint to go to next one, false if en route
    RETURN: None
    SIDE EFFECTS: enemies patrol a path
    */
    public void patrol(Vector3 enemyPosition, Vector3 tetherPoint, Rigidbody2D enemyRigidbody, float patrolDistance, bool turningAround)
    {
        if( ((enemyPosition.x >= (tetherPoint.x + patrolDistance)) ||
             (enemyPosition.x <= (tetherPoint.x - patrolDistance))) && !turningAround)
        {
            turningAround = true;
            Vector2 reverseSpeed = enemyRigidbody.velocity;
            reverseSpeed.x = -reverseSpeed.x;
            enemyRigidbody.velocity = reverseSpeed;
        }
        else if( ((enemyPosition.x < (tetherPoint.x + patrolDistance)) ||
                  (enemyPosition.x > (tetherPoint.x - patrolDistance))) && turningAround)
        {
            turningAround = false;
        }
    }

Child Class (enemyController):

    void Update()
    {
        transform.parent.GetComponent<allEnemies>().formHandler(myRenderer);
        //formHandler(myRenderer);
        patrol(transform.position, tetherPoint, myRigidbody, 3f, turningAround);
    }

The formHandler and patrol functions are all defined in the parent class and are both called in the Update function of the child class. Patrol functions perfectly fine when called this way, but formHandler gives me that error if I try to do the same.

Try searching for the word “patrol” in your enemyController script. you may have a function that looks like this:

//in enemyController
void patrol(...params...){
    transform.parent.GetComonent<allEnemies>().patrol(...params...);
}

Or maybe you have a duplicate of the function in your enemyController script.

I’ve never encountered a situation where i can call a function of one script from another script without first establishing a path between the two scripts.

This is still a rather short script and I don’t have any sort of line that establishes the path for patrol in enemyController. I also have another function in allEnemies named ‘wander’ that works when I call it without any sort of path from Update in enemyController. I’ll throw the entire enemyController script up just in case I’m not seeing anything.

Child Class (enemyController):
```csharp
**using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class enemyController : allEnemies
{
private bool turningAround;
private Vector3 tetherPoint;
private Rigidbody2D myRigidbody;
private SpriteRenderer myRenderer;

void Awake()
{
    myRigidbody = GetComponent<Rigidbody2D>();
    myRenderer = GetComponent<SpriteRenderer>();
}

// Use this for initialization
void Start()
{
    turningAround = false;
    tetherPoint = transform.position;
    myRigidbody.velocity = new Vector2(moveSpeed, 0);
}

// Update is called once per frame
void Update()
{
    if(myRenderer == null)
        Debug.Log("ERROR: RENDERER IS NULL");
    transform.parent.GetComponent<allEnemies>().formHandler(myRenderer);
    //formHandler(myRenderer);
    patrol(transform.position, tetherPoint, myRigidbody, 3f, turningAround);
}

}**
```

The allEnemies script is attached to a parent object whose children will all have enemyController attached as a script. Is this information that might be causing this odd behavior?

No, your enemyController script extends from your allEnemies script.

//your class
public class enemyController : allEnemies {
...
}

//usually in Unity
public class ClassName: MonoBehaviour {
...
}

//script which inherits from nothing
public class ClassName {
...
}

This means enemyController is inheriting from allEnemies. I recommend you read up on what inheritance is, rather than ask little by little in the forums. If you want to access properties of a script from other scripts, the most foolproof way is the method that solved your issue in my previous reply, although the general idea is to have access to the script before making use of it, so using transfrom.parent will not work if the script you are trying to access is not in the parent object of the game object attached with the script you are trying to gain access from.

Are you following a tutorial which made things this way?

I know enemyController inherits from allEnemies, hence the child and parent terminology. I was just wondering why patrol was successfully being called without a path. I’ve gone ahead and used the pathing you mentioned earlier and everything is working just fine. I haven’t been following a tutorial, was just doing my own thing. Thanks for your help.

So you know you are using inheritance, but you don’t seem to know what it actually does. In your situation, due to your usage of inheritance, you are not really accessing the parent’s patrol function, but rather that instance of enemyController’s patrol function. Since enemyController inherits properties from allEnemies. In a strange reversal, it becomes a mystery of why you are not able to access formHandler from allEnemies in enemyController if enemyController inherits from allEnemies.

1 Like

Ahhh, so when I was calling formHandler it would complain about the playerScript reference because enemyController itself does not have any such reference. Whereas in the patrol function, enemyController has all the necessary references. That clears it up completely. Hope my last post didn’t sound defensive. Thanks so much!

1 Like