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

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

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

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

Unity

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

Q&A

解決済

2回答

4129閲覧

World Spaceで扱うCanvasをカメラの視界の中央に寄せる方法。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2016/10/27 16:04

編集2016/10/27 16:10

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

任意のサイズでWorld Spaceで扱うCanvasを、
エディタ上で、任意の位置や角度のカメラの視界の中央に寄せる方法のご教授をお願いいたします。

※ゲームを実行してからプログラムでCanvasを中央に寄せるのではなく、
エディタでシーンを編集してる時点で、カメラの視界の中央に寄せる方法を知りたいです。
(そのカメラがメインカメラに設定された場合は、ゲーム画面の中央にCanvasが位置する。)

###試したこと その1

下記のような方法で、Canvasを中央に寄せることはできました。

・カメラの位置や角度を下記の設定にする。
Position → X:0, Y:0, Z:-10。
Rotation → X:0, Y:0, Z:0。

・Canvasの位置を下記の設定にする。
Pos X:0, Pos Y:0, Pos Z:0
Width, Heightは任意のサイズ。

この方法ならば、画面の中央に寄せることができますが、条件が限定されてしまいます。

カメラを任意の位置や角度にしたときに、そのカメラの視界の中央にくるような
CanvasのPos X, Pos Y, Pos Zの設定方法を知りたいです。

###試したこと その2

AdobeのIllustratorのような、オブジェクトを整列パネルで中央寄せにするようなメニューを探したが、
見当たらない。

###補足情報(言語/FW/ツール等のバージョンなど)
カメラはPerspectiveで扱います。

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

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

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

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

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

guest

回答2

0

ベストアンサー

もう解決済みになっていますが、エディタ拡張のスクリプトを書くとこんな感じです。

MoveCanvas.csをカメラオブジェクトにアタッチして、MoveCanvasInspector.cs
Assets/Editorディレクトリに置けばカメラのインスペクタにMoveとBackのボタンが表示されるので、
MoveCanvasスクリプトの canvasに移動したいCanvasを設定して、Moveボタンでキャンバスをカメラの中央に移動、Backボタンで移動前の位置に戻ります。
distanceはカメラからの距離になります。正ではく、負の値なので注意してください。

細かく動作の確認はしていないので、場合によってはCanvasが上手く中央に移動されないかもしれません。
その時は適宜スクリプトを書き換えてください。

C#

1using UnityEngine; 2 3[RequireComponent(typeof(Camera))] 4public class MoveCanvas : MonoBehaviour { 5 public Canvas canvas; 6 public float distance = -10.0f; 7 private Vector3 prevCanvasPosition; 8 private Quaternion prevCanvasRotation; 9 10 public void MoveToCamera() { 11 if (canvas != null) { 12 if (canvas.renderMode == RenderMode.WorldSpace) { 13 var _camera = GetComponent<Camera>(); 14 var _cameraRot = GetComponent<Transform>().localRotation; 15 var _canvasRectTf = canvas.GetComponent<RectTransform>(); 16 var _pivot = _canvasRectTf.pivot; 17 var _sizeDelta = _canvasRectTf.sizeDelta; 18 var _pos = Vector3.zero; 19 _pos.x = (_sizeDelta.x / -2f) + (_sizeDelta.x) * _pivot.x; 20 _pos.y = (_sizeDelta.y / -2f) + (_sizeDelta.y) * _pivot.y; 21 _pos.z = distance; 22 prevCanvasPosition = _canvasRectTf.localPosition; 23 prevCanvasRotation = _canvasRectTf.localRotation; 24 var _matrix = _camera.cameraToWorldMatrix; 25 var _point = _matrix.MultiplyPoint(_pos); 26 _canvasRectTf.localPosition = _point; 27 _canvasRectTf.localRotation = _cameraRot; 28 } 29 } 30 } 31 32 public void BackToPrevPosition() { 33 if (canvas != null) { 34 if (canvas.renderMode == RenderMode.WorldSpace) { 35 var _canvasRectTf = canvas.GetComponent<RectTransform>(); 36 _canvasRectTf.localPosition = prevCanvasPosition; 37 _canvasRectTf.localRotation = prevCanvasRotation; 38 } 39 } 40 } 41}

C#

1using UnityEditor; 2using UnityEngine; 3 4[CustomEditor(typeof(MoveCanvas))] 5public class MoveCanvasInspector : Editor { 6 7 public override void OnInspectorGUI() { 8 base.OnInspectorGUI(); 9 EditorGUILayout.Space(); 10 var moveCanvas = target as MoveCanvas; 11 using (new EditorGUILayout.HorizontalScope()) 12 { 13 EditorGUILayout.Space(); 14 if (GUILayout.Button("Move", GUILayout.Width(80f))) { 15 moveCanvas.MoveToCamera(); 16 } 17 if (GUILayout.Button("Back", GUILayout.Width(80f))) { 18 moveCanvas.BackToPrevPosition(); 19 } 20 EditorGUILayout.Space(); 21 } 22 EditorGUILayout.Space(); 23 } 24}

投稿2016/10/28 22:26

編集2016/10/30 12:43
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2016/10/29 12:26

ご回答ありがとうございます。エディタ拡張のスクリプトを使う方法があるのですね。 インスペクターのエディタ拡張は初めて知ったのでわからないことだらけですが、1番重要なコードは、cameraToWorldMatrixとその下の行辺りだと認識しました。 確かに、教えていただいたコードではCanvasがカメラの中央に寄りませんでした。 そして修正を試みて、cameraToWorldMatrixやMultiplyPointをマニュアルで見たのですが、あまり理解できませんでした。(例えば、カメラ空間って、カメラの位置?カメラの視界?MultiplyPointの引数には、今回の仕様ではどのような位置のベクトルを与えればいいか等)。 もし、お手数でなければこの辺りのコードに関して、ご教授いただけないでしょうか。
退会済みユーザー

退会済みユーザー

2016/10/29 16:57 編集

MoveCanvas のスクリプトを修正しました。まだ、不備があるかもしれません。 座標変換、変換マトリックスがキーなのですが、これらを解説するのはさすがに難しいです。 カメラから見たキャンバスの起点(キャンバス左下隅)となるローカル座標を、カメラのビュー座標系をワールド座標系に変換したもの(_matrix)のMultiplyPoint()メソッドに渡すことで、キャンバスの起点となるワールド座標を得ています。
退会済みユーザー

退会済みユーザー

2016/10/30 09:10

ご回答ありがとうございます。 いただいたコードをそのまま実行するとエラーになってしまうので、「_pos.x = (_sizeDelta.x / -2f) + (_sizeDelta.x) * _pivot.x;」の上に、「var _pos = new Vector3 (0, 0, 0);」を書くという対処で大丈夫ですか? また、「(_sizeDelta.x) * _pivot.x」がcanvasの右端、「(_sizeDelta.y) * _pivot.y」がcanvasの上端の位置を表しているということですか? _matrix.MultiplyPoint()の引数に渡しているposは、キャンバス左下隅ではなく、キャンバスの中央に見えるのですが、いかがですか? 質問が多くなってしまい、すみません。
退会済みユーザー

退会済みユーザー

2016/10/30 09:39

編集しているうちに _pos の宣言を削除してしまったようです。再編集しました。 キャンバスの起点の表現に誤りがありましたね。 キャンバスのpivotを考慮した、キャンバスの起点となる座標を渡しています。 >また、「(_sizeDelta.x) * _pivot.x」がcanvasの右端、「(_sizeDelta.y) * _pivot.y」がcanvasの上端の位置を表しているということですか? そこだけ取り出しても意味はありません。 (_sizeDelta.x / -2f) はキャンバスの左端、 (_sizeDelta.x) * _pivot.x はpivotの値によって移動したx座標の値です。 y座標は、同様に、キャンバスの下端と、移動したy座標の値です。 pivotが(0,0)の場合は、キャンバスの左下隅の座標を渡し、 pivotが(2,4)の場合は、キャンバス左下隅の座標からx座標はキャンバス2枚分、y座標はキャンバス4枚分ずらした座標を渡しています。 pivotがx = 0.5, y = 0.5 の場合のみ、キャンバスの中央の座標を渡していることになります。
退会済みユーザー

退会済みユーザー

2016/10/30 12:07

ご回答ありがとうございます。 私が未熟ゆえにまだ理解できていない箇所もありますが、おおよその流れは理解することができました。 いただいたコードも正常に動作していて、意図したいことができるようになりました。 ご丁寧にご教授くださりありがとうございました。
guest

0

World Spaceで扱うCanvasはエフェクト(パーティクル)のようなもので、
本来はHUD(キャラの上に表示されるHPバーみたいなの)等に利用されるものです。
基本的に3Dオブジェクトと同じ扱いですので、質問文のような用途には向いていません。
質問文のような事をしたいならScreen Spaceに置くのが基本です。

ですので、今回の件を実現したいなら面倒ですがスクリプト書くしかないと思います。
下記のサイトのようなやり方でエディタで処理している最中も動くスクリプトが書けるので、canvasにスクリプトを追加してください。
ExecuteInEditModeを使うと編集中も処理を実行可能

canvasをworldspaceに置いている場合、
スクリプトの内容はupdateでカメラの逆行列をかけるとかすればいいはずです。
(パーティクルみたいなものだから、それだけじゃ上手く動かないかもしれませんが)

追記:
ちょっと実現したいこととかけ離れているかもしれませんが、
「Screen Space - Camera」なら奥行き情報だけ3Dっぽく扱えるので、
もしかしたらこのあたりからいろいろいじれば求めている事を実現できるかもしれません。
Canvas

投稿2016/10/28 01:36

編集2016/10/28 01:56
ishi9

総合スコア1294

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

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

退会済みユーザー

退会済みユーザー

2016/10/28 08:59

ご回答ありがとうございます。 ExecuteInEditModeを知らなかったので勉強になりました。 プログラムで書くしかないのですね。 updateでカメラの逆行列をかけるプログラムに関しては、まだ理解していないので今後勉強したいと思います。 ご教授くださりありがとうございました。
退会済みユーザー

退会済みユーザー

2016/10/30 12:03

すみません、さらに求めていた回答に近い回答をいただいたのでベストアンサーを変更致します。ご教授ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問