Making an ai maintain a set range

Hi,

I am trying to make an ai which will try to maintain a set range (from min range to max range) from the player.

The code I am using is as follows:

using UnityEngine;
using System.Collections;

public class ArtilleryMovement : MonoBehaviour
{

    Transform player;
    NavMeshAgent nav;
    public float activeDist;
    public float minDist;
    public float maxDist;
    public float speed;
    public float acceleration;
    public float targetDist;
    int enemyMask;



    void Awake()
    {
        enemyMask = LayerMask.GetMask("Enemy");
        player = GameObject.FindGameObjectWithTag("Player").transform;
        nav = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        float dist = Vector3.Distance(transform.position, player.position);
        nav.speed = speed;
        nav.acceleration = acceleration;

        if (dist <= activeDist)
        {
            if (dist <= maxDist && dist >= minDist)
            {
                nav.Stop();
            }

            else if (dist > maxDist)
            {
                nav.SetDestination(player.position);
                nav.Resume();
            }

            else if (dist < minDist)
            {
                Vector3 playerDir = Vector3.Normalize(player.position - transform.position);
                Vector3 targetDir = -playerDir;
                playerDir.y = 0;
                bool newTargetSet = false;
                int i = 0;

                while (newTargetSet == false)
                {
                    print(i);

                    if (i == 9)
                    {
                        nav.SetDestination(targetDir * targetDist);
                        newTargetSet = true;
                        nav.Resume();
                    }
                    else if (Physics.Raycast(transform.position, Quaternion.Euler(0, 0, (10 * i)) * (targetDir * targetDist)) == false)
                    {

                        nav.SetDestination((Quaternion.Euler(0, 0, (10 * i)) * (targetDir * targetDist)));
                        newTargetSet = true;
                        nav.Resume();
                    }

                    else if (Physics.Raycast(transform.position, Quaternion.Euler(0, 0, (-10 * i)) * (targetDir * targetDist)) == false)
                    {
                        nav.SetDestination((Quaternion.Euler(0, 0, (-10 * i)) * (targetDir * targetDist)));
                        newTargetSet = true;
                        nav.Resume();
                    }

                    i++;
                }
            }
        }
    }
}

So the idea is that if the player gets within the minimum range, the ai will attempt to move away in a vector opposite to that the player is in (by getting the negative of the normalized vector to the player). There is a while loop to test if this vector is available, and if not, it is supposed to begin rotating that vector by increments of 10 / -10 degrees, until it finds an unblocked path.

The ai does sort of avoid the player as desired, but the while loop which is supposed to scan for available exit routes does not seem to be working; it never seems to get past the first condition (so I don’t know if there is something wrong with the raycast test?), and the ai will often go past the player in order to get to the minimum distance, even though other paths away from the player are open.

I am still pretty new to both Unity and using vectors to plot movement, so I think I must be misunderstanding something with the vectors (or maybe the raycast), but I can’t figure out what it is.

Any help would be appreciated!

Ok, I had a mistake in the way I was getting my vector between the player and the ai. Also, for some reason by telling the RayCast to ignore the enemyMask layer (of which my ai is a member), it wasn’t detecting other colliders - I don’t understand why that would be so, but removing that filter has allowed the RayCast to correctly detect my obstacles (which are box colliders), whereas before it couldn’t. Finally, I needed to put a limit into my while loop, to ensure that the loop didn’t indefinitely.

Making those changes, the code seems to be working pretty well now.

Hi,

I know you’ve already solved you problem. But I would like to suggest to use Behaviour Tree to make your AI. It would be more easier to manage your code using such tool.

I’m the author of Panda BT (http://www.pandabehaviour.com), which is a script-based Behaviour Tree engine.

This online demo shows an AI for the game tag (the child game). When the player “is it”, the AIs will try to run away from the player to keep the distance .

You are welcome on this thread if you have any question about using this tool.