読者です 読者をやめる 読者になる 読者になる

Unity / VRゲーム開発日記@長崎

Unityを使ったVRのゲーム開発をやってます。

カメラ比率に合わせ、GUIの位置を調整する

黄昏66さんの記事で、
スマフォ毎の解像度合わせて、カメラの比率を自動的に調整する
スクリプトが紹介されていました。

黄昏66 アスペクト比設定[Unity]


こちらのおかげで、比率さえ確定させてしまえば、
どの端末でもほぼ同じようにオブジェクトが表示され
非常に重宝しています。


ただし、Unityの通常のオブジェクトは比率に合わせて
伸縮表示されますが、GUIに関しては、ピクセル単位での値設定になるので、
カメラの比率とは別次元の位置とサイズの単位になります。

そこで、GUIも比率に合わせて伸縮させることができないかと思い、
黄昏66さんのコードを参照させていただき、
想定するピクセルサイズの位置を指定すると、
画面の比率に対してのRectサイズを返却するというクラスを
作成してみました。



比率の計算部分は、ほぼ参照で、
カメラ外のoffset値を付け加えたりしています。

また、広告にGAME FEATのアイコンを利用しているのですが、
こちらのUnityプラグインでのアイコンサイズは、
GUIの設定値とはまた別次元となっており、
通常のGUIの半分の値で設定するような仕様のようなので、
このための半分サイズの値も取れる関数も追加しています。

使い方的には、
コンストラクタ
画面の幅、画面の高さ、横画面かどうか
を渡してやり、

GetRect、GetRectHalfにRectを渡して
補正値をRectで受け取る構造にしています。

以下コードです。

public class GuiScaler
{
	
	#region public property



	#endregion
	
	#region private property

	float _scale;
	Vector2 _offset;
	
	#endregion
	
	#region constructer
	
	public GuiScaler (
		int fixWidth = 640, 
		int fixHeight = 960, 
		bool isPortrait = false
	)
	{
		Calc (fixWidth, fixHeight, isPortrait);
	}
	
	#endregion
	
	#region private method
	
	void Calc (int w, int h, bool portrait)
	{
		 
		float width = portrait ? h : w;
		float height = portrait ? w : h;
		
		float target_aspect = width / height;
		float window_aspect = (float)Screen.width / (float)Screen.height;
		float scale = window_aspect / target_aspect;

		Rect _rect = new Rect (0.0f, 0.0f, 1.0f, 1.0f);
		if (1.0f > scale) {
			_rect.x = 0;
			_rect.width = 1.0f;
			_rect.y = (1.0f - scale) / 2.0f;
			_rect.height = scale;
			
			_scale = (float)Screen.width / width;
		} else {
			scale = 1.0f / scale;
			_rect.x = (1.0f - scale) / 2.0f;
			_rect.width = scale;
			_rect.y = 0.0f;
			_rect.height = 1.0f;
			
			_scale = (float)Screen.height / height;
		}
		
		_offset.x = _rect.x * Screen.width;
		_offset.y = _rect.y * Screen.height;
		
	}
	
	#endregion
	
	#region public method
	

	
	public Rect GetRect (float x, float y, float width, float height)
	{ 
		

		Rect rect 
			= new Rect 
				(
					_offset.x + (x * _scale),
					_offset.y + (y * _scale), 
					width * _scale, 
					height * _scale
				);
		
		return rect;
		
	}
	
	public Rect GetRect (Rect rect)
	{
		return GetRect (rect.x, rect.y, rect.width, rect.height);
	}
	
	public Rect GetRectHalf (float x, float y, float width, float height)
	{
			

		
		Rect rect 
			= new Rect 
				(
					(_offset.x + (x * _scale)) / 2,
					(_offset.y + (y * _scale)) / 2, 
					(width * _scale) / 2, 
					(height * _scale) / 2
				);
		
		return rect;
		
	}
	
	public Rect GetRectHalf (Rect rect)
	{
		return GetRectHalf (rect.x, rect.y, rect.width, rect.height);	
	}
	
	#endregion
	

			
}