I have this script that points a missile's z+ axis at its target:

 public class Missile : MonoBehaviour
     Vector3 target;
     public Transform car;

     void Update()
         car = GameObject.FindGameObjectWithTag("Cube").transform;
         target = Vector3.Normalize(car.position - transform.position);
         Quaternion direction = Quaternion.LookRotation(target);
         transform.rotation = Quaternion.Slerp(transform.rotation, direction, 4*Time.deltaTime);
         transform.position = transform.position + 10* transform.up* Time.deltaTime;


But my missile model has its "front" pointing in the direction of the y+ axis, not z.

Missile model

How can I convert the LookRotation code above to rotate the y axis to my target, instead of the z? If possible, I'd love to see a diagram that explains how the conversion works.

I have referred to some previous answers about this topic, but still couldn't understand how to do it in this case.

  • 2
    \$\begingroup\$ Some coding tips: 1) you don't need to declare target as a member variable. You can just use it as a temporary inside Update and throw it out at the end of the function. 2) don't search for your target with GameObject.Find() every frame - this is slow. Do it only on start-up, or when the target changes (say the previous target got destroyed mid-flight and you need to pick a new one). 3) You're using a non-linear blend for your rotation, so the extra cost of Slerp over Lerp isn't doing anything useful for you here. 4) Give type names an initial uppercase letter. \$\endgroup\$
    – DMGregory
    Mar 13, 2022 at 15:01

2 Answers 2


Let's see if I can write a version of this answer so general-purpose that I never have to write another one. 😆

public static Quaternion OmniLookRotation(
             Vector3 exactAxis,       Vector3 exactTarget,
             Vector3 approximateAxis, Vector3 approximateTarget
) {
    // Compute a rotation that takes the z+ and y+ axes to our custom axes.
    var zyToCustom = Quaternion.LookRotation(exactAxis, approximateAxis);
    // Invert this, to map our custom axes to z+ and y+.
    var customToZY = Quaternion.Inverse(zyToCustom);

    // Compute a rotation that takes the z+ and y+ axes to our target directions.
    var zyToTarget = Quaternion.LookRotation(exactTarget, approximateTarget);
    // Chain these two rotations so that exactAxis maps to exactTarget,
    // and approximateAxis maps as closely as it can to approximateTarget.
    var customToTarget = zyToTarget * customToZY;

    return customToTarget;

So, let's say I want to point my local y+ axis (Vector3.up) exactly toward my target (let's call that toTarget to distinguish this offset from the target's absolute position), while pointing my local x+ axis (Vector3.right) as close as possible toward world "down" (Vector3.down). I'd write it like this:

var targetRotation = OmniLookRotation(
                       Vector3.up,    toTarget,    // "point my y+ at target"
                       Vector3.right, Vector3.down // "and my x+ down"

// This is already a non-linear, not correctly time-adjusted blend,
// so if we're being approximate anyway we may as well use Lerp
// and save the added cost of Slerp.
transform.rotation = Quaternion.Lerp(
  • \$\begingroup\$ Thanks for the great answer! I was rather curious about the answer too, but why did you use static? I haven't used this keyword a lot so I want to know what happens to the code without writing static \$\endgroup\$
    – Arian_ki
    Mar 13, 2022 at 15:04
  • \$\begingroup\$ You'll notice that nothing inside the body of that method depends on member variables. So, this does not need to be a member function of any particular object. You could throw it in a utilities class and call it from any object, much like Quaternion.LookRotation() itself. If you don't have the static keyword, then the compiler will insist that you have a reference to some object to call OmniLookRotation on, even though that's completely unnecessary to the math you want to do. So static frees us from that restriction. \$\endgroup\$
    – DMGregory
    Mar 13, 2022 at 15:06
  • \$\begingroup\$ I see, thanks for explanation👍 \$\endgroup\$
    – Arian_ki
    Mar 13, 2022 at 15:11
  • \$\begingroup\$ Let me take some time to digest this as Im bad at 3d imagination 😅 \$\endgroup\$
    – chuackt
    Mar 13, 2022 at 15:58

A quick and easy way to deal with a model not being lined up the way you want it is to make the game object with the model be a child of the game object that has the movement script. In this case, Change the local rotation of the child to orient the model's y axis along the parent object's z axis. That way, as your movement script points the parent object, the child will move with it. No fancy math needed.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .