質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.23%

LookAt関数について。

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 2,250

tkmnusr

score 302

前提・実現したいこと

LookAt関数について、リファレンスやその他のサイトを見ても分からなかったので、ご教示お願い致します。

質問1。

対象の Transform を設定し、その方向へと向かせます


とありますが、「その方向を向かせる」とは、そのゲームオブジェクトのローカル軸のZ軸を、
targetの方向へ向かせるということで合っていますか?
Unityでは、「ゲームオブジェクトの正面方向は、ゲームオブジェクトのローカル軸のZ軸の向き」という認識で合っていますか?

質問2。
第2引数の「上方ベクトルを指定」の意味が分からないです。
まず、質問1と似たような認識の確認になりますが、
「ゲームオブジェクトの上方向は、ゲームオブジェクトのローカル軸のY軸の向き」で合っていますか?
このゲームオブジェクトのローカル軸のY軸の向きを、第2引数の上方ベクトルの向きに合わせるものと解釈しようとしましたが、
そうではなさそうでした。

試したこと

ゲーム実行前。
イメージ説明

ユニティちゃんにアタッチしたスクリプトで、球の方向に向けるように設定しました。

    void Update () {
        this.transform.LookAt(sphere.transform);        
    }

イメージ説明

第2引数は省略したので、worldUp= Vector3.upに設定されているはずですが、
自分が想定して意図したかったことは、ユニティちゃんのY軸がワールド座標のY軸(worldUp= Vector3.up)と同じ向きになりつつ、
球方向に向くという挙動にしたかったのですが、
そうはなりませんでした。
このような結果になり、worldUp= Vector3.upがどういう風に効いているかわかりません。
また、LookAt関数では、ゲームオブジェクトのローカル軸のY軸を、第2引数に指定した方向に設定して、Z軸の向きを変えるというような処理はできないのでしょうか?

イメージ的には、下記です。

イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

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軸も)求めることができるのです。

上記のページの、

        Vector3 z = (target - transform.position).normalized;
        Vector3 x = Vector3.Cross(Vector3.up, z).normalized;
        Vector3 y = Vector3.Cross(z, x).normalized;

が、私がいま説明した内容ですね。(worldUpがVector3.up固定になっていますが)

これらの内容は、カメラ行列を作るための常套手段なので、その辺りを勉強すると良いかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/22 00:48 編集

    ご回答ありがとうございます。
    すみません、「targetへのベクトル、worldUpベクトルと同じ平面」がわからなかったです。
    他の回答者様の「Vector3.downを入れてみる」ことを試して考えたのですが、
    ゲームオブジェクトのローカルのZ軸がターゲットを向いた上で、ゲームオブジェクトのローカルのY軸の向きが、なるべく第2引数のworldUpの向きに近づける挙動になるという認識で合っていますか?

    キャンセル

  • 2018/12/23 00:56 編集

    ご回答ありがとうございます。
    外積については分からなかったので、検索して、右ねじの方向ということで
    イメージが掴めました(https://oguemon.com/study/linear-algebra/inner-and-cross-product/)
    ご提示のリンクの内容は難しくて理解できませんでしたが、
    ご回答者様のご説明の「外積を2回求めてローカルのY軸を割り出す方法」は、理解できました。
    外積2回のご説明、とてもわかりやすかったです、ありがとうございます。

    それを踏まえた上で、前回の私の質問なのですが、
    結果的には、
    「ゲームオブジェクトのローカルのX軸,Y軸,Z軸はお互い直角に交わっているのが前提条件として、
     LookAt関数で第2引数のworldUpを指定してtargetの方を向かせると、
     ゲームオブジェクトのローカルのZ軸がtargetを向いた状態で、
     ゲームオブジェクトのローカルのY軸の向きは、可能な限り第2引数のworldUpの向きに近づけたものになる。」
    ということにはなりませんか?(結果的な状態としてです。)

    キャンセル

  • 2018/12/24 03:58

    その認識でいいです。

    キャンセル

  • 2018/12/25 22:32

    ご回答ありがとうございます。
    とても勉強になりました。
    ありがとうございます。

    キャンセル

0

質問1はYESだと思います。
質問2は正確に説明できませんが、第2引数は Vector3.up が規定値のようなので、明示してもしなくても動作は変わらないのでしょう。

質問のイメージのとおり処理させるなら、以下のようにするのが一例かと思います。あらかじめ対象のY座標を自分とあわせてからLookAtすれば余計な傾きを除けます。

void Update () {
    // Y座標を自分と合わせる
    var target = new Vector3(sphere.transform.position.x, this.transform.position.y, sphere.transform.position.z);
    this.transform.LookAt(target);        
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/22 01:05 編集

    ご回答ありがとうございます。
    質問1に関して思い出したのですが、Transform.forwardがZ軸を指して、Transform.UpがY軸を指すので、英語の意味的にもそう言えましたね、ありがとうございます。

    Vector3 target = new Vector3(sphere.transform.position.x, this.transform.position.y, sphere.transform.position.z);
    this.transform.LookAt(target);
    を試してみて、意図したい挙動になりました。ありがとうございます。意味的にもわかりやすいコードでした。

    キャンセル

0

LookAtをしたあとに

transform.rotation=Quarternion.Euler(0,transform.rotation.eulerAngles.y,0);


を実行すると出来ますよ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/22 01:10

    ご回答ありがとうございます。
    Quarternion.EulerやeulerAngles.yを勉強したいと思います。

    キャンセル

0

worldUp= Vector3.up がどう効くのか、に関しては、
代わりにVector3.down を入れてみるとわかると思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/22 00:58 編集

    「Vector3.downを入れてみる」ことを試して考えたのですが、
    ゲームオブジェクトのローカルのZ軸がターゲットを向いた上で、ゲームオブジェクトのローカルのY軸の向きが、なるべく第2引数のworldUpの向きに近づける挙動になるという認識で合っていますか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる