🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

Unity

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

Q&A

解決済

1回答

709閲覧

プレイヤーを軸に回転した後に、同じところで止めたいのですが、毎回違うところで止まってしまいます。

Um_kok

総合スコア39

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2021/01/25 08:35

こんにちは、只今ゲーム制作をしております。
そこで、詰まってしまったので質問させていただきます。

まず、コードです。今作っているのはレースゲームなのですが、ゴールした後のカメラワークについてです。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Camera : MonoBehaviour 6{ 7 8 // キャラクター 9 [SerializeField] private Transform target; 10 11 // カメラの高さ 12 [SerializeField, Range(1, 100)] 13 private float camHeight = 5.0f; 14 15 // キャラクターからの(Z軸における)距離 16 [SerializeField, Range(1, 100)] 17 private float camDistance = 5.0f; 18 19 [SerializeField] private float rotSpeed = 3f; 20 21 22 public bool goalFlg; // ゴールしたか 23 private bool cameraMoveFlg; // カメラが移動したか 24 private int numberOfRotations = 0; // カメラを回転した数 25 private float cameraDistance; // カメラとプレイヤーの距離 26 27 private void LateUpdate() 28 { 29 30 if (!goalFlg) {// ゴールしたか 31 32 PlayerCamera(); 33 } 34 else { 35 36 GoalAngleCamera(); 37 } 38 } 39 40 /// <summary> 41 /// プレイヤーを写すカメラ 42 /// </summary> 43 private void PlayerCamera() 44 { 45 // キャラクターの位置から距離分後ろに下がり、高さ分上にあがる処理 46 transform.position = target.position - (target.forward * camDistance) + new Vector3(0, camHeight, 0); 47 transform.LookAt(target); 48 } 49 /// <summary> 50 /// プレイヤーのゴール時、カメラを動かす 51 /// </summary> 52 private void GoalAngleCamera() 53 { 54 55 if (cameraMoveFlg) return; // カメラの移動が終わったら通らない 56 57 58 float speed = 1 / rotSpeed; 59 60 float value = Time.time * 2 * Mathf.PI * speed; 61 62 transform.position = target.position + new Vector3(Mathf.Sin(-value), 0, Mathf.Cos(-value)) * -camDistance; 63 transform.LookAt(target); 64 65 print(value); 66 float rot = 47; 67 if(value > rot) { 68 cameraMoveFlg = true; 69 gameObject.transform.parent = target.gameObject.transform; 70 } 71 } 72}

このように、ゴールしていないときは後ろから追従して、ゴールした後に、プレイヤーを軸に回転して、一定の角度まで回ったら、そこで、止まる、、、というものです。なのですがカメラが前で止まったり、後ろで止まったりしてしまいます。
何故でしょうか?ご回答お願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

float value = Time.time * 2 * Mathf.PI * speed;

Unityは知りませんが,ここの Time.time ってどんな値なんでしょう?
何らかの時刻で回転角を決めているようですが,この値の起点や刻み幅が所望の動作に対して真っ当(?)ではないのではないかと想像します.


[追記]
考えの整理がつかないのであれば,一旦落ち着いて,valueに関して

  • どの時点で0になっていてほしいのか
  • どのくらいの時間をかけて最終値に到達してほしいのか

といった事柄をきちんと決めましょう.
で,valueの値と時間との関係を,例えば下図のようにグラフにでも描いてみましょう.
実際に描いてみれば,時間の値 Time.time から value を決める式は簡単に導出できることがわかるでしょう.

イメージ説明

(おっと,図の右下の「時間」は誤記ですね.直すのも面倒なので,「時刻」として見ていただきたい)

投稿2021/01/25 08:47

編集2021/01/26 01:54
fana

総合スコア11990

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

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

Um_kok

2021/01/25 10:21

ご回答ありがとうございます。お返事遅れました。 おっしゃる通り原因はそこにありそうです。 Time.time というのは、ゲームが実行されてからの時間が格納されています。 すなわち、増え続けます。なので、value が増えずずけて、Mathf.SinとMathf.Cos に入れて、カメラを回転させつづけています。 なので、GoalAngleCamera関数が呼ばれたときに Time.time = 0 にしたいのですが Update() で呼び続けられてしまうので、カメラが回らなくなってしまいます。 どうすればよいですか?
fana

2021/01/26 01:06 編集

その話だと,ゴール直後のカメラ位置(周り始める位置)が既に毎回異なっているのでは…? (実時間を用いねばならない理由は不明ですが,それはそれとして)Time.time なる値に連動して角度を変えるにしても, 毎度の角度算出に Time.time なる値をそのまま用いるのではなく, ゴール直後(=カメラの回転をし始める時点)の Time.time なる値をどこぞに記憶しておいて, 以降で回転角を算出する際にはそこからの相対時刻を用いれば良いだけに思えます.
fana

2021/01/26 01:51 編集

というか, > Time.time というのは、ゲームが実行されてからの時間が格納されています。 ということを把握されているのであれば,この値をそのまま用いたらどうなるのかは当然承知の上なハズ… (これって真面目な質問なんですよね…???) 一応,算数の話を追記しておきました. (意味的にvalueの値は最終値で飽和してほしいのではないかと思うので,図内赤線はある時刻以降は傾き0として描いてあります.)
Um_kok

2021/01/26 07:46

お返事遅れました。 至って真面目なお話です。 Time.time に関しては貴方様に言われたので気づきました。 確認なのですが、ゴール時にTime.time を一回だけ格納してvalue を上げていけば良いのですね? その格納した、Time.time * value で回転する角度がでる。ということでしょうか?
fana

2021/01/26 08:27

(うーん,ベクトルやら三角関数を用いた演算コードを示している人に対してこんな説明を書くのもどうなんだ…という感じですが) 要は,現在時刻 t に対する value の値を決める関数 value = f(t) があればよいのですよね? で,この関数はシンプルに一次関数である,と. であれば f(t) = a * ( t - Tg )  ここで  a は処理パラメータであり,この値によって回転速度(と回転方向)を定める.  Tg はゴールした時刻である. …くらいの話で良いのでは.
Um_kok

2021/01/26 09:35

すみません。数学は苦手なもので、、、 こう言う感じで宜しいでしょうか? value = 2ーパイ*Time.time 一 格納された時間*スピード という事ですね。
fana

2021/01/26 10:02

上記コメントのように a を用いて書けば, a = 2 * Mathf.PI * speed; value = a * ( Time.time - 格納しておいたゴール時の時刻 ); とかですかね. 初期回転角(一番最初のvalueの値)が0ではない場合には,さらに初期回転角を加算すればよいでしょう. value = a * ( Time.time - 格納しておいたゴール時の時刻 ) + 初期回転角;
fana

2021/01/27 01:09 編集

本題ではない(わりとどうでもいい)話ですが, > 2 * Mathf.PI * speed; って,(あなたにとって)考えやすい式なんでしょうか? 回転速度を調整したいときに,speed の値を求めるのに使われている rotSpeed の値を増減させるのでしょうけど,「所望の回転速度にするためには rotSpeed をどんな値にすればよいのか?」が分かりにくくないですか? ここでのaの意味は「1秒間に回転させたい角度[rad]」ですから,ダイレクトにそのような意味合いの値を扱った方が調整が楽そうに思えます.
Um_kok

2021/01/26 12:06

お返事遅れました。 分かりにくいコードですみません。 確かに float speed = 1 / rotSpeed; だと rotSpeed秒に1回回転という訳になるので分かりにくいですね。 もう少し良いやり方を考えてみようと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問