質問: ### 前提・実現したいこと LookAt関数について、リファレンスやその他のサイトを見ても分からなかったので、ご教示お願い致します。 質問1。 ``` 対象の Transform を設定し、その方向へと向かせます ``` とありますが、「その方向を向かせる」とは、そのゲームオブジェクトのローカル軸のZ軸を、 targetの方向へ向かせるということで合っていますか? Unityでは、「ゲームオブジェクトの正面方向は、ゲームオブジェクトのローカル軸のZ軸の向き」という認識で合っていますか? 質問2。 第2引数の「上方ベクトルを指定」の意味が分からないです。 まず、質問1と似たような認識の確認になりますが、 「ゲームオブジェクトの上方向は、ゲームオブジェクトのローカル軸のY軸の向き」で合っていますか? このゲームオブジェクトのローカル軸のY軸の向きを、第2引数の上方ベクトルの向きに合わせるものと解釈しようとしましたが、 そうではなさそうでした。 ### 試したこと ゲーム実行前。 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/17fef5a76b429239dd64a37627797d38.png) ユニティちゃんにアタッチしたスクリプトで、球の方向に向けるように設定しました。 ``` void Update () { this.transform.LookAt(sphere.transform); } ``` ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/9458f3ef699e7cc20676c85cf8d63965.png) 第2引数は省略したので、worldUp= Vector3.upに設定されているはずですが、 自分が想定して意図したかったことは、ユニティちゃんのY軸がワールド座標のY軸(worldUp= Vector3.up)と同じ向きになりつつ、 球方向に向くという挙動にしたかったのですが、 そうはなりませんでした。 このような結果になり、worldUp= Vector3.upがどういう風に効いているかわかりません。 また、LookAt関数では、ゲームオブジェクトのローカル軸のY軸を、第2引数に指定した方向に設定して、Z軸の向きを変えるというような処理はできないのでしょうか? イメージ的には、下記です。 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/eecf6a32f372ad7eca79e163eaeb1f52.png)
回答: LookAtのworldUpに関して、マニュアルの説明を引用します。 > > Then it rotates the transform to point its up direction vector in the direction hinted at by the worldUp vector. If you leave out the worldUp parameter, the function will use the world y axis. **worldUp is only a hint vector.** The up vector of the rotation will only match the worldUp vector if the forward direction is perpendicular to worldUp. > > > 質問者さんの言うとおり、LookAtメソッドはtargetへのベクトルをローカルのZ軸に、上方ベクトルをローカルのY軸になるよう設定します。 ここで注意が必要です。Z軸とY軸であれば、両者の為す角度は垂直でなければなりません。 ですので、worldUpベクトルは、targetへのベクトルと垂直に交わるベクトルを指定しなければなりません。 ...と言われたら、どうしますか? 面倒くさいですよね。(まぁ、実際は外積を2回求めるだけなんですが) ですので、「worldUp is only a hint vector」なんです。 LookAtメソッドでは、**worldUpをヒントに、上方ベクトルがtargetへのベクトル、workdUpベクトルと同じ平面上になるように設定します。** まぁ、横に傾げる事がなければ、Vector3.upを指定しておけば間違いないというのは、他の回答者さんの言うとおりです。 > > すみません、「targetへのベクトル、worldUpベクトルと同じ平面」がわからなかったです。 > > > そこを突っ込みますか。まぁ、自分でも説明が下手だなぁと思っていたところなんですがw とりあえず指向を変え、ヒントとなるworldUpからどのようにローカルのY軸を決定できるか、説明しましょうか。私の回答の「外積を2回求めるだけ」という部分についてです。 まず前提として、Z軸/Y軸/X軸というのは、お互い直角に交わっていなければなりません。(わかっていることとは思いますが、今回の肝ですので、確認しておきます。) 外積について、ご存知かもしれませんが説明します。 2つのベクトルの外積で何が求められるか。それは、お互いが共に垂直に交わるベクトルが求まります。 さて、targetへのベクトル=ローカルのZ軸と、ローカルのY軸...のヒントとなるworldUpの2つのベクトルの外積を求めると何が求まるか。 ローカルのZ軸とローカルのY軸(のヒント)が垂直に交わるベクトル、ですから、**ローカルのX軸**になるわけです。 更に、ローカルのZ軸と、今求めたローカルのX軸の外積を求めると、何が求まるか。 ローカルのZ軸とローカルのX軸が垂直に交わるベクトル、ですから、これが**本当のローカルのY軸**になります。 このように、targetへのベクトルとY軸のヒントとなるベクトルの2つで、ローカルのY軸(と、ついでにローカルのX軸も)求めることができるのです。 * TransformのLookAtをUnity APIを使わずに書く 上記のページの、 ``` Vector3 z = (target - transform.position).normalized; Vector3 x = Vector3.Cross(Vector3.up, z).normalized; Vector3 y = Vector3.Cross(z, x).normalized; ``` が、私がいま説明した内容ですね。(worldUpがVector3.up固定になっていますが) これらの内容は、カメラ行列を作るための常套手段なので、その辺りを勉強すると良いかもしれません。