I want an enemy to move towards an instantiated object

Hi, I’m trying to make an enemy gameobject gather instantiated objects. But, i get a null reference exception because the object is destroyed after being gathered. The object is removed from the hierarchy. But, it’s still selected as a pre fab. If i do / if( object != null)/ the enemy doesn’t move towards the objects .So, it either doesn’t move if i put a null exception or it does move but then i get an error because the game object has been destroyed. What do I do?

public class EnemyScript : MonoBehaviour
{
 void Update()
    {

       if (SphereObject == null)
       {
            SphereObject = GameObject.FindGameObjectWithTag("square").GetComponent<ColliderDestroy>();
        }

        if (SphereObject != null)
        {
        transform.position = Vector2.MoveTowards(transform.position, SphereObject.transform.localPosition, 2 * Time.deltaTime);
       }
public class PushButton : MonoBehaviour
{
    [SerializeField] GameObject[] arrayof;
  private void OnTriggerEnter2D(Collider2D collision)
    {
             if(collision.tag == "Player")
        {

            instan();
        }
    }    
    public void instan()
    {
        Instantiate(arrayof[0], new Vector2(Random.Range(-4, 4),Random.Range(-4,4)), Quaternion.identity);

    }

Hi Mikhail,

You could assign the position of the SphereObject to an instance variable at the top of your class. In the MoveTowards method, you use the your position variable, not the SphereObject.

However, there will be one remaining problem: You will have to define when your code is supposed to override the value of that variable.

I hope this helped. :slight_smile:


See also:

1 Like

I did reference sphereObject as (script) (variable name) ColliderDestroy SphereObject. I just didn’t paste that in.

1 Like

Can’t help you as accurately as I would want to without the full context and code, but one issue I’m seeing is that you are using two if statements meaning both will run if both conditions are true, and they might be, I obviously don’t know without seeing the full code, but what I’m trying to say here is that you should use and else statement instead, or even an else if if you need that amount of control.

if (SphereObject == null)
{
    SphereObject = GameObject.FindGameObjectWithTag("square").GetComponent<ColliderDestroy>();
}
else if (SphereObject != null)
{
    transform.position = Vector2.MoveTowards(transform.position, SphereObject.transform.localPosition, 2 * Time.deltaTime);
}

Also, Nina’s solution would work fine, what she was trying to say was not to save the reference of the sphere, but the reference to the position of the sphere, a Vector3 instead of a GameObject.

If i reference vector2 it’s not dynamically changing the position of the collectable prefab which is instantiated every time move over trigger.

I understood that your problem was the NullReferenceException when the target game object got removed from the Hierarchy. You’ll have to define your game rules exactly to be able to solve the problems in your game.

My suggestion was to keep the logic for “moving towards a target position (Vector3)” and “selecting a target (Transform or GameObject) and updating the target position (Vector3)” separate, so it’ll hopefully be easier to debug and fix NullReferenceExceptions in this context and to add more rules.

A Vector3 variable can never be null as it is a value type, hence you would never get a NullReferenceException, and your enemy will always be able to “move”.

If you referenced a prefab, your enemy will be able to move towards the prefab position only. Prefabs cannot get destroyed. They are files in your Assets folder.

1 Like

I still think Nina’s solution is perfect for this scenario where you are using update to check if there’s a sphere. Here’s some pseudo-code:

  • Check if there’s a sphere.
    • If there is, save the sphere’s position.
  • Move to the saved position.

That could fix your problem since, as Nina said, vectors can never be null. Technically your enemy will move all the time, no one would notice if there’s no deformation involved, but if there’s an animation or something else then you’ll need to find a way to make it stop, either the animation or the movement.

Could you give some actual code to see how it’s done?

It’s basically your code, just with an additional variable.

public class EnemyScript : MonoBehaviour
{
    ColliderDestroy SphereObject;
    Vector3 targetPosition;

    void Start()
    {
        targetPosition = transform.position;
    }

    void Update()
    {
        if (SphereObject == null)
        {
            SphereObject = GameObject.FindGameObjectWithTag("square").GetComponent<ColliderDestroy>();
        }
        if (SphereObject != null)
        {
            targetPosition = SphereObject.transform.position;
        }

        transform.position = Vector2.MoveTowards(transform.position, targetPosition, 2f * Time.deltaTime);
}

And if this code still does not make your enemy move, FindGameObjectWithTag("square") or GetComponent<ColliderDestroy>() probably did not return any object reference (= null).

1 Like

One thing I forgot to do was override the prefabs. But, thank you, it’s working now. I removed GetComponent<ColliderDestroy>()

final code:

          void Update()
    {

       SphereObject = GameObject.FindGameObjectWithTag("collectable");

       if (SphereObject != null)
       {  
        transform.position = Vector2.MoveTowards(transform.position, SphereObject.transform.position, 2 * Time.deltaTime);
       }

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms