[BUG?] Game freezes or I get error. C#

Hello, all!

Could you guys help me?

I’am scripting a IA (FSM) for my enemy: A simple follow and idle FSM.

Here’s the code:

using UnityEngine;
using System.Collections;

public class enemy_IA : MonoBehaviour {

	// Use this for initialization
	public GameObject particleHit;
	public GameObject particleDead;
	public float life = 10.0f;
	private GameObject player;
	public float minDist = 3.0f;

	public enum States
	{
		Idle,
		FollowChar
	}

	private States state;

	void Start () {
		state=States.Idle;
		StartCoroutine(UpdateFSM());
		//player = GameObject.FindWithTag("Player");
	}
	
	// Update is called once per frame
	void Update () {
		player = GameObject.FindWithTag("Player");
	}
	
	void Idle(){
		Debug.Log("to parado");
	}

	void FollowChar(){
		Debug.Log("to te seguindo");
	}

	void ApplyHit(){


	}

	void ApplyDamage(float dano){
		life=life-dano;

		GameObject particula1;
		particula1 = Instantiate(particleHit, transform.position , transform.rotation) as GameObject;

		if(life <= 0.0f){
			life=0.0f;
			Morto();
		}
	}

	void Morto(){
		GameObject particula2;
		particula2 = Instantiate(particleDead, transform.position , transform.rotation) as GameObject;
		Destroy(gameObject);
	}

	IEnumerator UpdateFSM(){
		while(true){
			if(state==States.Idle){
				if(jogador_perto())
					state=States.FollowChar;
				else Idle();
			}else if(state==States.FollowChar){
					if(jogador_longe())
					state=States.Idle;
				else FollowChar();
				}
			}
			yield return new WaitForSeconds(0.1f);
		}
	bool jogador_perto(){
		Vector3 distancia = gameObject.transform.position - player.gameObject.transform.position;
		if(distancia.magnitude <= minDist)return true;
		else return false;
	}

	bool jogador_longe(){
		Vector3 distancia = transform.position - player.transform.position;
		if(distancia.magnitude >= minDist*2.0f)return true;
		else return false;
	}
	}

If I press PLAY, I’ll get this error:

NullReferenceException
enemy_IA.jogador_perto () (at
Assets/Standard
Assets/Scripts/With_Love_Scripts/enemy_IA.cs:78)
enemy_IA+c__Iterator0.MoveNext
() (at Assets/Standard
Assets/Scripts/With_Love_Scripts/enemy_IA.cs:66)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
enemy_IA:Start() (at Assets/Standard
Assets/Scripts/With_Love_Scripts/enemy_IA.cs:23)

If I change the GameObject player to PUBLIC, and set it thru code or manually, the game freezes.

What do I do? What I’m doing worng?

  1. Check if object tagged as “Player” exists before you define your variable using the tag.

  2. Check if “player” is null before using any of its properties in the code: if(player != null).

  3. You had your yield in the wrong place in a couroutine causing Unity to hang. Try this.

    using UnityEngine;
    using System.Collections;

    public class enemy_IA : MonoBehaviour
    {
    public GameObject particleHit;
    public GameObject particleDead;
    public float life = 10.0f;
    private GameObject player;
    public float minDist = 3.0f;
    Vector3 distancia;

    enum States
    {
    	Idle,
    	FollowChar
    }
    
    States state;
    
    void Start () 
    {
    	state=States.Idle;
    	StartCoroutine(UpdateFSM());
    
    	if(GameObject.FindWithTag ("Player"))
    		player = GameObject.FindWithTag("Player");
    	else
    		print ("GameObject tagged Player not found!");
    }
    
    void Idle()
    {
    	Debug.Log("to parado");
    }
    
    void FollowChar()
    {
    	Debug.Log("to te seguindo");
    }
    
    void ApplyHit()
    {	
    	
    }
    
    void ApplyDamage(float dano)
    {
    	life=life-dano;
    	
    	GameObject particula1;
    	particula1 = Instantiate(particleHit, transform.position , transform.rotation) as GameObject;
    	
    	if(life <= 0.0f)
    	{
    		life=0.0f;
    		Morto();
    	}
    }
    
    void Morto()
    {
    	GameObject particula2 = (GameObject)Instantiate(particleDead, transform.position, transform.rotation);
    	Destroy(gameObject);
    }
    
    IEnumerator UpdateFSM()
    {
    	while(true)
    	{
    		if(state==States.Idle)
    		{
    			if(jogador_perto())
    				state=States.FollowChar;
    			else Idle();
    		}
    
    		else if(state==States.FollowChar)
    		{
    			if(jogador_longe())
    				state=States.Idle;
    			else FollowChar();
    		}
    		yield return new WaitForSeconds(0.1f);
    	}
    }
    
    bool jogador_perto()
    {
    	if(player != null)
    		distancia = gameObject.transform.position - player.gameObject.transform.position;
    
    	else
    		print ("Player is NULL!");
    
    	if(distancia.magnitude <= minDist)return true;
    	else return false;
    }
    
    bool jogador_longe()
    {
    	if(player != null)
    		 distancia = transform.position - player.transform.position;
    
    	else
    		print ("Player is NULL!");
    
    	if(distancia.magnitude >= minDist*2.0f)return true;
    	else return false;
    }
    

    }

player = GameObject.FindWithTag(“Player”) should not be called in Update (). Instead, set it once in Start () (which you have, but commented out), which will ensure the reference is assigned before the UpdateFSM coroutine runs.

You can try also to add yield return null; like this:

IEnumerator UpdateFSM(){
       while(true){
         if(state==States.Idle){
          if(jogador_perto())
              state=States.FollowChar;
          else Idle();
         }else if(state==States.FollowChar){
              if(jogador_longe())
              state=States.Idle;
          else FollowChar();
          }
          yield return null; //Add this
         }
         yield return new WaitForSeconds(0.1f);
       }