Two pieces of code making enemy follow player with two completely different results

Background Information:

  • I’m currently working on the Junior Programmer pathway on Unity Learn.
  • I am doing “Lab 4 - Basic Gameplay”.
  • I am on “1. Give objects basic movement”.

Project Context:

  • I have a Player object and an Enemy object in my hierarchy.
  • My Enemy object has an Enemy script.
  • I am trying to get my Enemy to face the player while chasing them.

My Enemy.cs script is below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
using UnityEngine.EventSystems;

public class Enemy : MonoBehaviour
{
    public float speed = 10.0f;
    private GameObject player;

    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.Find("Player");
    }

    // Update is called once per frame
    void Update()
    {
        //Working code from Challenge 4 - Bonus Features 4, step-by-step solution walkthrough,
        //Medium - Homing Rockets, step 6
        Vector3 moveDirection = (player.transform.position - transform.position).normalized;
        transform.position += moveDirection * speed * Time.deltaTime; 
        transform.LookAt(player.transform.position);


        //Vector3 lookDirection = (player.transform.position - transform.position).normalized;
        //transform.Translate(lookDirection * Time.deltaTime * speed);
        //transform.LookAt(player.transform.position);
    }
}

Question:
Why do the first 3 lines of code in “void Update()” have the enemy properly face and chase the player and the second 3 lines of code (the commented code) have the enemy immediately move in the opposite direction of the player as soon I hit play? And its only when my player moves does the enemy gradually circle around to my player?

2 of the 3 lines of code are exactly the same. And the line of code that is different has the same purpose (changing the position of the enemy to head towards the player’s position).

So I’m guessing there is some sort of difference between transform.Translate and adding to transform.position.

1 Answer

1

The code you have commented out isn’t correct for using the local-space Translate method.

  1. You want to perform the LookAt before Translate. This ensures the enemy’s forward (local blue axis) is pointing towards the player.
  2. When doing the Translate, you translate the enemy in the direction it’s facing (Vector3.forward) in local space (default).
transform.LookAt(player.transform.position);	
transform.Translate(Vector3.forward * Time.deltaTime * speed);

or, you need to specify the enemy should translate in world space, not local space

Vector3 lookDirection = (player.transform.position - transform.position).normalized;
transform.Translate(lookDirection * Time.deltaTime * speed, Space.World);
transform.LookAt(player.transform.position);	

Thanks for the answer. For your first solution (which I can't believe I didn't think of), is the lookDirection not necessary to include since it isn't used? For your second solution, why does adding "Space.World" to transform.Translate make everything work correctly? I don't understand why the enemy translating in world space compared to local space suddenly fixes everything. Isn't local space only relevant when an object is in a parent-child relationship with another object? (My Player and Enemy don't have a parent-child relationship in the hierarchy.)

You're right, the lookDirection isn't even needed for the option #1. For option #2, the lookDirection has been calculated in world space (via using transform.position, which is the world position). You are translating the enemy in world space using a world direction. If you wanted to Translate in local space, you would need to convert the lookDirection to local space: Translate(transform.InverseTransformDirection(lookDirection),...)

Ok, thank you for the explanation. I appreciate your help.