A* Pathfinding Project

Run Away From Player AI System Issue


#1

hello.

i’ll say sorry for my English at first…

i’m trying to build a AI system where NPC will Run Away from the players if they are watching him,
let me explain it better…

NPC will try to eat Players if they are not watching him otherwise it will run away…right now i have something working but with some bug…
it will run away from player but like a circle around it…it is not so good to see, it would be great if i can choice from witch distance from the player it will run away otherwise it will just walk around.

anyone can help me to understand where i’m making a mistake?

 using UnityEngine;
 using System.Collections;
 using UnityEngine.AI;
 
 public class TunAway : MonoBehaviour {
 
     private Transform player;
     private UnityEngine.AI.NavMeshAgent myNMagent;
     private Transform startTransform;
 
     public float multiplyBy;
     public Vector3 resultedVector;

     private enum ERun
     {
         FORWARD,
         RIGHT,
         LEFT,
     }
     private ERun eRun = ERun.FORWARD;

     private void SwitchRun()
     {
         switch (eRun)
         {
            case ERun.FORWARD : 
                RunFromToForward();
                break;
            case ERun.LEFT      :  
                RunFromToLeft(); 
                break;
            case ERun.RIGHT     :
                RunFromToRight();
                break; 
         }
     }

 
 
     // Use this for initialization
     void Start () {
 
         player = GameObject.FindGameObjectWithTag ("Player").transform;
         myNMagent = this.GetComponent<UnityEngine.AI.NavMeshAgent> ();
 
         RunFromToForward ();
     }
     
     // Update is called once per frame
     void Update () {
 
         
         //if is not facing got to eat him
        if(!ISFacing())
        {
            GotToEat();      
        }
        else
        {
            UpdateRaycast();
            SwitchRun();
        }
     }
 
     public void RunFromToForward()
     {
         startTransform = transform;
         
         transform.rotation = Quaternion.LookRotation(transform.position - player.position);
 
         Vector3 runTo = transform.position + player.transform.TransformDirection(Vector3.forward) * multiplyBy;
         
         NavMeshHit hit;    

        // Debug.Log(RandomPoint(multiplyBy,out resultedVector));
    
        if(NavMesh.SamplePosition(runTo, out hit, 3000,1 << NavMesh.GetAreaFromName("Walkable")))
        {
            transform.position = startTransform.position;
            transform.rotation = startTransform.rotation;

            myNMagent.SetDestination(hit.position);
        }
     }
     public void RunFromToRight()
     {
         startTransform = transform;
         
         transform.rotation = Quaternion.LookRotation(transform.position - player.position);
 
         Vector3 runTo = transform.position + player.transform.TransformDirection(Vector3.right) * multiplyBy;
         
         NavMeshHit hit;    

        // Debug.Log(RandomPoint(multiplyBy,out resultedVector));
    
        if(NavMesh.SamplePosition(runTo, out hit, 300,1 << NavMesh.GetAreaFromName("Walkable")))
        {
            transform.position = startTransform.position;
            transform.rotation = startTransform.rotation;

            myNMagent.SetDestination(hit.position);
        }
     }
     public void RunFromToLeft()
     {
         startTransform = transform;
         
         transform.rotation = Quaternion.LookRotation(transform.position - player.position);
 
         Vector3 runTo = transform.position + player.transform.TransformDirection(Vector3.left) * multiplyBy;
         
         NavMeshHit hit;    

        // Debug.Log(RandomPoint(multiplyBy,out resultedVector));
    
        if(NavMesh.SamplePosition(runTo, out hit, 300,1 << NavMesh.GetAreaFromName("Walkable")))
        {
            transform.position = startTransform.position;
            transform.rotation = startTransform.rotation;

            myNMagent.SetDestination(hit.position);
        }
     }
     

     private void UpdateRaycast()
     {
         NavMeshHit hit;
         if(NavMesh.Raycast(transform.position,transform.TransformDirection(Vector3.forward),out hit,NavMesh.GetAreaFromName("Walkable")))
         {
             Debug.DrawLine(transform.position,transform.TransformDirection(Vector3.forward),Color.blue);
             eRun = ERun.FORWARD;
         }
         else if(NavMesh.Raycast(transform.position ,transform.TransformDirection(Vector3.right),out hit,NavMesh.GetAreaFromName("Walkable")))
         {
             Debug.DrawLine(transform.position,transform.TransformDirection(Vector3.right),Color.blue);
             eRun = ERun.RIGHT;
         }
         else
         {
             Debug.DrawLine(transform.position,transform.TransformDirection(Vector3.left),Color.blue);
             eRun = ERun.LEFT;             
         }
     }

     private void GotToEat()
     {
         transform.rotation = Quaternion.LookRotation(player.position - transform.position);
         myNMagent.SetDestination(player.transform.position);
     }
     private bool ISFacing()
     {
        float angle = 45;
        float angleToPlayer = Vector3.Angle(player.transform.forward,( transform.position - player.transform.position));

        // Debug.Log(angleToPlayer);
         if( angleToPlayer < angle)
         {
             return true;
         }
         else
         return false;
     }


#2

i did it…if someone are looking to do something similar this is what i did

using UnityEngine;
using UnityEngine.AI;

public class RunAway : MonoBehaviour
{
    [SerializeField]
    private NavMeshAgent _agent;

    public GameObject   player;
    private float EnemyDistanceRun = 20.0f;

    void Awake()
    {
        _agent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        UpdateNavimesh();
        
    }
    private float Distance(Transform in_player, Transform me)
    {
        Vector3 FixedPlayer = in_player.transform.position;
        FixedPlayer.y = 0;
        Vector3 FixedMe = me.position;
        FixedMe.y = 0;
        float distance = Vector3.Distance(FixedMe ,FixedPlayer);
        return distance;
    }
    private void RunAway()
    {
        Vector3 dirToPlayer = transform.position - player.transform.position;
        transform.rotation = Quaternion.LookRotation(dirToPlayer);

        Vector3 newPos = transform.position + dirToPlayer;

        _agent.SetDestination(newPos);        
    }

    private void UpdateNavimesh()
    {
        if(Distance(player.transform,this.transform) < EnemyDistanceRun)
        {
            if(!ISFacing())
            {
                GotToEat();
            }
            else
            {
                RunAway();
            }
        }
        else
        {
            _agent.SetDestination( RandomNavmeshLocation(5f));
        }
    }
     private void GotToEat()
     {
         transform.rotation = Quaternion.LookRotation(player.transform.position);
         _agent.SetDestination(player.transform.position);
     }
     private bool ISFacing()
     {
        float angle = 45;
        float angleToPlayer = Vector3.Angle(player.transform.forward,( transform.position - player.transform.position));

        // Debug.Log(angleToPlayer);
         if( angleToPlayer < angle)
         {
             return true;
         }
         else
         return false;
     }
    public Vector3 RandomNavmeshLocation(float radius) {
            Vector3 randomDirection = Random.insideUnitSphere * radius;
            randomDirection += transform.position;
            NavMeshHit hit;
            Vector3 finalPosition = Vector3.zero;
            if (NavMesh.SamplePosition(randomDirection, out hit, radius, 1)) {
                finalPosition = hit.position;            
            }
            return finalPosition;
        }
}

#3

Hey, sorry I’ve been meaning to reply to this thread before, but kept getting distracted.

Rather than taking a random point within the unitcircle, you could also make use of the ConstantPathType.
Similar to the wandering AI tutorial which can be found here: https://arongranberg.com/astar/docs/wander.html


#4

Thank’s you for your reply!

Actually it’s working well but with one issue… on runaway function, when it is running away from player it will freeze to the corner of map because there is not a way to run forward anymore… how i should fix it?
Any idea?


#5

@Sylon87 You can look at the tutorial that @ToastyStoemp linked to. In there you can find out how the RandomPath can be used which I think will work well for you.