UnityのSplinesをEditorで操作する【Unity】

はじめに

Unity 2022.1から入っている新機能 Splines を使ってみたかったので、とりあえず 触ってみることにしました。これからゲーム等に活用していければ嬉しいですね

Demo

Runtime及び Editor上で Splinesのknot(各ポジション)を増やせるクラスの作成や調査を行いました。

環境

  • Unity 2022.2.0b13
  • Splines 2.0.0
  • Odin

Splineとは

公式サイトより

パスに沿ってオブジェクトと動作を生成し、軌跡を作成し、形状を描画します。

UnityのSplines デモシーンの確認

どんなものなのかデモを見てみないと分からないので、確認してみます。

サンプルの導入方法

  1. Unity Package Managerを開く
  2. Packgesの Unity Registry を選択 (画像の1)
  3. 検索欄で Splinesで検索して出てきたものを選択
  4. タブの中から Sample を選択 (画像の2)
  5. サンプルデータをimportする(画像の3)

サンプルシーンの動作確認

  1. Loft Road

道が今までできなかった曲線を描いている静止デモ

2 . Spline Animate

1の道路の上にCubeを載せてアニメーションで動くようにしているデモ

3 . ExtrudeSpline

Meshデータを Splineを使って動かすデモ

4 . SplineInstantiate

Treeや Grassなども曲線に配置している 静止デモ

5 . SplineData and Generation

Spline周りのAPIを使用して生成するデモ

ReadMeより

plineDataSplineUtilitySplineEditorUtility API を使って、シーン上にスプラインベースのオブジェクトをプロシージャルに生成する

6 . Area Generation

5とほぼ同様?のデモ

7 . Nearest Point

任意の場所からスプライン上の最も近い点を見つけて移動するデモ

8 . Curvature

スプライン曲率の可視化しているデモ

9 . Embedded Spline

スプラインをコンポーネントに埋め込んで動かしているデモ

10 . GPU Evaluation

GPU上で Splineの計算を行うデモ

Spline関連クラスについて

クラスイメージは以下のようになっています。

SplineContainer

Inspectorに表示されている Splineは SplineContainer クラスになっています。

基本これが親クラスです。

Spline

Spline0 と書かれている部分は Spline になっていて、画面に表示されるポイントの箱(リスト)です

BezierKnot

各ポイントを Knot と呼ばれる位置や回転情報などの情報です。

SplineのKnotの操作

追加

それでは Editor上やRuntime上で Knotを増やしていけるようにしたいと思います。 上記のクラス関係から 何もない状態からでも追加できるようにします。

まず SplineContainerが追加されているかを判断するために、以下のif文を入れます。

if (splineContainer.Splines.Count != 0) return;

次に 追加したい SplineContainerを指定して、以下の処理で Splineを追加していきます

splineContainer.AddSpline();

最後に Knotを追加します

splineContainer.Spline.Add(knot);

最終的なスクリプトは以下のようになりました。

    public class SplineKnotExtra : MonoBehaviour
    {
        [SerializeField] private List<SplineContainer> movePointList;

        #region EditorからSplineを操作する

        /// <summary>
        /// Knotを一つランダム値を一つ追加
        /// </summary>
        private static void AddKnotAtRandomValue(SplineContainer splineContainer, int addSplines)
        {
            for (var splineCount = 0; splineCount < addSplines; splineCount++)
            {
                var knot = new BezierKnot(Random.Range(-50f, 50f), Random.Range(-50f, 50f), Random.Range(-50f, 50f), Random.rotation);
                splineContainer.Spline.Add(knot);
            }
        }

        private static void AddKnotAt2DLineRandomValue(SplineContainer splineContainer, int addSplines)
        {
            for (var splineCount = 0; splineCount < addSplines; splineCount++)
            {
                var knot = new BezierKnot(Random.Range(-50f, 50f));
                splineContainer.Spline.Add(knot);
            }
        }

        /// <summary>
        /// SplineのNodeを任意の数を追加
        /// </summary>
        private static void AddSplineKnot(SplineContainer splineContainer, int addSplineCount)
        {
            if (splineContainer.Splines.Count != 0) return;
            for (var addSplineCountIndex = 0; addSplineCountIndex < addSplineCount; addSplineCountIndex++)
            {
                splineContainer.AddSpline();
            }
        }

        #endregion

        [Button("Spline Knowのランダム追加")]
        private void AddRandomKnot(int addKnowCount)
        {
            foreach (var splineContainer in movePointList)
            {
                AddSplineKnot(splineContainer, addKnowCount);
                AddKnotAtRandomValue(splineContainer, addKnowCount);
            }
        }

        [Button("2D line Knowのランダム追加")]
        private void AddRandom2DLineKnot(int addKnowCount)
        {
            foreach (var splineContainer in movePointList)
            {
                AddSplineKnot(splineContainer, addKnowCount);
                AddKnotAt2DLineRandomValue(splineContainer, addKnowCount);
            }
        }

        [Button("Spline Know Reset")]
        private void RemoveAllKnot()
        {
            foreach (var splineContainer in movePointList)
            {
                splineContainer.RemoveSpline(splineContainer.Spline);
            }
        }
    }

取得

以下の画像のように任意のSplineの最後のknot情報を取得したいときは以下のようにして取得します。

_splineContainer.Splines[_splineIndex].Knots.Last();

参考サイト

nekojara.city

docs.unity3d.com