# Lock enemy's y-axis when using Vector3.MoveTowards to follow the player

I am using the following code to make a zombie move towards me, but when playing the scene the zombie seems to be moving towards me, but also off the ground and not fixed on the y-axis

 public GameObject ThePlayer;
public float TargetDistance;
public float AllowedRange = 10;
public GameObject TheEnemy;
public float EnemySpeed;
public int AttackTrigger;
public RaycastHit Shot;

void Update()
{
transform.LookAt(ThePlayer.transform);
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
EnemySpeed = 0.01f;
if (AttackTrigger == 0)
{
//TheEnemy.GetComponent<Animation>().Play("Walking");
transform.position = Vector3.MoveTowards(transform.position, ThePlayer.transform.position, EnemySpeed);
}
}
else
{
EnemySpeed = 0;
//TheEnemy.GetComponent<Animation>().Play("Idle");
}
}

if (AttackTrigger == 1)
{
EnemySpeed = 0;
//TheEnemy.GetComponent<Animation>().Play("Attacking");
}
}

void OnTriggerEnter()
{
AttackTrigger = 1;
}

void OnTriggerExit()
{
AttackTrigger = 0;
}


What can i do to ensure that it is sticking to the y axis at all times

The reason this is happening is because Vector3.MoveTowards will move all axes toward the target.

You can specifically exclude changes to the Y axis by creating a new target Vector3 having the Y axis set to the value it should stay at.

transform.position = Vector3.MoveTowards(
transform.position,
new Vector3(
ThePlayer.transform.position.x,
transform.position.y,
ThePlayer.transform.position.z
),
EnemySpeed
);


The above code creates a new Vector3 target where the Y axis is the same as the current position instead of the target, preventing Vector3.MoveTowards from changing the Y axis at all.

• This works perfectly thank you! But when the zombie gets into close contact with me it seems to lean back and fall into the floor (weird), is it possible to state when it gets within a certain distance of me, stop moving towards me? Mar 6, 2019 at 16:24
• Sure, you can use Vector3.Distance(a, b) to check the distance between two objects. docs.unity3d.com/ScriptReference/Vector3.Distance.html Mar 6, 2019 at 16:27
• Is there any benefit to this approach over calculating the move-towards vector as normal and then just maintaining the current Y position during the assignment? i.e. Vector3 moveTowards = Vector3.MoveTowards(transform.position, ThePlater.transform.position, EnemySpeed); transform.position = new Vector3(moveTowards.x, transform.position.Y, moveTowards.z); Mar 6, 2019 at 23:41
• @Abion47 yes. Doing it as shown in EstelS's answer (if you apply appropriate frame time adjustment to the speed parameter not made explicit here), you can ensure that the speed of movement is exactly consistent no matter the origin/destination. If you compute the MoveTowards vector first, then override the y coordinate, you might shorten the total distance travelled - making the character move slower when seeking a target that's above/below them than when seeking directly sideways. In EstelS's answer, the shortening of the offset vector occurs before we enforce our consistent speed. Mar 13, 2019 at 0:25

You can break out the Vector3 target parameter of Vector3.MoveTowards to prevent movement on the y-axis. Simply set the y value of the target position to the same y value as the current position. For example:

Vector3 currentPosition = transform.position;
Vector3 targetPosition = new Vector3(ThePlayer.transform.position.x, transform.position.y, ThePlayer.transform.position.z);

transform.position = Vector3.MoveTowards(currentPosition, targetPosition, EnemySpeed);


The other answers are great. But if you have a RigidBody attached, you can freeze the y rotation via constraints. Then no code change would be necessary.

• Except that the current code is moving the object via transform.position, which completely bypasses the Rigidbody and ignores any locking on its axes. Mar 7, 2019 at 12:22
• @DMGregory indeed. Thank you. I'll delete this answer when I get to a computer
– Evorlor
Mar 7, 2019 at 14:08
• Instead of deleting it, you could show how to move the Rigidbody with velocity instead of transform.position so the locked axes are respected. Mar 7, 2019 at 20:02