Getting the player to retreat a certain distance from the player

Hi all,

This problem has been plaguing me for about 2 weeks now and I cant seem to crack it.

I have a simple state machine for the enemy. The enemy chases the player until the player reaches a light source. Once the player reaches a light source, the enemy retreats. This all works except i want the enemy to stop retreating a certain distance from the player.

At the moment, the enemy is retreating indefinitely until the player leaves the light in which the enemy once again, gives chase.

As you can see in the Retreat function below, I have tried a few methods but none seem to do exactly what I want.

Pastie here or code below: http://pastie.org/private/tjfb3r1xzemmm05dele0wa

Thanks for the help in advance, I really appreciate it.

using UnityEngine;
using System.Collections;

public class DarkChase : MonoBehaviour {

public float maxAdvanceSpeedY = 1.0f;
public float maxAdvanceSpeedX = 1.0f;
public float maxRetreatSpeedY = 1.0f;
public float maxRetreatSpeedX = 1.0f;
public float minDistance = 5.0f;
//public float maxRetreatDistance = 100.0f;
//public float maxDistance = -10.0f;

public GameObject Player;
public GameObject theDark;
public PlayerControl thePlayerScript;
//public Transform Target;

// Use this for initialization
void Start () {

	Player = GameObject.FindGameObjectWithTag("Player");
	thePlayerScript = thePlayerScript.GetComponent<PlayerControl>();

}

// Update is called once per frame
void Update () {

	if (PlayerControl.inLight == false) 
		Advance();
	else if (PlayerControl.inLight == true)
		Retreat();

}

public void Advance () {

	print ("Advance");

	Vector3 playerPosition = Player.transform.position;
	Vector3 darkPosition = transform.position;

	Vector3 difference = darkPosition - playerPosition;
	difference.Normalize();

	transform.Translate (
		(difference.x * -maxAdvanceSpeedX), (difference.y * -maxAdvanceSpeedY), (difference.z * -1));

}

public void Retreat () {

	print ("Retreat"); 

	Vector3 playerPosition = Player.transform.position;
	Vector3 darkPosition = transform.position;
	
	Vector3 difference = darkPosition + playerPosition;
	difference.Normalize();
	
	transform.Translate (
		(difference.x * +maxRetreatSpeedX), (difference.y * +maxRetreatSpeedY), (difference.z * +1));
		
	float dist = Vector3.Distance(playerPosition, darkPosition);
	if (Vector3.Distance (playerPosition, darkPosition) <= minDistance)
		Debug.DrawLine (playerPosition, darkPosition, Color.yellow);
		print ("Distance to player: " + dist);

	//darkPosition = Vector2.MoveTowards (transform.position, playerPosition, maxAdvanceSpeedX * Time.deltaTime);

	//transform.Translate (
			//(maxDistance), (0), (0));

	
	//Vector3 maxDistance = Vector3.Distance (playerPosition, darkPosition);
		//if (maxDistance >= maxRetreatDistance)
			//.Translate (
				//(difference.x - maxRetreatDistance), (difference.y - 0.01), (difference.z - 0.01));
}

}

I would add a third “state” idle. You might even choose to make an Enum for the states. But, to fix this, go into update and change the retreat conditions.

 void Update () {
 
     if (PlayerControl.inLight == false && (Vector3.Distance(playerPos,transform.pos)> minDistance)) {
			Advance();
		 }
     else if (PlayerControl.inLight == true){
		if(Vector3.Distance(playerPos,transform.pos) < maxRetreatDistance){
			Retreat();
		}

	}else{
	     Idle();
	     //Idle = Rotate toward character and don't move? Or whatever you want.
	}

 }

if your saying you dont like it running endless checks in that you can actually use trigger boxes around lights and OnTriggerEnter push bots back, OnTriggerExit send in the hordes.

The thing is if you do this you can actually sleep the monster and then use OnTriggerExit to wake it.

Up to you though.

if your saying the issue is as far as “get him to a point and then just stop the translate”

if your saying you dont know how to because it doesn’t ever quite arrive. mathf.approximately is your friend. instead of saying if position == X do if mathf.approximately(X)

Approx allows you to be slightly innacurate to account for the fact that vector3 is a floating point, suffers floating point inaccuracies and so it lets you say if your really close thats good engouh.

alternatly just pick a point and go if (vector3.distance(monster.position, point)) < .1f
i’m within a tenth of a meter to my idle area, thats fine, lets start idling.

if your saying you dont know how to pick a point.

cast a ray from monster to player and or light source.

rays actually have a method called ray.getpoint(float distance)

thats gets you the world point X distance along the line.

So casting a ray from monster to player and ray.getpoint(10);
would get you the point in the world 10 meters from the monster in the direction of the player.

so say if you set origin to player, direction as player.position - light.position so you have a line starting at the player but traveling in the OPPOSITE direction of the light. and use getpoint(10).

you’ll now have the point closest to the light within 10 feet of the player kind of thing.