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

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

ただいまの
回答率

90.34%

  • Unity

    6020questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1977questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,773

tkmnusr

score 244

前提・実現したいこと

任意のサイズで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で扱います。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

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

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

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

using UnityEngine;

[RequireComponent(typeof(Camera))]
public class MoveCanvas : MonoBehaviour {
    public Canvas canvas;
    public float distance = -10.0f;
    private Vector3 prevCanvasPosition;
    private Quaternion prevCanvasRotation;

    public void MoveToCamera() {
        if (canvas != null) {
            if (canvas.renderMode == RenderMode.WorldSpace) {
                var _camera = GetComponent<Camera>();
                var _cameraRot = GetComponent<Transform>().localRotation;
                var _canvasRectTf = canvas.GetComponent<RectTransform>();
                var _pivot = _canvasRectTf.pivot;
                var _sizeDelta = _canvasRectTf.sizeDelta;
                var _pos = Vector3.zero;
                _pos.x = (_sizeDelta.x / -2f) + (_sizeDelta.x) * _pivot.x;
                _pos.y = (_sizeDelta.y / -2f) + (_sizeDelta.y) * _pivot.y;
                _pos.z = distance;
                prevCanvasPosition = _canvasRectTf.localPosition;
                prevCanvasRotation = _canvasRectTf.localRotation;
                var _matrix = _camera.cameraToWorldMatrix;
                var _point = _matrix.MultiplyPoint(_pos);
                _canvasRectTf.localPosition = _point;
                _canvasRectTf.localRotation = _cameraRot;
            }
        }
    }

    public void BackToPrevPosition() {
        if (canvas != null) {
            if (canvas.renderMode == RenderMode.WorldSpace) {
                var _canvasRectTf = canvas.GetComponent<RectTransform>();
                _canvasRectTf.localPosition = prevCanvasPosition;
                _canvasRectTf.localRotation = prevCanvasRotation;
            }
        }
    }
}
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MoveCanvas))]
public class MoveCanvasInspector : Editor {

    public override void OnInspectorGUI() {
        base.OnInspectorGUI();
        EditorGUILayout.Space();
        var moveCanvas = target as MoveCanvas;
        using (new EditorGUILayout.HorizontalScope())
        {
            EditorGUILayout.Space();
            if (GUILayout.Button("Move", GUILayout.Width(80f))) {
                moveCanvas.MoveToCamera();
            }
            if (GUILayout.Button("Back", GUILayout.Width(80f))) {
                moveCanvas.BackToPrevPosition();
            }
            EditorGUILayout.Space();
        }
        EditorGUILayout.Space();
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/30 18: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 18: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 21:07

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

    キャンセル

0

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/28 17:59

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

    キャンセル

  • 2016/10/30 21:03

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

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Unity

    6020questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1977questions

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