2
\$\begingroup\$

I have a 2D game where the player can move up and down on the y axis, I need the enemy to rotate to look at my player (which I have working, but probably isn't the best method) while also moving up and down with the player.

I have both of those things working, but not fully, right now whenever I move up and down, the rotation happening seems to cause the enemy to move backwards more and more with each up and down movement.

I need it to remain stationary on the x and z axis's.

Also, if anyone knows how I could make it so the enemy always wants to be slightly above the player on the y axis, that'd be awesome. Meaning, instead of locking onto the player dead straight, maybe the enemy can be up slightly by perhaps 20%.

This is the code I'm working with:

public float moveSpeed = 3.0f;
public Transform target;

private Transform myTransform;

// Use this for initialization
void Start () {
  myTransform = transform;
}

// Update is called once per frame
void Update () {
  Quaternion rotation = Quaternion.LookRotation(
    target.transform.position - transform.position, 
    transform.TransformDirection(Vector3.up));
  transform.rotation = new Quaternion(0, 0, rotation.z, rotation.w);

  if (target.transform.position.y < myTransform.position.y)  {

    myTransform.position -= myTransform.up * moveSpeed * Time.deltaTime; 
  }
  else if (target.transform.position.y > myTransform.position.y) {

    myTransform.position += myTransform.up * moveSpeed * Time.deltaTime; 
  }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ You might want to add a video or a couple of images that illustrate your issue, and, if at all possible, images of what you expect. This would help us help you :) \$\endgroup\$ – Vaillancourt Jun 9 '15 at 11:26
2
\$\begingroup\$
float YOffset = 0f;

void Update() 
{
    myTransform.LookAt(target);
    float targetPosY = target.transform.position.y + YOffset;
    if(myTransform.position.y != targetPosY)
    {
        float MoveAmount = moveSpeed * Time.delta;
        if(Mathf.Abs(myTransform.position.y - targetPosY) < MoveAmount)
            myTransform.position = Vector3.up * MoveAmount;
        else
        {
            if (targetPosY < myTransform.position.y)  
            {
                myTransform.position -= Vector3.up * MoveAmount; 
            }
            else if (targetPosY > myTransform.position.y) 
            {
                myTransform.position += Vector3.up * MoveAmount; 
            }
        }
    }

}

1.) Consider using Transform.LookAt to simplify the rotation.

2.) In your movement code, myTransform.Up represents the Up vector of the transform in local spcae, so if your model is tipped off center then Up will no longer point Up in world space. Use Vector3.Up as MistaGiggles suggests.

3.) You can make your enemy hover above the player by adding an Offset amount for the Y axis like the sample code above.

Additional way to rotate your enemy based on your comment:

1.) Get the normalized vector from enemy to player and assign it to Transform.Right, which would be your X axis. Unity takes care of updating the Transform's rotation internally when you set Up/Right/Forward manually.

    Vector2 lookDir = (target.transform.position - myTransform.position); 
    myTransform.right = lookDir; 
    if ((target.transform.position.y + YOffset) < myTransform.position.y) 
    {
        float MovementAmount = moveSpeed * Time.deltaTime;
        if((myTransform.position.y - MovementAmount) < (target.transform.position.y + YOffset))
        {
            myTransform.position = new Vector3(myTransform.position.x,target.transform.position.y + YOffset, myTransform.position.z);
        }
        else  
            myTransform.position -= Vector3.up * moveSpeed * Time.deltaTime; 
    } 
    else if ((target.transform.position.y + YOffset) > myTransform.position.y) 
    { 
        float MovementAmount = moveSpeed * Time.deltaTime;
        if((myTransform.position.y + MovementAmount) > (target.transform.position.y + YOffset))
        {
            myTransform.position = new Vector3(myTransform.position.x,target.transform.position.y + YOffset, myTransform.position.z);
        }
        else
            myTransform.position += Vector3.up * moveSpeed * Time.deltaTime; 
    } 
\$\endgroup\$
  • \$\begingroup\$ Thank you very much Jeremiah, I really appreciate the help! - That code works quite well, thank you! - Only I'm not sure how to get it to face the direction of the character now, at the moment it turns itself to facing the camera (so it looks thin), I need it to face my character who is to the right of the enemy on the x axis. And the rotation needs to be on the z axis. Any ideas? \$\endgroup\$ – S_Byrnes Jun 9 '15 at 22:32
  • \$\begingroup\$ Also, I'm sorry for how disgusting the above comment is, apparently if you press enter to make a new paragraph, it just sends the comment. \$\endgroup\$ – S_Byrnes Jun 9 '15 at 22:36
  • \$\begingroup\$ Thanks for the edit Jeremiah, where would I place this code in your script you posted the first time? \$\endgroup\$ – S_Byrnes Jun 10 '15 at 0:50
  • \$\begingroup\$ Never mind, I worked it out actually, thanks! - Do you perhaps know how I can stop the enemy from jittering up and down when the player is just falling from gravity (no keys pressed). I think it's due to the enemy trying to rotate towards the player, but since the player is already level with the enemy, it won't let him. \$\endgroup\$ – S_Byrnes Jun 10 '15 at 2:03
  • \$\begingroup\$ Also, I've just spotted another issue. Right now my enemy is getting "squashed" slightly, he's being rotated on more than just the z axis, his y and x axis' both keep changing and I need to try to 'lock' them, so they don't get affected. \$\endgroup\$ – S_Byrnes Jun 10 '15 at 2:35
0
\$\begingroup\$

First of all, why have a private member "myTransform" and then mix usage of "transform" and "myTransform"? It is more readable to just use "transform".

I have a feeling that the problem arises from using "myTransform.up" vs "Vector3.up" combined with your rotation code. I think the combination of the quaternion calculations and the local up vector is resulting in an accumulated offset in the axis you want to remain unchanged.

Have a look at this for calculating the rotation (you may need to offset the result).

Alternatively make use of Euler angles, as you are only working with one axis of rotation (where you have no benefit of using quaternions over euler angles).

As for moving backwards, if you are working in the global y-axis, use "Vector3.up" (which is global up) vs "myTransform.up" which is the up direction of your object after rotation is taken into account (and so will change direction depending on where it is looking).

\$\endgroup\$
  • \$\begingroup\$ Thanks for the help MistaGiggles, I'm looking into vector3.up now for future use, I wasn't aware that both were viable for this purpose and that one is better than the other. \$\endgroup\$ – S_Byrnes Jun 9 '15 at 22:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.