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

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

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

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

Q&A

解決済

1回答

1914閲覧

Unityエディタのゲーム画面で、マウスの移動量とスクリーンのサイズの関係が合わない。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

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

0グッド

0クリップ

投稿2018/11/03 18:27

編集2018/11/04 12:11

前提・実現したいこと

こちらのサイトこちらのサイトを参考に、
Unityエディタのゲーム画面で端から端までのマウス移動で90度回転するように実装したつもりですが、
実際にゲームを実行してみると、かなり少ないマウス移動で何回転もしてしまいます。
該当のソースにおいて、何がおかしいのでしょうか?
ご教示お願い致します。

該当のソースコード

C#

1 Vector2 beganPos; 2 float mouseDeltaPositionX, mouseDeltaPositionY; 3 float xAngle, yAngle, zAngle = 0; 4 5 void Update() 6 { 7 if (Input.GetMouseButtonDown(0)) 8 { 9 beganPos = Input.mousePosition; 10 } 11 else if (Input.GetMouseButton(0)) 12 { 13 14 mouseDeltaPositionX = (Input.mousePosition.x - beganPos.x)/Screen.width; 15 mouseDeltaPositionY = (Input.mousePosition.y - beganPos.y)/Screen.height; 16 17 float xAngle = mouseDeltaPositionY*90; 18 float yAngle = -mouseDeltaPositionX*90; 19 20 //回転 21 this.transform.Rotate(xAngle, yAngle, zAngle, Space.World); 22 } 23 }

追記。

タッチの場合は、なぜRotateで実装できたのでしょうか?
可能ならば、なるべくこれに近いコード(Rotateを使ったコード)で、エディタの方も実装したいです。

int touchCount = Input.touches.Count(t => t.phase != TouchPhase.Ended && t.phase != TouchPhase.Canceled); if (touchCount == 1) { Touch t = Input.touches.First(); switch (t.phase) { case TouchPhase.Moved: xAngle = (t.deltaPosition.y/Screen.height)*90; yAngle = -(t.deltaPosition.x/Screen.width)*90; break; } this.transform.Rotate(xAngle, yAngle, zAngle, Space.World); }

MEMO

タッチのdeltaPositionを、マウスで表現すると下記のようなmouseDeltaPositionになる。

C#

1 void Update() 2 { 3 if (Input.GetMouseButtonDown(0)) 4 { 5 prevPos = Input.mousePosition; 6 } 7 else if (Input.GetMouseButton(0)) 8 { 9 mouseDeltaPosition = Input.mousePosition - prevPos; 10 11 //ポインタ位置差分を求めた後で、現在のポインタ位置をprevPosに代入し、次回のUpdate実行に備える。 12 //この「現在のポインタ位置」が、次フレームでは「前フレームのポインタ位置」となる。 13 prevPos = Input.mousePosition; 14 15 (省略)

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

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

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

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

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

guest

回答1

0

ベストアンサー

Rotateは、現在のtransformの回転状態に対してさらに回転を加えるような動作をしますので、例えば下記のような状況になってしまうでしょう。

  • 画面上端中央でマウスボタンを押し下げる。
  • そのまま真下にドラッグし、画面中央でポインタを止める。ボタンは押しっぱなしにしておく。
  • このとき、mouseDeltaPositionY-0.5を示し、xAngle-45.0を示す。

つまり、毎フレームthis.transform.Rotate(-45, 0, 0, Space.World);が実行される。
マウスポインタを画面中央から動かさなくてもxAngle-45.0を示し続けるので、オブジェクトは-45°/フレームの速度で回り続ける。

対処方法の一例として、マウスボタンを押し下げたときに、初期マウス座標に加えてオブジェクトの初期回転を覚えておくというのはどうでしょうか。そして、オブジェクトにセットする新しい回転は「初期回転に対して(xAngle, yAngle, zAngle)回転したもの」としてみます。

C#

1 Vector2 beganPos; 2 Quaternion beganRot; // オブジェクトの初期姿勢を覚えておくフィールドを追加 3 float mouseDeltaPositionX, mouseDeltaPositionY; 4 float xAngle, yAngle, zAngle = 0; 5 6 void Update() 7 { 8 if (Input.GetMouseButtonDown(0)) 9 { 10 beganPos = Input.mousePosition; 11 beganRot = this.transform.rotation; // ボタン押し下げ時の回転を初期姿勢として保存しておく 12 } 13 else if (Input.GetMouseButton(0)) 14 { 15 mouseDeltaPositionX = (Input.mousePosition.x - beganPos.x) / Screen.width; 16 mouseDeltaPositionY = (Input.mousePosition.y - beganPos.y) / Screen.height; 17 18 float xAngle = mouseDeltaPositionY * 90; 19 float yAngle = -mouseDeltaPositionX * 90; 20 21 //回転 22 // Rotateだと基準姿勢が現在の姿勢となってしまう...そこで回転方法を変える 23 // 基準となる姿勢は初期姿勢として、そこからさらに(xAngle, yAngle, zAngle)回転し現在姿勢とする 24 this.transform.rotation = Quaternion.Euler(xAngle, yAngle, zAngle) * beganRot; 25 } 26 }

#追記

タッチ用コードではdeltaPositionを使っているのがポイントですね。
上で申しあげたように、Rotateは現在の姿勢を基準に回転を追加する動作となります。deltaPositionは「前フレームの指の位置からの差分」(「タッチを開始した位置からの差分」ではない点にご注意ください)を示しており、これをもとに求めた角度を使ってRotateで回しているのでうまくいっていると考えられます。
最初に挙げた例と同様に考えると...

  • 画面上端中央にタッチする。
  • そのまま真下にすばやくスワイプし(1フレームで一気に動かしたものとご想像ください)、画面中央で指を止める。

deltaPositionには指の移動量が入っている。画面高さの半分の距離を移動したので、求めたmouseDeltaPositionY-0.5xAngle-45.0となる。
this.transform.Rotate(-45, 0, 0, Space.World);が実行され、45°回転する。

  • このまま画面中央から指を動かさなかった場合、次のフレームのdeltaPositionは移動なしのためゼロベクトルを示す。

求められる回転角も0°なので、そのまま指を動かさず触れ続けていても、先の例のように回転し続けてしまうことはない。

マウス版コードの書き換え案ですが、こちらもタッチ版と同じように、角度算出の基となるポインタ座標差分を「ドラッグ開始時の位置からの差分」ではなく「前フレームの位置からの差分」に変更すればRotateを使用できるはずです。
下記のような形ではいかがでしょうか?

C#

1 Vector2 prevPos; // 覚えておく座標を「マウスボタン押し下げ時の座標」から「前回の座標」に変更...フィールド名を使用目的に沿った名前に変えた 2 float mouseDeltaPositionX, mouseDeltaPositionY; 3 float xAngle, yAngle, zAngle = 0; 4 5 void Update() 6 { 7 if (Input.GetMouseButtonDown(0)) 8 { 9 // フィールド名が「prevPos」に変わっただけで、ボタン押し下げ時に最初の座標を覚えておくのは変わらない 10 prevPos = Input.mousePosition; 11 } 12 else if (Input.GetMouseButton(0)) 13 { 14 // ここも同じく名前が「prevPos」に変わっただけだが、意味合いとしては「前フレームとのポインタ位置差分を求める」となる 15 mouseDeltaPositionX = (Input.mousePosition.x - prevPos.x) / Screen.width; 16 mouseDeltaPositionY = (Input.mousePosition.y - prevPos.y) / Screen.height; 17 18 // ポインタ位置差分を求めた後で、現在のポインタ位置をprevPosに代入し、次回のUpdate実行に備える 19 // この「現在のポインタ位置」が、次フレームでは「前フレームのポインタ位置」となる 20 prevPos = Input.mousePosition; 21 22 // 以降の処理は変更なし 23 24 float xAngle = mouseDeltaPositionY * 90; 25 float yAngle = -mouseDeltaPositionX * 90; 26 27 //回転 28 this.transform.Rotate(xAngle, yAngle, zAngle, Space.World); 29 } 30 }

投稿2018/11/03 20:43

編集2018/11/04 09:16
Bongo

総合スコア10807

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

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

退会済みユーザー

退会済みユーザー

2018/11/04 08:14

ご回答ありがとうございます。 ご提示の方法でできました。 追記したのですが、タッチの方はRotateのコードで、端から端のスワイプで90度回転してるように見えたのですが、これは何故でしょうか?(標準サイズのスマホしか持っていないので、それでしかテストできてませんが。) Unityエディタの方でも、タッチに近いコード(Rotateを使ったコード)で、実装するのは、どうしても無理ですか?
Bongo

2018/11/04 09:17

Rotateを使うことも可能かと思います。書き換え案を検討してみました。
退会済みユーザー

退会済みユーザー

2018/11/04 12:09

ご回答ありがとうございます。 タッチのdeltaPositionは、「タッチを開始した位置からの差分」ではなく、「前フレームの指の位置からの差分」だったのですね。 勘違いしていました。 ご回答いただけた方法で実装できました。 ありがとうございます。 メモとして追記したのですが、 タッチのdeltaPositionを、マウスのmouseDeltaPositionで表すコードを書いてみましたが、合っているかご確認いただけませんか?
Bongo

2018/11/04 12:35

はい、ご提示のコードで問題ないかと思います。 今回のような、前回の値を覚えておいて差分をとって1フレームの変化量を調べるという手は、座標に限らず色々な場面で使い道がありそうです。
退会済みユーザー

退会済みユーザー

2018/11/04 12:47

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問