はじめに
この記事はUnity Advent Calendar 201817日目の記事の代理投稿です!16日目は@namazuchinさんのUnityでTwilioを利用して固定電話に架電するでした。
iPhone X/XSのSafeAreaに対応したUnityアセットをリリースしました🎉
— Nakaji Kohki / リリカちゃん💜💊 (@nkjzm) 2018年11月20日
1. iOSでの実行時にCanvasサイズ調整機能
2, Unityエディタ上でのプレビュー機能
3. GameビューにiPhone X/XS用サイズの追加機能
ぜひ使ってみてください!
nkjzm/Unity-SafeAreaCanvashttps://t.co/If9zYqHrqG #Unity #SafeArea pic.twitter.com/9EFPkf1qGf
先日、iPhone X/XSのSafeAreaに対応したOSSをリリースしました。
今回は、使い方の紹介と、実装の解説をしていこうと思います。
リポジトリ: https://github.com/nkjzm/Unity-SafeAreaCanvas
使い方
UnityのSafeArea対応に関する記事は、実機での反映のみに言及したものが多いですが、実際に開発する際には、SafeAreaが適用された場合の見え方をプレビューしながら進めたいと感じました。そのため、プレビューと実機対応の両方に対応したのが今回のアセットになります。
-
Releasesから
SafeAreaCanvas.unitypackage
をダウンロードしてください。 - プロジェクトに
SafeAreaCanvas.unitypackage
をインポートしてください。 - シーンに
SafeAreaCanvas/Prefabs/SafeAreaCanvas.prefab
をドラッグしてください。
あとはSafeAreaCanvas.prefab
の子のSafeArea
以下にUIなどを作成・配置していけば良いです。
その状態でGameビューのサイズを変更すると、自動的にSafeAreaの余白が更新されます。
また、実機でも同じように動作するはずです。
実装
シンプルな実装なのですが、簡単に紹介していきます。
iOS実機実行時のCanvasサイズ調整機能
using UnityEngine;
namespace nkjzm.SafeAreaCanvas
{
[ExecuteInEditMode()]
public class SetCanvasBounds : MonoBehaviour
{
public RectTransform panel;
Rect lastSafeArea = new Rect(0, 0, 0, 0);
void ApplySafeArea(Rect area)
{
panel.anchoredPosition = Vector2.zero;
panel.sizeDelta = Vector2.zero;
var anchorMin = area.position;
var anchorMax = area.position + area.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
panel.anchorMin = anchorMin;
panel.anchorMax = anchorMax;
lastSafeArea = area;
}
void Update()
{
if (panel == null) { return; }
Rect safeArea = Screen.safeArea;
#if UNITY_EDITOR
if (Screen.width == 1125 && Screen.height == 2436)
{
safeArea.y = 102;
safeArea.height = 2202;
}
if (Screen.width == 2436 && Screen.height == 1125)
{
safeArea.x = 132;
safeArea.y = 63;
safeArea.height = 1062;
safeArea.width = 2172;
}
#endif
if (safeArea != lastSafeArea)
{
ApplySafeArea(safeArea);
}
}
}
}
panel
のサイズがSafeAreaのサイズと一致するようになっています。
Unity2017.3くらいから、Rect safeArea = Screen.safeArea
でsafeAreaのサイズが取得できるようになりました。その値をApplySafeArea
関数でpanel
に反映させています。
void ApplySafeArea(Rect area)
{
panel.anchoredPosition = Vector2.zero;
panel.sizeDelta = Vector2.zero;
var anchorMin = area.position;
var anchorMax = area.position + area.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
panel.anchorMin = anchorMin;
panel.anchorMax = anchorMax;
lastSafeArea = area;
}
UIのAnchorサイズをSafeAreaに合わせて更新しています。AnchorはVector2
型で各値が0-1の範囲で表現されています。RectTransform
の左下が(0,0)
で右上が(1,1)です(下記画像参照)。Areaの座標を代入した後にScreen.width
やScreen.height
で割ることで、0-1に正規化しているイメージです。
ちなみにScreen.safeAreaはRect型として返ってきます。矩形を表現するクラスで、Vector2
型のPosition
にx
やy
などで直接アクセス出来たりする便利なクラスなのですが、Rect
本来の座標系は左上が原点である点に注意してください。
Unityエディタ上でのプレビュー機能
上記コードでiPhone X/XSを判定する部分がこちらです(めちゃめちゃハードコーディングですみません)。
#if UNITY_EDITOR
if (Screen.width == 1125 && Screen.height == 2436)
{
safeArea.y = 102;
safeArea.height = 2202;
}
if (Screen.width == 2436 && Screen.height == 1125)
{
safeArea.x = 132;
safeArea.y = 63;
safeArea.height = 1062;
safeArea.width = 2172;
}
#endif
エディタ上ではScreen.safeArea
が値を返してくれないため、自前で値を入れています。大した処理じゃないのでUpdate()
でやっています(ApplySafeArea()
は繰り返し呼ばれません)
逆に言うと、エディタプレビュー機能はこんなに短いコードのみで対応しています。簡単ですね。
GameビューにiPhone X/XS用サイズの追加機能
インポート時、GameビューのサイズにiPhone X/XSの設定を追加する機能を入れています。Build TagetをiOSにしている場合はすでに含まれているので不要なのですが、別プラットフォームの設定で作業をする場合などに便利です。
実装にはunity-GameViewSizeHelperというアセットを利用させていただいています。「ScriptからGameViewSizeを作成、また設定するヘルパークラス」とあり、まさにやりたいことでした。
using UnityEditor;
using UnityEngine;
namespace nkjzm.SafeAreaCanvas
{
public class GameViewSizeAdder
{
[InitializeOnLoadMethod]
static void Init()
{
var wide = new GameViewSizeHelper.GameViewSize
{
type = GameViewSizeHelper.GameViewSizeType.FixedResolution,
width = 2436,
height = 1125,
baseText = "iPhone X/XS Landscape"
};
var tall = new GameViewSizeHelper.GameViewSize
{
type = GameViewSizeHelper.GameViewSizeType.FixedResolution,
width = 1125,
height = 2436,
baseText = "iPhone X/XS Portrait"
};
GameViewSizeHelper.AddCustomSize(GameViewSizeGroupType.Standalone, wide);
GameViewSizeHelper.AddCustomSize(GameViewSizeGroupType.Standalone, tall);
GameViewSizeHelper.AddCustomSize(GameViewSizeGroupType.Android, wide);
GameViewSizeHelper.AddCustomSize(GameViewSizeGroupType.Android, tall);
}
}
}
[InitializeOnLoadMethod]
というアトリビュートを使って自動的にサイズ追加をしています。コンパイルが終わった後などにエディタ上で呼び出されるものです。複数回AddCustomSize
を呼び出していますが、GameViewSizeHelper
では同一の設定は追加されないようになっているみたいなので、大丈夫でした。ありがたいですね!
iOSと同じプロジェクトで使う可能性が高そうなStandAloneとAndroidの対応を入れています。
最後に
『Unity-SafeAreaCanvas』は、私がSafeArea対応で消耗した時に作成したアセットです。ぜひ多くの方に使っていただきたいですし、気になった点のIssueやPull Requestもお待ちしております!
Unity Advent Calendar 201818日目の記事は@kaiware007さんのThetaのストリーミング映像をリアルタイムにリフレクションさせてみたです。