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

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

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

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

Unity

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

Q&A

解決済

1回答

3654閲覧

Unity-3次元ベクトルをスクリーン座標に投影・変換する

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

Unity

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

0グッド

0クリップ

投稿2017/11/10 13:40

3Dゲームを製作しています。

3D空間上に配置された薄いパネル(コライダが設定されている)を画面上でタッチ・スワイプした時に、スワイプした方向がパネルにとって左右方向により近いならtrueを、上下方向により近いならfalseを返すメソッドを書きたいです。

メインカメラが移動してパネルを見る角度が変化する設定なので、実装方法として、
1:タップしたポイントと指(あるいはマウス)を離したポイントをWorldToScreenPointでスクリーン座標に変換し、2点の差を取ることでスワイプのベクトルを得る。
2:パネルの上下方向(transform.up)と左右方向(transform.right)をスクリーン座標に投影・変換する。
3:"1"で得たベクトルと"2"で得た2ベクトルとの角度をそれぞれVector2.Angleで測り、左右方向との角度の方が小さければtrueを、上下方向との角度の方が小さければfalseを返す。

というのを考えています。
そこで質問なのですが、WorldToScreenPointで空間上の点をスクリーン座標上に投影・変換するように、ベクトルをスクリーン座標に投影・変換することは可能ですか?
あるいは上記のような実装をする上でより適した方法はありますか?

試したこと:
Camera.main.WorldToScreenPoint(transform.up/right);で変換してみたのですが、エラーこそ出ないものの、これで得られるベクトルは常にスクリーン上での上下・左右方向となってしまい、期待している「パネルにおける上下左右方向をスクリーンに投影したもの」にはなりませんでした。

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

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

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

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

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

guest

回答1

0

ベストアンサー

タップ開始点と終了点をそれぞれScreenToWorldPointでワールド座標にして、両者の差を取ってワールド座標系でのスワイプベクトルとし、それをさらにパネルのtransformのInverseTransformVectorに渡してパネルローカル座標系でのスワイプベクトルを求める、というのはどうでしょう?
あとはその変換したスワイプベクトルのxの絶対値とyの絶対値を比較すれば(パネルがローカル座標においてZ軸+に面しており、パネル上縁がY軸+を向いている場合です)、パネルに対して左右にスワイプしたか上下にスワイプしたか判定できるのではないでしょうか。

[補足を追記]
最初の部分で申し上げました、タップ開始点と終了点のワールド座標を求めるという件についてですが、たとえばカメラからレイキャストしてパネルとの衝突点を取っているのでしたら、衝突点がそのままワールド座標で得られるのでScreenToWorldPointを使う必要はないでしょう。ご質問者さんの設計に合った方法を試してみてください。

投稿2017/11/10 14:50

編集2017/11/11 05:54
Bongo

総合スコア10807

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

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

退会済みユーザー

退会済みユーザー

2017/11/11 08:42

回答ありがとうございます。 アドバイスしてくださった通りに実装してみたのですが、タップ開始点と終了点をScreenToWorldPointで変換した時点で同値になってしまっているらしく、スワイプベクトルがゼロになってしまいます。 ScreenToWorldPointの内部処理を知らないのですが、これはタップした点からレイキャストして、何らかのコライダにヒットした地点が表示されているのでしょうか? 例えば「パネル上でタップ始め、パネル外でタップ終わり」といった終了点からのレイキャストがコライダにヒットしない状況ではScreenToWorldPointはうまく作動しないんでしょうか
Bongo

2017/11/11 11:04

ScreenToWorldPointはレイキャストを行っているわけではなく(つまりコライダーとは無関係に)、二次元スクリーン座標をカメラ前方の仮想的な平面に投影したときの三次元ワールド座標を計算しているものと思います。 ScreenToWorldPointを使うときの注意点として、ScreenToWorldPointに渡すVector3は、xとyについてはタップ座標のxとyでいいですが、zは0より大きな適当な数(たとえば1とか10とか)を定めてやる必要があります(これがカメラからどれだけ離れた平面上に座標を投影するかを表します)。たとえばもしInput.mousePositionをそのまま渡したりしてしまうと、zが0になってしまう...つまり画面上のどこをタップしようが変換後の座標はカメラ自身の座標になってしまうと予想されます。スワイプベクトルが0になったとのことですが、上記のような状況になっていませんでしょうか?
退会済みユーザー

退会済みユーザー

2017/11/11 13:29

Bongoさんのおっしゃる通りでした、zを定めてやったところ思い通りに動いてくれました! これで次のステップに行けそうです、丁寧な回答ありがとうございましたm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問