【Unity】UniRxで列数、行数から動的にセルサイズを調整するGrid Layout Groupを実現する

f:id:Kanchi0914:20200726020736g:plain

Unityのレイアウト用コンポーネントの1つにGrid Layout Groupがあります。 名前の通りグリッド、もといエクセルのような表形式でオブジェクトを配置する場合に使うためのコンポーネントですが、個人的にはいまいち使い勝手が悪いと感じています。Grid Layout Groupでは、基準がCell Sizeで、列数、行数はCell Sizeを基に決定される仕様となっているので、行数、列数を基準にCell Sizeを決定するということがエディタ上では難しいからです。Vertical LayoutやHorizontal Layoutでは親のサイズに合わせて子のサイズを動的に決定してくれるので、それに比べると‥‥という感じです。 一応Constraintの値をFixed Column Sizeなどに変えると列数、行数を自由に決めることはできますが、これは本当に列数、行数を固定するだけで、それに応じてセルのサイズを動的に決定してくれたりはしません。

結局のところ、「〇行〇列の表」をGrid Layout Groupを使って作ろうとすると、Item Sizeを毎度いい感じに調整するしかないというわけです。で、これを毎回設定するのは面倒なので、行数と列数を指定すると自動的にセルのサイズを調整してくれるスクリプトを書いてみました。

gistaf937e71da132d53ed8290f4fd27e25a

セルサイズの変更はUpdate関数内でやってもいいのですが、せっかくなのでUniRxを使って値が変更されたときのみ変更するようにしています。

gameObject.ObserveEveryValueChanged(_ => rectTransform.sizeDelta).Subscribe(_ => UpdateCellSize());
gameObject.ObserveEveryValueChanged(_ => gridLayout.spacing).Subscribe(_ => UpdateCellSize());
gameObject.ObserveEveryValueChanged(_ => gridLayout.padding.GetType().GetProperties()).Subscribe(_ => UpdateCellSize());

UniRxはご存じの方も多いと思いますが、以前紹介したC#のイベントをUnity向けによしなにやってくれるアセットで、今回の場合のように特定のプロパティの値を監視し、値が変更されたときに特定のメソッドを呼び出したいという処理にはピッタリだと思います。

github.com

UniRxでは色々なことができるっぽいですが、全部を使いこなすのは自分には難しそうです。ただ今回のように値の変更を監視するだけであれば、以下の感じで書けるので楽だと思います。

gameObject.ObserveEveryValueChanged(_ = 値を監視したいプロパティ).Subscribe(_ => 呼び出したいメソッド)

難点として上記スクリプトでは rectTransform.sizeDelta を基準にセルサイズを決定しているので、AnchorにStretch(青色のやつ)を含む可変サイズのものを設定すると正しく動作しないという点があります。Stretchの場合、sizeDeltaはマイナスの値を取りうるからです。 個人的な事情で最近RectTransformのあれこれについて勉強してるので、そのうちその辺について記事を書くかもしれません。詳しいことはそちらで。それでは。