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

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

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

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

解決済

1回答

2711閲覧

[Unity] 左右入力をする前に移動キーを押すと機体が回転してしまう

l-_-l

総合スコア47

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

0クリップ

投稿2020/03/31 13:56

編集2020/04/01 04:49

こちらの質問を参考に機体を動かすときにトルクをつけたのですが
左・右キーを押す前に上・下キーを押すと機体が回転してします。
左・右キーを押すとなおるのはなんでなんでしょうか?
GIF画像が重すぎてアップロードできなかったのでGoogleDriveにアップロードしました。リンクはこちらです

コード自体全てを理解できているわけではないですが
下の行が影響しているようです

C#

1// プレイヤーの入力に応じて姿勢をひねろうとするトルク 2Vector3 rotationTorque = new Vector3(-y * pitchTorqueMagnitude, x * yawTorqueMagnitude, -x * rollTorqueMagnitude);

以下ソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Player : MonoBehaviour 6{ 7 public float moveSpeed = 80.0f; 8 public float moveForceMultiplier = 0.4f; 9 10 // 水平移動時に機首を左右に向けるトルク 11 private float yawTorqueMagnitude = 25.0f; 12 13 // 垂直移動時に機首を上下に向けるトルク 14 private float pitchTorqueMagnitude = 60.0f; 15 16 // 水平移動時に機体を左右に傾けるトルク 17 private float rollTorqueMagnitude = 50.0f; 18 19 // バネのように姿勢を元に戻すトルク 20 private float restoringTorqueMagnitude = 100.0f; 21 22 private Rigidbody rigidbody; 23 24 void Awake() 25 { 26 rigidbody = GetComponent<Rigidbody>(); 27 // バネ復元力でゆらゆら揺れ続けるのを防ぐため、angularDragを大きめにしておく 28 rigidbody.angularDrag = 10.0f; 29 } 30 31 void FixedUpdate() 32 { 33 float x = Input.GetAxis("Horizontal"); 34 float y = Input.GetAxis("Vertical"); 35 // xとyにspeedを掛ける 36 rigidbody.AddForce(x * moveSpeed, y * moveSpeed, 0); 37 38 rigidbody.AddForce(moveForceMultiplier * (Vector3.zero - rigidbody.velocity)); 39 40 // プレイヤーの入力に応じて姿勢をひねろうとするトルク 41 Vector3 rotationTorque = new Vector3(-y * pitchTorqueMagnitude, x * yawTorqueMagnitude, -x * rollTorqueMagnitude); 42 43 //現在の姿勢のずれに比例した大きさで逆方向にひねろうとするトルク 44 Vector3 right = transform.right; 45 Vector3 up = transform.up; 46 Vector3 forward = transform.forward; 47 Vector3 restoringTorque = new Vector3(forward.y - up.z, right.z - forward.x, up.x - right.y) * restoringTorqueMagnitude; 48 49 // 機体にトルクを加える 50 rigidbody.AddTorque(rotationTorque + restoringTorque); 51 } 52 53}

環境

OS:MacOS Catalina 10.15.3
Unityのバージョンは2018.4.19f1です

追記

  • スクリプトは提示した物で全てです
  • CubeとCapsuleで試してみたところ、どちらも正常通りでした
  • 飛行機はこちらのアセットを使用しています

↓インスペクタータブの画像です
画像

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

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

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

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

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

Bongo

2020/04/01 03:58

奇妙な症状ですね... のちほど調べてみようと思いますが、参考情報としていくつかおうかがいしたいです。 ・このスクリプト以外にRigidbodyまたはTransformに対して何か操作を行っているスクリプトはあるでしょうか?もしありましたら、そちらのコードもご提示願います。 ・このスクリプトとRigidbodyのインスペクターの様子をご提示いただけるでしょうか。その際、念のためRigidbodyの「Info」の内容も見えるように撮影願います。InfoにはVector3型の項目もありますので、インスペクターの横幅が狭いと値が見切れてしまうかもしれません。必要に応じて横幅を広げていただけるとありがたいです。 ・このスクリプトをこの飛行機以外で使用しても同じ現象が起きるでしょうか?たとえばCubeやCapsuleにRigidbodyとこのスクリプトを付けた場合でも、同様に初期位置から上下に動かすとクルクル回ってしまうでしょうか。
guest

回答1

0

ベストアンサー

追加情報ご提示ありがとうございます。どうやらTransformの初期回転が(0, 0, 180)になっているのがまずいようですね。

いずれかの軸が180°反転している姿勢というのは、あのスクリプトにとって特異点のようなものなのです。
あのスクリプトがかけている復元トルクは、イメージとしてはいわばtransform.rightの先端とVector3.rightの先端、transform.upの先端とVector3.upの先端、transform.forwardの先端とVector3.forwardの先端をそれぞれゴムで繋いだようなものでして、ぴったり180°回転した姿勢ではゴムの張力が均衡してしまい姿勢を元に戻せなくなるのです。
その状態でゲームを開始して上下にだけ移動させたときには、transform.upVector3.upの方に引っ張るトルクとtransform.forwardVector3.forwardの方に引っ張るトルクがちょうど釣り合って復元力がかからず、上下入力の際に加えられた回転がそのまま残ってクルクル回り続けてしまうわけです。

ご提示いただいたGIFアニメーションで、最初に横移動しようとしたときに機体がクルッと反転する様子が映っています。このときに力の均衡が崩れて正常な姿勢に戻り、以降は意図通り安定した動きになっています。
ゲーム開始直後にいきなり左右に移動させた場合には上下のときのようなクルクル現象は起こらず、すぐに1回クルッと反転して安定な動きに移行しますが、これは見栄えをよくするために加えた「水平移動時に機体を左右に傾けるトルク」が均衡を崩しているためでしょう。試しにrollTorqueMagnitudeの値を0にすると、水平移動でもクルクル現象が発生するはずです。

ご質問者さんがZを180°反転させているのはどのような理由からでしょうか?もしZが180°反転した姿勢を正常な姿勢として扱いたい場合、上で申し上げたようなスクリプトの都合上、その反転した姿勢が無回転...(0, 0, 0)の姿勢となるようにしてやる必要があります。
つまり、下図のように...

図

SpaceshipFighter_Spear自身のRigidbodyPlayerスクリプトは削除してしまい、空のゲームオブジェクトを作ってSpaceshipFighter_Spearはそれの子階層に入れてやり、RigidbodyPlayerスクリプトは空ゲームオブジェクトの方にアタッチしてみてください。

投稿2020/04/01 11:42

Bongo

総合スコア10811

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

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

l-_-l

2020/04/01 12:35 編集

そういうことだったのですか、悩んでいたのが解決して嬉しいです。 ありがとうございます!! 単純にこっちの向きの方が好みだったのでZを180度回転させたのですが、 よく考えればカメラの向きを変えればよいだけだったかもですね。 180度のまま動作させる方法までありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問