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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

4回答

10364閲覧

LookAt関数について。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

1グッド

0クリップ

投稿2018/12/20 16:03

前提・実現したいこと

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

質問1。

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

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

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

試したこと

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

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

C#

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

イメージ説明

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

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

イメージ説明

Hawn👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

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

上記のページの、

cs

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

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

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

投稿2018/12/21 12:45

編集2018/12/22 07:44
katsuko

総合スコア3469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/21 17:45 編集

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

退会済みユーザー

2018/12/22 16:02 編集

ご回答ありがとうございます。 外積については分からなかったので、検索して、右ねじの方向ということで イメージが掴めました(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の向きに近づけたものになる。」 ということにはなりませんか?(結果的な状態としてです。)
katsuko

2018/12/23 18:58

その認識でいいです。
退会済みユーザー

退会済みユーザー

2018/12/25 13:32

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

0

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

投稿2018/12/21 09:49

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/21 17:45 編集

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

0

LookAtをしたあとに

C#

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

を実行すると出来ますよ

投稿2018/12/21 09:23

bochan2

総合スコア2050

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/21 16:10

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

0

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

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

C#

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

投稿2018/12/20 17:59

編集2018/12/20 18:13
negitama

総合スコア943

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/21 16:06 編集

ご回答ありがとうございます。 質問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); を試してみて、意図したい挙動になりました。ありがとうございます。意味的にもわかりやすいコードでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問