A* Pathfinding Project

Make seekers retreat when too close to target


#1

Hey there,

I am making a 2D top-down game.
I was able to get the enemies to follow the players correctly. But, I want them to retreat when they are too close to the player.

How can I accomplish this?


#2

A* just handles movement and path finding. Any decision making on what the destination should be has to be implemented by the end user. This either being a third party AI behavior addon or custom code.


#3

Any good third party AI you can recommend to me?
Thanks anyways :+1:


#4

I haven’t personally played around with any 3rd party behaviour editors, we build our own solution for our project.
Depending on your needs and skill level there is always something to fit your needs.

Behaviour Designer I think is one of the most popular ones.


#5

I decided to make something myself. But, I am not sure how to override the a* behaviour. Because a* is always telling the enemy to follow the player, but I don’t want that.

How can I do that?


#6

Hi

You might want to remove the AIDestinationSetter component and instead manually set the ai.destination property to wherever you want the agent to move.


#7

I suppose you’re using the DestinationSetter script?
Remove the scripts from your agents. And in your behaviour scripts you set the destination on the movement script.
https://arongranberg.com/astar/docs/aibase.html#destination


#8

I modified the AIDestinationSetter script to make the agent retreat when too close, However, it’s not working consistently.
Here’s the code:

public class AIDestinationSetter : VersionedMonoBehaviour {
		/// <summary>The object that the AI should move to</summary>
		public Transform target;
		[SerializeField] float retreatDistance;
		IAstarAI ai;

		void OnEnable () {
			ai = GetComponent<IAstarAI>();
			// Update the destination right before searching for a path as well.
			// This is enough in theory, but this script will also update the destination every
			// frame as the destination is used for debugging and may be used for other things by other
			// scripts as well. So it makes sense that it is up to date every frame.
			if (ai != null) ai.onSearchPath += Update;
		}

		void OnDisable () {
			if (ai != null) ai.onSearchPath -= Update;
		}

		/// <summary>Updates the AI's destination every frame</summary>
		void Update () {
			if (target != null && ai != null)
			{
				if (Vector2.Distance(transform.position, target.position) > retreatDistance)
            	{
                	ai.destination = target.position;
					
            	}
				else
				{
					Vector3 dirToPlayer = (target.transform.position - transform.position).normalized;
					ai.destination = Quaternion.Euler(0, 0, 180) * dirToPlayer;
				}
			} 
		}

		public void ChangeTarget(Transform newTarget){
			if (newTarget != target) target = newTarget;
			Debug.Log(target);
		}
	}```

#9

Hey,

Here is an updated destination position code

Vector3 dirToPlayer = (target.transform.position - transform.position).normalized;
ai.destination = target.transform.position + dirToPlayer * retreatDistance;

#10

Thanks for the help, it actually worked better like this
ai.destination = dirToPlayer * retreatDistance;


#11

But that would make the destination centered around the world center ( 0,0 ).
So it might not always go in the correct direction.

Alternatively on the second line you could swap retreatDistance for another variable, so you can control them individually.