3
1

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 1 year has passed since last update.

PlayMaker勉強会 第1回 ~多対多接続はやめよう編~

Last updated at Posted at 2023-06-18

PlayMaker勉強会 第1回 ~多対多接続はやめよう編~

社内のSTYLYシーンクリエイター向けに、PlayMaker勉強会というものを実施しています!
せっかくなので、資料を公開します!

シリーズになっているので、気になるところだけでも読んでみてください!

PlayMaker勉強会シリーズ

本記事の対象

以下の方を対象としています。

  • UnityのPlayMakerでなにか制作・開発したことがある人
  • ただしPlayMakerの設計は、あまり自信がない人

気づいたら大量のTransitionでぐちゃぐちゃ

みなさんは以下のようなPlayMaker FSMを見たことがありませんか?

image.png

大量のStateが 縦横無尽に 大量のTransition(ワイヤー)で接続されています!

規則性がありそうな雰囲気はあるので、がんばればどういう処理なのか読み取れそうですが、 非常に複雑です!

もしこれが先輩から引き継いだものだとしたら、先輩を恨むと同時に、 「自分は絶対にこういうFSMを作らないぞ!」 と心に誓うことでしょう…

ただ、そうやって誓ったにもかかわらず、 気づいたら自分も大量のTransitionを引いていたりします。

そもそも、なぜこういう状態に陥るのでしょうか?

例題を交えて解説したいと思います!

例題

以下の 要件 を満たすPlayMaker FSMを設計したいとします。

  • 3つのボタンがあります。
  • 3つの展示物があります。
  • ボタン1 をクリックすると、 展示物1 が表示され、他の展示物は非表示になります。
  • ボタン2 をクリックすると、 展示物2 が表示され、他の展示物は非表示になります。
  • ボタン3 をクリックすると、 展示物3 が表示され、他の展示物は非表示になります。
  • 展示物が表示されるとき、出現エフェクトが表示されます。
  • 展示物が非表示になるとき、消失エフェクトが表示されます。
  • 同じボタンを連続でクリックしたとき、出現エフェクトは表示されません。

テレビのリモコンで、チャンネルを切り替えるようなイメージです。
よくあるシーンですね!

案A: 多対多接続(アンチパターン)

例題の 要件 を満たすPlayMaker FSMを試しに作ってました!
(以下は アンチパターンなので真似しないでください!

image.png

同じボタンを連続してクリックしたときに、出現エフェクトが表示されてはいけないので、他のボタンをクリックしたときだけ遷移するようにしました!

丁寧にコメントも書いたし、これで文句ないでしょう!!

いや、 文句おおありです!

正直、ぐちゃぐちゃでわけがわかりません!

なんでこんなに複雑になってしまったんでしょうか?

一番の原因は、 多対多接続 をしていることです!

多対多接続とは、以下のような状態です。

多対多.jpg

この場合、矢印の数は 9本 です。

3 \times 3 = 9本

もし仕様変更があって展示物の数が4個になったら、矢印の数は16本になります!
展示物の数が5個になったら矢印の数は25本です!

矢印の数が多いほど、PlayMaker制作者の作業量は増えます。

つまり、 作業量が二次関数的に増えてしまいます!

案B: 多対1接続と1対多接続の組み合わせ

多対多接続ではなく、多対1接続と1対多接続を活用しましょう!
以下のような状態を目指します。

多対1&1対多.jpg

この場合、矢印の数は 6本 です。

3 + 3 = 6本

もし仕様変更があって展示物の数が4個になっても、矢印の数は8本です!
展示物の数が5個になっても矢印の数は10本です!

つまり、 作業量は一次関数的に増えます。

案Bは案Aよりも n/2 倍効率的!

展示物の数を n 個とすると、

  • 案Aの作業量は n×n になります。
  • 案Bの作業量は n×2 になります。
展示物数 1 2 3 4 5 6 7 8
案Aの作業量(多対多接続) 1 4 9 16 25 36 49 64
案Bの作業量(多対1接続と1対多接続) 2 4 6 8 10 12 14 16

グラフにするとこんな感じ!赤線が案A、青線が案Bです!

グラフ作成: desmos

展示物数が増えるほど、作業量の差がどんどん大きくなります!

そして、プロジェクトを進めていくうちに展示物数が増えることはよくありますが、 減ることは滅多にありません。

多対多を直接接続する設計は、いますぐやめましょう!

案BをPlayMakerで実現する方法

それじゃどうやって案Bを実現するんだ?という話になります。
多対1接続と1対多接続の2段階に分けて考えましょう!

Step1: 多対1接続

多対1接続 とは以下の部分です。

多対1.jpg

まず、 ExhibitManager という空のGameObjectを作って、そこに空のFSMを作成し、そこに ExhibitId という変数を追加します。

image.png

Exhibit展示物 という意味の英単語です。
ExhibitId は、現在選択中の展示物のIDを保管する変数です!

次に、各ボタンにFSMを作成し、ボタンクリック時に ExhibitId を書き換える処理を追加します。
具体的には、 SetFsmInt アクションを使って、 ExhibitManagerExhibitId を書き換えます。

以下のような感じです!

image.png

これで 多対1接続 の部分は完了です!

Step2: 1対多接続

次に、 1対多接続 の部分を考えます。

1対多.jpg

各展示物にFSMを作成し、 ExhibitManagerExhibitId の変化を監視するようにします。

以下のような感じです!

image.png

まず、 GetFsmIntExhibitManagerExhibitId の値を取得します。
EveryFrame にチェックを入れることで、毎フレーム取得しています。

取得した値に変化があった場合、 IntChanged アクションがそれを検知して、 Changed Event が発火します!

これで、 展示物IDが変わったときだけ処理を実行できるようになりました!

同じボタンが連続でクリックされた場合、展示物IDは変化しないので、処理は実行されません!
そのため、出現エフェクトが連続で表示されるような心配もありません。

計算負荷は問題ないのか?

EveryFrame にチェックを入れたことで、計算負荷は上昇してしまうのでは?という疑問が浮かびます!

結論から言うと、計算負荷は多少上昇しますが、 無視できるレベル だと判断しています。

値の取得と比較をしているだけであり、これは重たい処理とは言えないです。

それよりも多対多接続のデメリットの方が大きいです!

さいごに

今回はここまでです!おつかれさまでした!

次回はArray編です!引き続きこちらも実践していただけると嬉しいです!

本記事作成にあたり、以下の記事を参考にさせていただきました!
ありがとうございました!

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?