10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ScriptableObjectの入れ替えで振る舞いを変える

Last updated at Posted at 2018-02-24

はじめに

 ゲームを作っていて、必殺技の作成等を簡単に行えるようにできないだろうか?ということを考えたのが今回の発端です。そこで、ScriptableObjectにパラメーターとメソッドを定義して入れ替えるだけで挙動を変えれると簡単なのでは?と考えついて試してみたので備忘録として書きます。

最終的に、以下のようになります。
Sample1.gif

上のサンプルでは、ジャンプする挙動と色が変わる挙動をScriptableObjectの入れ替えで行っています。

gifで動かしているプロジェクトは公開しているので、説明読むより触ってみたい!という方はご活用ください。
https://github.com/MizoTake/ChangeBehaviourWithScriptableObject

一連の流れ

 最初に、今回の処理がどういう流れで行われているのか書きます。

まず、gifにあったCubeはSpaceキーを押すとInspectorから代入されたScriptableObjectの振る舞いを実行します。
中身は以下のようになっています。
Cubeに貼られているスクリプトから

ControllerInput.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControllerInput : MonoBehaviour
{
    [SerializeField]
    private Rigidbody _rigid;
    [SerializeField]
    private Behaviour _behaviour;

    public Rigidbody Rigid { get { return _rigid; } }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _behaviour.Move(this);
        }
    }
}

SpaceKeyが押されるとBehaviourというクラスのMoveメソッドを実行します。
次に、そのBehaviourというクラスです。

Behaviour.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class Behaviour : ScriptableObject
{
    public abstract void Move(ControllerInput input);
}

public static class BehaviourExtension
{
    public static void Init(this Behaviour behaviour)
    {
        Debug.Log("Initialize");
    }
}

これは、abstractを宣言しているので基底クラスです。継承先で振る舞いを書いて欲しいメソッドを定義しています。今回は、Moveメソッドになります。
そして、ScriptableObjectクラスを継承しているので継承先のクラスをScriptableObjectにできるようになります。
また、abstractクラスには、そのまま拡張メソッドを追加できるので共通で何かを行いたい場合等に使うと便利です。(今回はTips程度に書いています。)

次にgifの最初にJumpしていたクラスです。

Jump.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Jump : Behaviour
{

    public int Power;

    public override void Move(ControllerInput input)
    {
        this.Init();
        input.Rigid.AddForce(Vector3.up * Power, ForceMode.Impulse);
    }
}

これはBehaviourを継承してMoveの振る舞いを定義しています。そのためgifでは、JumpクラスがInputControllerのInspectorに代入され、Moveが呼ばれるためジャンプをしていました。

ここで便利になるのはScriptableObjectを作成した後、Powerの値を変えることでジャンプの高さも変えることが容易になるという点です。

また、this.Init()で呼び出すことによりabstractの拡張メソッドであるInitが呼ばれます。

ここまでが基本的な一連の流れになります。

次からは+αで便利だと思った部分を書きます。

sample2.gif

これは最初のgifでバラバラに実行されていた、ジャンプの振る舞いと色を変える振る舞いを複合して実行しているものになります。

まず、色を変えるクラスです。

ChangeMaterial.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeMaterial : Behaviour
{

    public Material Target;

    public override void Move(ControllerInput input)
    {
        this.Init();
        input.gameObject.GetComponent<MeshRenderer>().material = Target;
    }
}

ScriptableObjectにした後、InspectorでMaterialを代入しています。そして、Jump同様にInputControllerのInspctorに代入することで動作します。

次に複合させたクラスです。

Composite.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Composite : Behaviour
{

    public Behaviour[] Behaviours;

    public override void Move(ControllerInput input)
    {
        this.Init();
        foreach (var behaviour in Behaviours)
        {
            behaviour.Move(input);
        }
    }
}

中身を見ると何てことはないと思います。配列をInspectorから入れて、for文で一気に実行するというものです。

ただ、Behaviourクラスがあるだけで振る舞いの複合やランダム実行などが簡単に定義でき、Compositeクラス自体もBehaviour継承クラスなので、InputControllerのInspectorに代入するだけで切り替えれるというのは便利だと思っています。

InputControllerに対してCharacterごとの動きを設定していけば同じControllerでも振る舞いが変わるので便利かと思います。ここからRxやDIで読みやすく扱いやすくしていくことも良いと思っています。

以上で今回の記事はすべてになります。
(…ScriptableObjectにメソッドが書けるのが個人的に驚きだった)

また、ScriptableObjectの作成に関しては、個人的に以下の記事がオススメです。
【UnityEditor】ScriptableObjectのアセットを右クリックから作れるようにするエディター拡張

右クリックから作れるようになるので簡単作成できるようになって便利でした!

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?