Unity初心者です。
現在2Dでゲームを作成しているのですが、綺麗にレイアウトを並べたい時には「LayoutGroup」を多用してきました。(HorizontalLayoutGroupとか)
なんか調べるとUnityのLayoutGroupは評判が良くないみたいでしたが、お手軽ですごい便利に使っていました。座標指定よりレスポンシブに作ることが出来ますし。
しかし、HorizontalLayoutGroupを使用して横(PosX)は調整したいが、高さ(PosY)は自分で決めたいみたいな時があって対応に苦労しました。
というのもHorizontalLayoutGroupを使っているとPosYは自動で決められてしまうからです。

↑Upper、Middle、Lowerから選ぶしかない
とりあえず面倒だったので、自作でレイアウトを揃えられるようにしました。作ったソースなどを記載してみたいと思います。
自作のLayoutGroupで実現したい動作

↑オブジェクトの水平位置を3分割しつつ、高さは不揃えにする
前述したとおりHorizontalLayoutGroupを使うと水平方向に均等に配置することは出来るのですが、高さが勝手に決まるので上記要件を実現できませんでした。
ちなみにLayoutGroupにはGridLayoutGroupというものがあります。
GridLayoutGroupに空のゲームオブジェクトを間に挟んでいけば実現できそうでしたが、流石に保守性が悪くなりそうなので辞めました。
自作のLayoutGroupのソースコード
「自作!!」とかカッコイイことは言いましたが、単純に親要素の大きさを分割して並べているだけの、しょぼいコードです。
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private float width;
private float height;
private int childCount;
void Start()
{
// 親オブジェクトの高さと幅を取得
RectTransform rect = GetComponent<RectTransform> ();
width = rect.sizeDelta.x;
height = rect.sizeDelta.y;
childCount = 0;
}
void Update()
{
// 要素数が変更になったら並びを整える
if(childCount != this.transform.childCount)
{
SetLayout();
}
childCount = this.transform.childCount;
}
private void SetLayout()
{
for (int i = 0; i < this.transform.childCount; i++){
// 子オブジェクトを均等間隔に並べる
Transform child = this.transform.GetChild(i);
float left = width * (i + 1) / (this.transform.childCount+ 1) - width / 2;
float top = height * (i + 1) / (this.transform.childCount+ 1) - height / 2;
child.localPosition = new Vector3(left, top, 0);
}
}
}最初に親要素の横幅と縦幅を取得します。
上記で取得した値を子の数で割った値を算出し、positionを変更してあげているだけです。
一応自動で変更されるようにしたかったのでUpdateで呼び出しをする形にしました。
Updateで毎回計算するのもどうかと思ったので、子要素の数に変更がなければ何もしないようにしています。
後は必要になるとしたら
- Spanを指定できるようにする
- オプションで左側から並べられるようにする(Alignment Left)
くらいですかねー。
LayoutGroupを複数使用すれば調整可能
そもそも何故自作で作ることにしたかを書いておこうと思います。
元々は自作するつもりがなくて、LayoutGroupを使用したまま要件を満たせないかを考えてきました。
結論から言うと同じような悩みを持っている人がいて、やり方が公開されていました。
(teratailの質問です)
Unity の HorizontalLayoutGroup を使うと Pos Y がいじれなくなるのを回避したい。
https://teratail.com/questions/194411
こちらのやり方を真似しようと思ったのですが、「間にもう1階層増やす」という方法が取られていて、LayoutGroupを重ねる方法が紹介されていました。
正直LayoutGroupを階層にしていくのは構造上よろしくないような気がしたので、今回自作をしてみました。
ただ、見ていくと「HorizontalLayoutGroup」を継承して「SetLayoutVertical」メソッドを空でオーバーライドしてあげるという方法も記載されていました。
こちらを使用する方法も良い気がしますね。
(階層表示の回答を見て閉じてしまったので、見つけるのが遅かった…)


コメント