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

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

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

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

Q&A

解決済

1回答

2143閲覧

FPSでオートマチックにアングルを変更する方法。

tkshp

総合スコア174

Unity

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

0グッド

0クリップ

投稿2016/09/11 14:45

編集2016/09/13 09:46

###前提・実現したいこと

前回、こちらで質問して、FPSのアングル変更の処理をご教授いただきました。
ご回答者様、ありがとうございました。

仕様は、FPSで垂直方向に関しては-90度~90度までの制限をかけてのアングル変更、水平方向に関しては、制限なく回転できるものです。

その応用で、垂直方向にアングルを変更した際、デフォルトの角度、つまりrotX=0 に戻るようなリセットキーを作りたいと考えています。
現在、そのリセットキーの処理で、瞬時にrotX=0と変わるものは作れました。

しかし、瞬時に切り替わるのではなく、rotX = [現在の角度] から、rotX = 0 までイージング、もしくは等速運動でアングルが変わるものを作りたいと考えています。

ゲームイメージとしては、例えば、天井を見上げてた視界が、体の正面(rotX=0)まで、首を下ろすような動きで、視界が変わる処理です。(地面を見ていた場合は、顔を上げる動きで、地面から正面まで視界が変わる処理。)

コードロジックとして、FixedUpdate()の中で常にrotXが更新されているので、ここから更にrotXの値を連続的に変えていく方法が思いつきません。

どのようなコードを書いたらよいのでしょうか?

###該当のソースコード

C#

1 2 3 4public class GameObjectScript : MonoBehaviour { 5 6 GameObject camera; 7 public float rotSpeed = 5.0f; 8 float rotX = 0.0f, rotY = 0.0f; 9 10 void Start(){ 11 camera = GameObject.Find("Main Camera"); 12 } 13 14 private void FixedUpdate() 15 { 16 // Read input 17 float horizontal = Input.GetAxis("Horizontal"); 18 float vertical = Input.GetAxis("Vertical"); 19 20 rotX -= vertical * rotSpeed; 21 rotY += horizontal * rotSpeed; 22 23 rotX = Mathf.Clamp( rotX, -90.0f, 90.0f ); 24 while( rotY < 0.0f ) { rotY += 360.0f; } 25 while( rotY > 360.0f ) { rotY -= 360.0f; } 26 27 //垂直方向リセット処理。 28 //この処理だと瞬時に切り替わってしまう。 29 //現在のrotXの値から、rotX = 0 の値まで、イージングするような動き、もしくは等速運動で変化させたい。 30 if (Input.GetKeyDown (KeyCode.R)) { 31 rotX = 0; 32 } 33 34 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 35 36 } 37}

###追記。
ご回答ありがとうございます。マイナスの場合の処理を継ぎ足してみました。

C#

1 IEnumerator ResetAngleAnimation() { 2 float speed = 3.0f; //メンバで定義してもよい。 3 if (rotX > 0) 4 { 5 while(rotX > 0) 6 { 7 rotX -= speed; 8 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 9 yield return null; 10 } 11 } 12 else if (rotX < 0) 13 { 14 while(rotX < 0) 15 { 16 rotX += speed; 17 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 18 yield return null; 19 } 20 } 21 22 // 最後はぴったり0になるようにする。 23 rotX = 0; 24 25 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 26 yield return null; 27 }

###追記②。
ご回答ありがとうございます。末尾の「yield return null」は書かなくても問題ないですか?

C#

1 IEnumerator ResetAngleAnimation() { 2 float speed = 3.0f; //メンバで定義してもよい。 3 if (rotX > 0) 4 { 5 (省略) 6 } 7 else if (rotX < 0) 8 { 9 (省略) 10 } 11 12 // 最後はぴったり0になるようにする。 13 rotX = 0; 14 15 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 16 //yield return null; //コメントアウト可? 17 }

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

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

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

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

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

guest

回答1

0

ベストアンサー

Unirx等の強力なライブラリを使う方法もありますが、
標準のやり方ならコルーチンですね。
不完全ですが、以下サンプル(マイナスの場合の処理を継ぎ足しておいてください)

c#

1IEnumerator SampleResetAnimation() { 2 float speed = 1.0f; // もちろん、メンバで定義しておいてもOK 3 if (rotX > 0) 4 { 5 while(rotX > 0) 6 { 7 rotX -= speed; 8 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 9 yield return null; 10 } 11 } 12 // 最後はぴったり0になるように 13 rotX = 0; 14 camera.transform.eulerAngles = new Vector3(rotX, rotY, 0.0f ); 15 yield return null; 16} 17 18//updateでこのように呼び出す。 19if (Input.GetKeyDown (KeyCode.R)) { 20 StartCoroutine("SampleResetAnimation"); 21}

投稿2016/09/12 02:09

編集2016/09/12 02:21
ishi9

総合スコア1294

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

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

tkshp

2016/09/12 16:00

ご回答ありがとうございます。目的のコードは完成したのですが、コルーチンの文法が理解できておらず(マニュアルのご提示ありがとうございます)、なぜこれで意図通りの挙動ができてしまうのか?悩んでます。 (yield return nullはどうゆうタイミングで行い、なぜ一気にrotX=0にならないのか?等) 少々、考えるお時間をください。恐れ入りますが、よろしくお願いします。 また、マイナスの場合の処理を継ぎ足してみました、合っているかご確認お願いできますか?
ishi9

2016/09/13 01:36 編集

yield return nullはさっくり説明すると、1フレーム進める処理です。 yield return nullにぶつかると1フレームの間、処理がそこで止まるというイメージでしょうか。呼び出し元であるGameObjectScriptのFixedUpdateもResetAngleAnimationが終了するまでそこで止まったままです。 マイナスの場合の処理はそうですね。多分そんな感じでいけると思います (実際にデバッグしてないので確証はありませんが) この辺りは比較的優しめで一通りのことを網羅しているのではないでしょうか http://tsubakit1.hateblo.jp/entry/2015/04/06/060608
tkshp

2016/09/13 09:50

ご回答ありがとうございます。ご説明とURLのご提示ありがとうございます。 コルーチンについてだいぶ理解できました。 1点だけ気になったのですが、末尾の「yield return null」は必要でしょうか? 試しにコメントアウトしてみた所、問題なく動いているように見えました(詳細は追記②)。
ishi9

2016/09/13 09:54

無くても特に問題無いですよ。カメラを0度にした状態から1フレーム待つか、待たないかだけなので体感ではまずわからないでしょう。なんとなく入れておきましたが、深い意味はありません。
tkshp

2016/09/13 11:12

ご回答ありがとうございます。今回はライブラリでなく、標準のやり方を知りたかったのでとても勉強になりました。コルーチンを知って、だいぶプログラムの幅が広がりました。最後までご教授くださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問