Hack and Play

プログラミングやCG、ゲーム、コンピュータのネタを投稿していくブログ。不定期更新。

UnityのPlaymakerとC#による状態変移の制御について

2014年01月03日 | CG関連

UnityのAssetStoreで販売している、Playmakerを購入しました。

http://www.hutonggames.com/index.html

このPlaymakerは、スクリプトを一切書かなくても、Unityでゲームロジックが組めるということを売りにしていますが、自分の場合は、普段C#でスクリプトを組んでいるので、そのメリットがちょっと見えづらいという点がありました。

いろいろいじってた結果、Playmakerはゲームロジックのひとつである、状態変移に特化しており、その代わりに非同期処理や複数条件での分岐処理(n-stateを含む)を書くのが難しいことが分かりました。

またC#側ではメリットデメリットが逆転している(状態変移を書くと、Update関数内が変移チェック変数でごちゃごちゃする)ので、これらを使い分けると面白いのではないかと考えたわけです。

 

というわけで、自分の勉強もかねて、C#とPlaymaker両方を使って、状態変移の制御を行う簡単なやり方について考えてみました。
内容の理解度に関しては、一通りPlaymakerを触っている人が対象になります。
アルゴリズムについてですが、

  1. PlaymakerからGameObject(Prefab)のインスタンスを作成する。(1秒ごとに生成するループ)
  2. 生成されたGameObjectは一定時間(ランダム性あり)が来たら自己消滅する。その際にPlaymaker側に消滅したことを知らせる(カウンタを増やす)
  3. Playmaker側は一定数の消滅が来たら、生成ループから外れて、自己消滅する

という構成になっています。

まずはPlaymaker側の設定です。適当な空のGameObjectをHierarchyに追加し名前を"CubeControllerFSM"にし、PlaymakerのFSMを作ります。また、ついでにもうひとつ、"CubeOrigin"という名前の空のGameObjectを作っておきます。
シーンに初めてFSMを作った際の名前は、"FSM"になっていますが、それ以降は変わってきますので、この辺はスクリプトを制御する際に他のFSMと混同しないよう、FSMの名前は意識しておいたほうが良いと思います。

一つ目のActionはCreate Objectになります。このActionは実行時にGameObject(Prefab可)のインスタンスを作成する機能を持っています。Game Objectの箇所には生成したいGameObjectを、Spawn Pointには生成する原点となるGameObjectを設定します。
Store ObjectにはPlaymakerのVariablesの変数と紐付けできますが、増減するものに対しては使いづらいので、今回は無視します。
スクリーンショットでは既にCubeというGameObjectがつけられていますが、後でそのPrefabについて説明します。

二つ目のActionはInt Compareです。これはVariables中のint型の変数が、ある一定の数値未満(Less than)、同値(Equal)、それよりも大きい(Greater than)に、処理を分岐する機能です。

ここでは、IsNotOVERとIsOVERというカスタムEventを作っていますが、ラベル付けの役割だけですので、名前は何でも良いです。
IsNotOVERのほうは、WaitのActionに紐付けされ、IsOVERのほうはDestroy Selfに紐付けされています。
今回は変数にNumOfDestroyという変数を作っています。Variablesタブから変数を作っておきましょう。作ったらInteger1にNumOfDestroyをセットしましょう。

三つ目のActionはWaitです。あまり説明することは少ないですが、Waitは結構重要で、他のActionのLogicのうち、*** Changed系のActionがある場合は、これをかまさないとうまく動かないケースがあります。また、今回はPlaymakerが無駄にインスタンスを生成しないように、Waitを入れています。

このActionは一つ目のCreate ObjectのActionと紐付けされており、ループ処理が行われます。

最後のActionは、Destroy Selfになります。C#で言うDestroy(gameObject)を呼ぶのと同じ機能です。これはそのままなので、画像は省略します。

さて、今度はC#のスクリプト作りです。

名前は何でも良いですが、この記事では"FSMListner"というスクリプトにしています。コードは以下のとおりです。スクリプト自体は、上記の2の機能そのものです。

using UnityEngine;
using System.Collections;
using HutongGames.PlayMaker;

public class FSMListner : MonoBehaviour {

    PlayMakerFSM fsm;
    public string PlaymakerObject;
    public string FsmName;
    public string ParamName;

    float lifetime;

    // Use this for initialization
    void Start () {
        fsm = GameObject.Find(PlaymakerObject).GetComponent<PlayMakerFSM>();
        if(fsm == null && fsm.name != FsmName) {
            Debug.Log("FSMListner: " + PlaymakerObject + " is not found!");
        }
        lifetime = 1.0f + Random.value;
        Vector3 vec = new Vector3();
        vec.x = (Random.value - 0.5f) * 2f;
        vec.y = (Random.value - 0.5f) * 2f;
        gameObject.transform.position = vec;
    }
    
    // Update is called once per frame
    void Update () {
        lifetime = lifetime - Time.deltaTime;
        if(lifetime < 0.0f) {
            if(fsm != null) {
                fsm.FsmVariables.GetFsmInt(ParamName).Value += 1;
            }
            Destroy(gameObject);
        }
    }
}

Start時に自己消滅までの時間を設定し(lifetimeがそれです)、生成位置をランダムに設定しています。また、

fsm = GameObject.Find(PlaymakerObject).GetComponent<PlayMakerFSM>();

の行で、PlaymakerFSMクラス(Playmakerの実体のクラス)から、特定のFSMを抽出できます。
Update関数内では、時間経過による処理のプログラムを書いています。Destroyを呼ぶ前の行の、

fsm.FsmVariables.GetFsmInt(ParamName).Value += 1;

で、FSM内のVariablesにアクセスし、値を書き換える(インクリメント)しています。

スクリプトは保存して、Assetにおいておきましょう。

次にCubeのPrefabとHierarchyについてです。

HierarchyにCubeのGameObjectを作成し、そこに"FSMListener"のスクリプトをD&Dし、CubeをAssetに追加し、Prefab化しておきます。一度Prefab化が終わっていれば、HierarchyからCubeを削除しても大丈夫です。
Inspectorの"FSMListener"の項目に、public変数がありますので、それぞれ、

Playmaker Objectには、"CubeControllerFSM"、
Fsm Nameには、"FSM"、
Param Nameには、"NumOfDestroy"

を忘れずに入れておきましょう、すべて文字列になっていますので、手打ちで文字列を
入力してください。

これが終わったら、再度CubeのPrefabを、Playmakerの一つ目のCreate ObjectのGameObjectにセットしておきましょう。

終わったら、実行して、どんな動作をするか確認しましょう。

実行中はCube(Clone)が生成され、消えては生成され、という具合になり、最後はCubeがすべて消え、CubeControllerFSMも消滅するという挙動になると思います。

さて、今回はPlaymakerとC#両方の操作で互いに影響するコードについて解説をしました。
今後もこのように、互いのメリットデメリットを補完することにより、より楽しいUnityコーディングができるようにいろいろ考えていこうと思います。


最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。