(SOLVED)I have some problems with creating boss ai script

Hi guys i am really new at programming something. I am trying to make a boss ai system for my project but when i try to run my project its freezing because of instantiate loop. I can’t solve this problem could you help me.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BasicBossAI : MonoBehaviour
{
   
    public enum BossMoves
    {
        Idle,
        Move,
        Jumpattack,
        DashAttack,
        LaserAttack
    }
    public BossMoves currentState = BossMoves.Idle;
    public float distance = 10.0f;
    public GameObject Player;
    public GameObject Boss;
    public GameObject MovePosition;
    public float BossMoveSpeed = 10.0f;
    private Transform target;
    public int ObjCounter;
    void Start()
    {
     
    }


    void Update()
    {
    start:
       

       
        if (Vector2.Distance(Player.transform.position, Boss.transform.position) > distance)
        {
            currentState = BossMoves.Move;
        }
        else
        {
            currentState = BossMoves.Idle;
        }

        if (currentState == BossMoves.Idle)
        {
            BossWaiting();
            goto start;

        }
      
        if (currentState == BossMoves.Move)
        {
            Transform Playerpos = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
            ObjCounter = GameObject.FindGameObjectsWithTag("Movepos").Length;
            if (ObjCounter < 1)
            {
                Instantiate(MovePosition, Playerpos.position, Playerpos.rotation);
            }

            target = MovePosition.GetComponent<Transform>();
            Boss.transform.position = Vector2.MoveTowards(transform.position, target.position, BossMoveSpeed * Time.deltaTime);

            if (Vector2.Distance(MovePosition.transform.position, Boss.transform.position) > 3.0f)
            {
                transform.position = Vector2.MoveTowards(transform.position, target.position, BossMoveSpeed * Time.deltaTime);

            }
            else
            {
                Destroy(MovePosition);
                currentState = BossMoves.Idle;
                goto start;
            }

        }


    }




    IEnumerator BossWaiting()
    {
        //Boss waiting for another move
         yield return new WaitForSeconds(3);
               
       
    }
}

Ok - a couple of things.

You probably don’t need your “goto” statements. The Update() function fires for every frame of your game, so it will naturally start over regularly. Just let you code naturally flow to the end. This will help you avoid accidental closed loops.

Try to avoid any “find” operations within your Update() function, as these are relatively slow. For example. avoid Transform Playerpos = GameObject.FindGameObjectWithTag(“Player”) and instead either define “Player” as a public gameobject and drag your player GameObject into it in the editor, or if you need to use find, do it in the Start() function where it is only done once.

Similar for your “ObjCounter = GameObject.FindGameObjectsWithTag(“Movepos”).Length;”. Instead, perhaps just define “objCounter” as a INT variable at the beginning, then increment it each time you instantiate an object and decrease it each time you destroy an object:

Instantiate(MovePosition, Playerpos.position, Playerpos.rotation);
ObjCounter+=1;


Destroy(MovePosition);
ObjCounter-=1;

Hope that helps.

DC

1 Like
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BasicBossAI : MonoBehaviour
{
  
    public enum BossMoves
    {
        Idle,
        Move,
        Jumpattack,
        DashAttack,
        LaserAttack
    }
    public BossMoves currentState = BossMoves.Idle;
    public float distance = 10.0f;
    public GameObject Player;
    public GameObject Boss;
    public GameObject MovePosition;
    public float BossMoveSpeed = 10.0f;
    private Transform target;
    public int ObjCounter = 0;
    public Transform Playerpos;
    void Start()
    {
       
    }


    void Update()
    {
      
        if (Vector2.Distance(Player.transform.position, Boss.transform.position) > distance)
        {
            currentState = BossMoves.Move;
        }
        else
        {
            currentState = BossMoves.Idle;
        }

        if (currentState == BossMoves.Idle)
        {
            BossWaiting();
          

        }
     
        if (currentState == BossMoves.Move)
        {
            Playerpos = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
            if (ObjCounter < 1)
            {
                Instantiate(MovePosition, Playerpos.position, Playerpos.rotation);
                ObjCounter += 1;
            }
            MovePosition = GameObject.FindGameObjectWithTag("Movepos");

            target = MovePosition.GetComponent<Transform>();
            //Boss.transform.position = Vector2.MoveTowards(transform.position, target.position, BossMoveSpeed * Time.deltaTime);

            if (Vector2.Distance(MovePosition.transform.position, Boss.transform.position) > 3.0f)
            {
                transform.position = Vector2.MoveTowards(transform.position, target.position, BossMoveSpeed * Time.deltaTime);

            }
            else
            {

                Destroy(MovePosition);
                currentState = BossMoves.Idle;
                ObjCounter -= 1;
              
            }

        }


    }




    IEnumerator BossWaiting()
    {
        //Boss waiting for another move
         yield return new WaitForSeconds(3);
              
      
    }
}

Firstly thanks for your comment and help

i did that your way but this time its not creating a game object after destroying the first one.

What do you need to achieve with Instantiate? At the moment, your code allows for multiple “MovePosition” game objects. Is that what you need to do?
DC

i am trying to make a dodgeable move attack like that picture. Its attacking to player’s position before the dodge
https://d1fs8ljxwyzba6.cloudfront.net/assets/editorial/2017/04/hollow-knight-how-to-beat-mantis-lords-2.jpg.jpg

I’m not 100% clear why you are using Instantiate. Is it just to store the player’s position at the point the “missile” is launched at them, so the “missile” moves towards that stored position, rather than the player’s current position?

Yes exactly i want to boss moves towards that stored position

OK - then the instantiate is a long-way round to do that.

You can simply define a Vector3 Variable such as “lastPosition” and then when the missile is launched, store the player’s position at that moment with;

lastPosition=Player.transform.position;

You would then move your missile towards that position with;

transform.position = Vector2.MoveTowards(transform.position, lastPosition, BossMoveSpeed * Time.deltaTime);

DC

1 Like

Thanks its solve the problem