Character Controller keeps going even if I limit it

I’m working on simple enemy AI, and now I’m forced to use Character Controller Component because terrain is not flat so It will prevent enemy from doing stutter movement.

Now problem is even when I limit it, so when enemy movement is on desired distance from player, it should stop, but character controller forces its way through player. Only way to really stop it is to limit calling that function, which is not what I want.

Code:

using UnityEngine;

public class Enemy : Entity {

	[SerializeField]
	private Transform target;

	public float moveSpeed;

	public float rotationSpeed;

	public float combatRadius = 10.0f;
	public float minDistance = 5.0f;

	private float distance;

	public bool isOnMinDistance;
	public bool seePlayer;

	private Transform myTransform;

	private CharacterController controller;

	private void Start () {

		GameObject target = GameObject.FindGameObjectWithTag ("Player");
		this.target = target.transform;

		myTransform = transform;

		controller = GetComponent<CharacterController> ();
	}

	private void Update () {

		if (reaction == Reaction.Hostile) {
			ChasePlayer ();
		}
	}

	private void ChasePlayer () {

		distance = Vector3.Distance (target.position, myTransform.position);

		if (distance <= minDistance) { //attack
			isOnMinDistance = true;
			seePlayer = true;
		}

		else if (distance >= minDistance && distance <= combatRadius) {

			Debug.DrawLine (new Vector3 (target.position.x, target.position.y + 1f, target.position.z), myTransform.position, Color.red);

			LookAtTargetYAxis ();

			FollowTarget ();
	
			isOnMinDistance = false;
			seePlayer = true;
		}

		else {
			isOnMinDistance = false;
			seePlayer = false;
		}
	}

	private void FollowTarget () {
		Vector3 forward = transform.TransformDirection(Vector3.forward * moveSpeed * Time.deltaTime);

		controller.SimpleMove (forward);
	}

	private void LookAtTargetYAxis () {
		
		transform.LookAt (target);

		Vector3 angles = myTransform.rotation.eulerAngles;
		angles.x = 0;
		angles.z = 0;

		transform.rotation = Quaternion.Euler(angles);
	}

	private void OnDrawGizmosSelected () {
		Gizmos.DrawWireSphere (transform.position, combatRadius);
		Gizmos.color = Color.red;
	}
}

I would appreciate if someone could help me. :slight_smile:

If they are within the min distance have a boolean change to true and use that to reduce the velocity.

I’m assuming here that the script is attached to each enemy and they have a RigidBody (2D or 3D don’t really matter you just have to change the Vector type)

in your update wrap the enemy speed you are using to move to the player with this if:

if(!isOnMinDistance && seePlayer){
//move full speed ahead
}

Add this else after that:

    else if(isOnMinDistance){ //target is in striking range
    GetComponent<RigidBody>().velocity = .8f * GetComponent<RigidBody>().velocity;
    //This line takes the velocity on the rigid body and reduces it by 80% each frame, giving a smooth playback.
    //do strike logic
    }

The only thing left is to flip the boolean based on if the enemy is in range
where the check is for the distance

It looks like you just have a speed variable running the show here, so you can use the same strategy here, Just take the speed and set it to max if they are outside of min distance, and if they are in min distance, reduce it by a percent. Since it runs every frame you want to use a higher number for a smoother stop.

if(isOnMinDistance)
{
       speed = speed * .8;
}
else
{
 if(speed < maxSpeed)
       speed = speed * acceleration;
else
      speed = maxSpeed;

}