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

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

詳細はこちら
C#

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

3回答

2285閲覧

特定のオブジェクトを原点とした回転運動における角度の変更

Izayoi-san

総合スコア12

C#

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2021/02/08 11:37

今特定のオブジェクトを中心に、その周囲を一定間隔・一定周期で円運動するプログラムを作成しています。
オブジェクトのtransformを変更することで回転運動を実現しようと考えています。

現在下記のコードにおいて、デバッグを実施したところ、
②の部分のコードで対象オブジェクト(BossObj[0])のpositionを変更し、円の軌道上を移動させ続けることは成功しています。

しかし、③の部分で原点(PlayerObj)からみて対象オブジェクトが常に一定の方向を向かせようとしていますが、うまくいっていません。
(文章だけではわかりにくいと思いましたので、うまくいっていない状況に関しては参考(図1)を添付しておきます)

Mathf.Cosを利用して算出している角度が0°~90°に該当する範囲でしか算出されていないようなのですが、
対象オブジェクトの位置そのものは原点を中心に360°移動しており、
Mathf.AcosはUnityで用意されている関数なので、こうなってしまう原因がわかっておりません。

C#

1public class UltimetWepon : MonoBehaviour 2{ 3 void FixedUpdate() 4 { 5 //①プレイヤー【PlayerObj】と対象【BossObj[0]】位置情報の取得 6 PlayerTransform = PlayerObj.transform; 7 PlayerLocate = PlayerTransform.position; 8 BossTransform1 = BossObj[0].transform; 9 BossLocate1 = BossTransform1.position; 10 11 //②対象の位置情報の算出(プレイヤーの位置を中心に半径Rangeで回転運動させる) 12 BossLocate1.x = PlayerLocate.x + Range * Mathf.Cos(2 * Mathf.PI * period * Time.time); 13 BossLocate1.y = PlayerLocate.y + Range * Mathf.Sin(2 * Mathf.PI * period * Time.time); 14 BossObj[0].transform.position = BossLocate1; 15 16 //③プレイヤーの位置から見た対象の角度を算出 17 Direction1 = Mathf.Acos(Mathf.Abs(PlayerLocate.y - BossLocate1.y) / Mathf.Sqrt(Mathf.Pow(PlayerLocate.x - BossLocate1.x, 2) + Mathf.Pow(PlayerLocate.y - BossLocate1.y, 2))); 18 BossObj[0].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * Direction1); 19 20 } 21}

イメージ説明
図1:現状参考

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

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

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

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

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

guest

回答3

0

Unityを知らないので,transformがどうこういう話はわかりませんが…

**(1)**図内赤矢印の向きを求めたいのであれば,わざわざ「角度」を求める必要性がわかりません.(transformとかいうのを使うには必須なのでしょうか?)
2つのオブジェクトの位置関係が分かっているならば,図の「成功例」の赤矢印の向きは既に自明ではないでしょうか.

(2)「角度」を求めることが必須なのだとしても

Direction1 = Mathf.Acos(Mathf.Abs(PlayerLocate.y - BossLocate1.y) / Mathf.Sqrt(Mathf.Pow(PlayerLocate.x - BossLocate1.x, 2) + Mathf.Pow(PlayerLocate.y - BossLocate1.y, 2)));

ここで Abs が用いられている理由がわかりません.

0°~90°

みたいな話の原因はコレでは?

投稿2021/02/09 01:45

編集2021/02/09 01:46
fana

総合スコア11990

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

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

Izayoi-san

2021/02/09 10:13

(1)図内赤矢印の向きを求めたいのであれば,わざわざ「角度」を求める必要性がわかりません.に関してですが、 Unityはtransformの中で位置情報を扱うpositionと角度情報を扱うrotationが別です。 なので、何の例をもって自明とおっしゃっているのかちょっとわかりません。(Unityを知らないとおっしゃっているので別のソフトでの話でしょうか?) (2)「角度」を求めることが必須なのだとしてもに関してですが ABSをはずしても0°~180°までしか変化しません。こちらに関しては関数の仕様だと考えています。 そのため、ABSで絶対値にした上で角度の代入時に調整などする必要があるか、関数の仕様時に調整できるのかと考えているところです。 せっかくご指摘をいただいたのに申し訳ないのですが、Unityを知らない、 かつ何を想定されているのかこちらにはわからない状態ですので、何がおっしゃりたいのかいまいち把握できておりません。
Izayoi-san

2021/02/09 10:14

Unityを知らない状態でのご指摘なので、私には貴方様がおっしゃりたいことがいまいちピンときていません。
fana

2021/02/09 10:38 編集

「対象オブジェクト」の座標(図内で赤い矢印) から 「プレイヤー」の座標(図内で★) を引けば,それが 「対象オブジェクト」が向くべき方向を示すベクトルなんじゃないですか? というのが「自明」と記した話. だから,(Unity知らんから,それが可能かどうか不明だけども)ベクトルそのもので指定できる方法が存在するのならば,「角度」を経る必要はないのでは? という. > Mathf.Cosを利用して算出している角度が0°~90°に該当する範囲でしか算出されていない 理由として ABS を指摘しましたが,間違ってますか? (まぁそれを取っ払ったところで,おっしゃるように,360度範囲が得られるという話ではないですから,回答としては不親切すぎるだろ! というのはわかります. 「こうなってしまう原因がわかっておりません。 」とのことだったので,まずはとりあえず原因は知りたいかな,と.) で,「角度」が360範囲で欲しいなら,atan2 的なものが無いのかを探してみれば良いのではないでしょうか?(……まぁそれもUnityだと存在しないのか等,知りませんが)
fana

2021/02/09 10:41

低評価を入れる場合, 「低評価理由:ちょっと何言ってるのかわからないので」 みたいな感じで,明確に書いていただけると助かります.
fana

2021/02/09 11:03

(つーか,すぐ上でsinだのcosだのに「角度」そのものを食わせてますやん.)
Izayoi-san

2021/02/09 11:16

低評価理由はUnityをわからないとおっしゃっている状態でよくわからないままにこうすればいいんじゃないのとおっしゃっていることです。 私視点での貴方様は当人にもよくわからないことをよくわからないままにおっしゃっている知らない人になります。 よくわからないままにご指摘をいただいてもこちらもよくわからないというのが、 私独自の思考なのかもしれませんがご理解いただけると幸いです。
fiveHundred

2021/02/09 12:19 編集

斜め読みなので全て把握していませんが、Unityでも「transform.forward」や「transform.LookAt()」があります。 これらで向きのベクトルや座標を指定すれば、角度を求めずに向きを変えられるので、この回答が的を得ていないとはとても思えません。 いくら何でも低評価はあんまりので、打ち消しておきます。
fiveHundred

2021/02/09 12:13

ついでに「Mathf.Atan2()」も存在します。
ozwk

2021/02/09 12:49

わざわざ回転角度を求めるまでもなく 2 * Mathf.PI * period * Time.time <- これが角度では?
fana

2021/02/10 01:28

> 低評価理由 要は「内容がわからん」という意味合いであることが把握できたのでOK. 意味合いが伝わるかどうか自信が無いですが,以下に補足はしておきます. (1)の話: 「方向」を角度で表すかベクトルで表すかその他なのか,いろいろあるでしょうけども, 既に得られているベクトルをそのまま指定することが可能であるならば,それが手っ取り早いのではないか,という. (「角度」に直して指定しなくても済むのであれば,「角度」を求める必要性自体が無い) 以上が Unityのtransformを使う場面において当てはまるかどうかを私は知らないが,一般論(?)として. (2)の話: 質問文にて不明とされている原因を率直に述べた. それ以上でもそれ以下でもない. (絶対値の計算が現れることはは話の内容に対してあまりにも不自然に思われた.  そのため,そこのABSというのはコピペか何かの際に混じり込んだような凡ミス的なもので,その存在を指摘さえすれば即終わるだろう,みたいな勝手な想像もあった)
fana

2021/02/10 01:49

「対象オブジェクト」の向きを指定する手段に関する現状出ている話は以下の3種かな: ・実際その角度はもう算出済みだよ説 ・acos じゃなくて atan2 で求めればいいよ説 ・ベクトルで指定する方法もあるかもしれないよ説 簡単に試せそうな物から検証してみては.
guest

0

自己解決

下記コードのようにすることで考えていた動きができました。
最終的には4つの対象オブジェクトをプレイヤーオブジェクトの周囲(異なる場所)に配置したかったので、
角度をそのまま代入すると補正値が必要になるのでもう少し検討をしてみようと考えています。

あとは三角関数を触っていたのがはるか昔であんまり覚えていなかったので、思い出さないといけない状態です。

C#

1public class UltimetBoss : MonoBehaviour 2{ 3 void FixedUpdate() 4 { 5 PlayerTransform = PlayerObj.transform; 6 PlayerLocate = PlayerTransform.position; 7 BossTransform1 = BossObj[0].transform; 8 BossLocate1 = BossTransform1.position; 9 BossTransform2 = BossObj[1].transform; 10 BossLocate2 = BossTransform2.position; 11 BossTransform3 = BossObj[2].transform; 12 BossLocate3 = BossTransform3.position; 13 BossTransform4 = BossObj[3].transform; 14 BossLocate4 = BossTransform4.position; 15 16 BossLocate1.x = PlayerLocate.x + Range * Mathf.Cos(2 * Mathf.PI * period * Time.time); 17 BossLocate1.y = PlayerLocate.y + Range * Mathf.Sin(2 * Mathf.PI * period * Time.time); 18 BossLocate2.x = PlayerLocate.x + Range * Mathf.Cos(2 * Mathf.PI * period * (Time.time + 4 * period / 4)); 19 BossLocate2.y = PlayerLocate.y + Range * Mathf.Sin(2 * Mathf.PI * period * (Time.time + 4 * period / 4)); 20 BossLocate3.x = PlayerLocate.x + Range * Mathf.Cos(2 * Mathf.PI * period * (Time.time + 8 * period / 4)); 21 BossLocate3.y = PlayerLocate.y + Range * Mathf.Sin(2 * Mathf.PI * period * (Time.time + 8 * period / 4)); 22 BossLocate4.x = PlayerLocate.x + Range * Mathf.Cos(2 * Mathf.PI * period * (Time.time + 12 * period / 4)); 23 BossLocate4.y = PlayerLocate.y + Range * Mathf.Sin(2 * Mathf.PI * period * (Time.time + 12 * period / 4)); 24 25 BossObj[0].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * (2 * Mathf.PI * period * Time.time) - 90.0f); 26 BossObj[1].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * (2 * Mathf.PI * period * (Time.time + 4 * period / 4)) - 90.0f); 27 BossObj[2].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * (2 * Mathf.PI * period * (Time.time + 8 * period / 4)) - 90.0f); 28 BossObj[3].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * (2 * Mathf.PI * period * (Time.time + 12 * period / 4)) - 90.0f); 29 30 BossObj[0].transform.position = BossLocate1; 31 BossObj[1].transform.position = BossLocate2; 32 BossObj[2].transform.position = BossLocate3; 33 BossObj[3].transform.position = BossLocate4; 34 35 } 36}

投稿2021/02/10 14:15

Izayoi-san

総合スコア12

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

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

0

・実際その角度はもう算出済みだよ説
・acos じゃなくて atan2 で求めればいいよ説
・ベクトルで指定する方法もあるかもしれないよ説

質問者さんが検証するか怪しいので、こちらで検証してみました。
(普通は質問者さんが検証すべき内容だと思っているので、次は無いと思ってください)

C#

1#if true 2 // 実際その角度はもう算出済みだよ説 3 Direction1 = 2 * Mathf.PI * period * Time.time; 4 BossObj[0].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * Direction1); 5#elif false 6 // acos じゃなくて atan2 で求めればいいよ説 7 Direction1 = Mathf.Atan2(BossLocate1.y - PlayerLocate.y, BossLocate1.x - PlayerLocate.x); 8 BossObj[0].transform.rotation = Quaternion.Euler(0, 0, Mathf.Rad2Deg * Direction1); 9#else 10 // ベクトルで指定する方法もあるかもしれないよ説 11 BossObj[0].transform.forward = BossLocate1 - PlayerLocate; 12#endif

いずれも動作します。

投稿2021/02/10 02:41

fiveHundred

総合スコア10152

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問