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

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

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

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

Unity

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

Q&A

解決済

2回答

8759閲覧

【Unity】カメラ描画位置をrect(x,y,width,height)指定しているスクリプトの解説をお願いしたいです

unity_level1

総合スコア8

C#

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

Unity

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

0グッド

0クリップ

投稿2020/06/03 11:29

前提・実現したいこと

■開発言語:C#
■開発ツール:Unity 2019 3.7f
■参照ブログ:https://pengoya.net/unity/aspect/
■実現したいこと
・本スクリプトの理解
・rect(x,y,width,height)の使い方についてしっかりと理解

■スクリプトの内容
スマホの機種などで、アスペクト比が変化した際にも、指定しておいたアスペクト比の範囲は固定します

■現状の認識

Unityリファレンスを確認すると、Rect (float x, float y, float width, float height);と記載があり
位置と大きさから矩形を作成する関数という認識をしております。

矩形を作成する基準点x
矩形を作成する基準点y

上記で矩形の配置される位置(x,y)座標を決め、その後、

矩形の幅width (右横へ広げる)
矩形の高さheight (左横へ広げる)

を指定し、矩形の大きさを決めるというところまでは確認しております。

しかし、私のrectの理解がちんぷんかんぷんのため、スクリプトを理解できておりません。

スクリプトの下記部分

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

①float bgScale = height / Screen.height;
②float camWidth = width / (Screen.width * bgScale);
③cam.rect = new Rect((1f - camWidth)/2f, 0f, camWidth, 1f);

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

上記では、
①固定の高さ/現在の高さ=固定の高さと現在の高さの差分の比率(aとする)
②固定の幅/現在の幅×a=高さがaのときの幅の比率

という理解をしたとき、

・質問1
③のcam.rect = new Rect((1f - camWidth)/2f, 0f, camWidth, 1f);で
『(1f - camWidth)/2f』として、x座標を出しているのですが、なぜこのような式になるのでしょうか?
1fとは?
なぜ1f‐camWidthなのか
なぜ1f‐camWidthを2fで除算するのか

・質問2
第二引数の0fはなぜ0fになるでしょうか

・質問3
第三引数のcamWidthは高さがaのときの幅を比率として取っている認識で良いのでしょうか?

・質問4
質問3の認識が正しい場合、なぜこの値はbgScale (幅aに対する高さ)にならないのでしょうか?

Unity上の挙動としては、アスペクト比を変化させても問題なく描画されております。

上記質問につきまして、うまく質問がまとめられず申し訳ございませんが、ご教示のほどよろしくお願いします。

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class camera2 : MonoBehaviour
{

private Camera cam; // 固定したい表示サイズ [SerializeField] private float width = 16f, height = 9f; // 画像のPixel Per Unit [SerializeField] private float pixelPerUnit = 100f; void Start() { float aspect = (float)Screen.height / (float)Screen.width; //表示画面(現在)のアスペクト比 float bgAcpect = height / width; //理想とするアスペクト比 Debug.Log(aspect); Debug.Log(bgAcpect); // カメラコンポーネントを取得します cam = GetComponent<Camera>(); // カメラのorthographicSizeを設定 cam.orthographicSize = (height / 2f / pixelPerUnit); if (bgAcpect > aspect) { float bgScale = height / Screen.height; // viewport rectの幅 float camWidth = width / (Screen.width * bgScale); // viewportRectを設定 cam.rect = new Rect((1f - camWidth)/2f, 0f, camWidth, 1f); Debug.Log(cam.rect); } else { float bgScale = aspect / bgAcpect; Debug.Log(bgScale); // カメラのorthographicSizeを縦の長さに合わせて設定しなおす cam.orthographicSize *= bgScale; Debug.Log(cam.orthographicSize); // viewportRectを設定 cam.rect = new Rect(0f, 0f, 1f, 1f); } } // Start is called before the first frame update void Awake() { } // Update is called once per frame void Update() { }

}

試したこと

Rect (float x, float y, float width, float height)

上記の座標を変更させると、配置されたオブジェクトが半分だけ表示されたりすることは確認しました。
また、float width, float heightが1.0f以上になるとGameビューに移される範囲が変わらず、
0.5などにすると半分の値になることを確認しました。
※ここから、float width, float heightは比率1fがMAXの値になるのかなという予想はしております。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

まず公式リファレンスを参照しましょう。
UnityEngine.Rect - Unity スクリプトリファレンス
通常のRectの各変数の仕様はこれで分かると思います。

そしてCamera.rectの方を見ると、
Camera-rect - Unity スクリプトリファレンス
「画面座標の正規化座標でどこにカメラが描画されるか。0 (左/下)から 1 (右/上) 範囲の値。」とあります。
お察しの通り、ピクセル数や3D座標ではなく、正規化座標(画面サイズを1とした時の比)というのがポイントです。

アスペクト比の固定の場合、「高さを基準に幅を求める」「幅を基準に高さを求める」のいずれかが考えられます。
今回質問で上げているコードは「高さを基準に幅を求める」の方なので、cam.rectの第2引数は0、第4引数は1になります。
(絶対に高さは画面いっぱいになる、ということ)

幅の計算を理解するに当たり、実際の値で考えてみましょう。
実際に表示させたいサイズ: width=1080, height=1920(9:16)
端末の画面のサイズ: Screen.width=1200, Screen.height=1920(10:16)
だったとすると、
bgScale = 1920 / 1920 = 1
camWidth = 1080 / (1200 * 1) = 0.9
となります。つまり「表示される横幅は画面サイズの90%分」と分かります。(cam.rectの第3引数が決まる)

もしこの画面を左寄せで表示させたい場合、cam.rectの第1引数は0で構いません。この場合、画面右端にのみ黒帯が入ります。
ですが今回、描画範囲を中央に表示させたい(左右に黒帯を入れたい)です。
ということは、この「片方の黒帯の幅」を求めればいいことになります。

表示領域が画面の90%ということは、黒帯(左右合計)の幅は画面の10%です。(これが1 - camWidth
欲しいのは片方分なので、半分にすると5%になります。(これが/ 2.f
なので(1f - camWidth)/2fでcam.rectの第1引数が求められると分かります。

投稿2020/06/04 00:57

sakura_hana

総合スコア11427

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

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

unity_level1

2020/06/05 16:29

sakura_hanaさん お返事が遅くなってしまい申し訳ございません。 本質問に詳しくご教示くださりありがとうございます。 今回、一番理解できていなかった(1f - camWidth)/2fの理由がすっきりしました。 今回は「高さを基準に幅を求める」ため、 new Rect((1f - camWidth)/2f, 0f, camWidth, 1f)となるとのことですが、 反対に「横を基準に幅を求める」際には bgScale = width / Screen.width camWidth = height / (Screen.height * 1) new Rect(0f, (1f - camWidth)/2f, 1f, camWidth) という処理になるのでしょうか? また、本スクリプトでは、事前にアスペクト比を固定値private float width = 16f, height = 9f;にしているのですが、このようにすると16:9で固定はされるのですが、ゲーム画面(正規化座標でよろしいでしょうか)以外は黒枠が表示されてしまいます。 こちらの固定値をprivate float width = Screen.height , height = Screen.width;のようにし、現在の画面サイズを変数に格納することで、端末が変化した際に黒枠なしのフル画面表示にすることは可能なのでしょうか? 上記が実現可能でしたら、そのスクリプトをご教示いただくことなどは可能でしょうか。 sakura_hanaさんのご説明がかなりわかりやすかったため、もし可能でしたら追加の質問もご教示いただけますと非常に助かります。 重ねての質問で大変申し訳ございませんが、何卒よろしくお願いいたします。
sakura_hana

2020/06/06 05:12

>横を基準に幅を求める 理論上は多分それでいいと思います。(変数名は意味に合わせて変えるべきかと思いますが) >widthとheightを画面サイズに合わせる これはアスペクト比を固定する(=指定アスペクト比が違ったらカメラサイズを調整する)為のスクリプトなので、固定させる必要が無いのであればそもそもスクリプトは何も要りません。(カメラは何もしなければ勝手に画面サイズに合います)
unity_level1

2020/06/06 08:17

sakura_hanaさん 追加の質問に対してご回答いただきありがとうございました! 追加の質問につきましても承知いたしました! ご教示いただきました内容で引き続き試してみたいと思います。 詳しく教えていただき助かりました。 ありがとうございました。
guest

0

fが付いてる数値は、float型の数値を表してます

cam.rect = new Rect((1f - camWidth)/2f, 0f, camWidth, 1f);

は、
cam.rect = new Rect((1.0 - camWidth)/2.0, 0.0, camWidth, 1.0);
と同じ意味です

投稿2020/06/03 11:37

y_waiwai

総合スコア88024

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

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

unity_level1

2020/06/03 12:15

y_waiwaiさん ご回答いただきありがとうございます。 私の質問がわかりづらく申し訳ございません。 cam.rect = new Rect((1f - camWidth)/2f, 0f, camWidth, 1f); この計算や引数の意味が理解できていない状況です。 本スクリプトでは、カメラの描画開始座標を決めたあと、ゲーム画面に表示される幅を横と縦の比率で指定しているように見受けられるのですが、x座標をなぜこのような計算で求められるのか、また、y座標はなぜ0になるのかについてに理解ができていない状況になります。 (rectの認識が違っている可能性がございます。。。) おそらく最終的には数学的な知識が足りていないため理解できないという結果になる気がしております。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問