本記事は「MIXI DEVELOPERS Advent Calendar 2024」の19日目の記事です。
はじめに
MIXIで開発本部 クライアントエンジニアグループとしてとあるゲームのクライアントエンジニアをやっています太田です。
今回はUnityでUI配置にSplinesを導入した取り組みについて話します。
Splinesツールとは
Unity 公式ドキュメント
UnityのSplinesツールは、曲線やパスを作成、編集、および操作するための強力なツールセットで、直感的に空間内のオブジェクトを配置したり、動きを制御したりすることができます。レベルデザイン、アニメーション、UI操作など多くの場面で活用可能です。
Splines API
またAPIも提供されていて、スプラインを利用した動的なパス生成やオブジェクトの配置、カスタマイズされた動きの制御を可能にします。
SplineInstantiateを使って線上に等間隔にオブジェクトを配置する
SplineInstantiateを使って線上に等間隔、またはランダムにオブジェクトを配置することが可能です。Bake Instancesボタンを押すと自身の子にPrefabが生成されます。
ただし導入しているSpline2.6.1ではBakeInstancesを押すとコンポーネントが剥がれるという事象が発生しているので、再配置をする場合はコンポーネントを貼り直し再設定する必要があります。(おそらく仕様)
生成時の命名指定やTransformの指定が出来ないこともあり、2DUI配置ツールとして使うには少し不便です。
Splineをコード上から操作する
private static IReadOnlyList<Vector3> CalcPlaceOnSpline(SplineContainer container, Spline spline)
{
var startOffset = 0.2f; // スプライン上の実質的な始点
var endOffset = 0.8f; // スプライン上の実質的な終点
var distance = 100f; // 区間の距離
if (endOffset < startOffset || distance <= 0f)
{
return Array.Empty<Vector3>();
}
// 個数分中間点を置く
var list = new List<Vector3>();
var fromT = startOffset;
// 始点は必要距離を満たさなくても置く
list.Add(container.transform.TransformPoint(spline.EvaluatePosition(startOffset)));
while (fromT < endOffset)
{
// 指定距離だけ進んだ位置を取得
var localPosition = spline.GetPointAtLinearDistance(fromT, distance, out var resultPointT);
// ワールド座標に変換
var worldPosition = container.transform.TransformPoint(localPosition);
list.Add(worldPosition);
// 次の位置に進む
fromT = resultPointT;
}
return list;
}
線上に等間隔で配置するpointを返す関数を用意しました。
UIを配置する際にはSpline上の実質的な始点と終点も調整できるようにした方が良いでしょう。Splineの始点と終点にUIを配置し、始点を基準に等間隔にオブジェクトを配置すると被りが発生するためです。(↓のように)
エディタウィンドウでパラメーターを拡張する
GUIを使用しパラメーターをより調整しやすいものにしましょう。
ここは用途によって分かれると思いますが、自分はエディタウィンドウで実装しています。
Spline.Changed:イベントを使用してシーン上のSplineが編集されたら即再計算するようなロジックを組むのも便利です。
まとめ
SplinesツールはUIの配置ツールとしても、とても便利なツールです。
特に等間隔で置く系のUIを、出来る限り間隔はプログラム的に制御したいが曲線自体はビジュアル的に操作したい時などに導入してみてはいかがでしょうか。