STYLYでよく使うPlaymakerサンプル集

#はじめに
[STYLYアドベントカレンダー](https://qiita.com/advent-calendar/2021/styly)12日目（遅れてすみません…）の記事です。
今回は、STYLYでPlaymakerを使い始めた人を対象にしたサンプル集になります。

##オブジェクトを回転させる
![Rotate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/2758391c-1c5f-09ac-b88a-b6c9f87af6cf.gif)

回転させたいオブジェクトにFSMを追加し、`Rotate`アクションを使用します。回転させたい軸方向の`Angle`に数値を入れ、`Per Second`にチェックを入れると、1秒間に何度動かすか指定して回転させる事ができます。

##オブジェクトを上下に浮遊させる
![updown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/2146ce5e-a090-7127-b39b-c8455a89da18.gif)

`Ease Float`アクションを使う事でイージングするVariableを作ることができます。`Reverse`にチェックを入れると数値が逆の動きになるので、交互に遷移するようにステートを組みます。その値を`Set Position`アクションでオブジェクトのポジションに、毎フレームセットすることで浮遊するような動きを作ることができます。

`Ease Type`に様々なイージングが用意されているので、いろいろな動きを試してみてください。

##プレイヤーが近づいたらイベントを起こす
![event.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/c8c46490-e6ed-243a-cf68-25c533c08885.gif)

プレイヤーが近づくと処理が実行されるロジックはColliderを使用することで実現できます。

まず、接触したらイベントを起こしたいオブジェクト同士（今回はプレイヤーであるMain CameraとCube）に`Collider`コンポーネント、Cube側に`Rigidbody`コンポーネントを追加します。この際、Cube側の`Collider`コンポーネントの`Is Trigger`にチェックを入れます。

![スクリーンショット 2021-12-20 005846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/12a5ac8d-a5ff-8b3b-3562-6cc2cc349682.png)

`Rigidbody`コンポーネントの`Use Gravity`のチェックは外します。

![スクリーンショット 2021-12-20 010000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/0367b37b-e83a-e2f3-b97b-2a3582ddd37f.png)

STYLYではシーン読み込み時にプレイヤー=カメラが新規に生成されるので、`Get Main Camera`アクションでシーンロード後にカメラを探し、`Collider`だけを持ったゲームオブジェクトがカメラに追従するようにすると問題が起こりにくいのでおすすめです。

![スクリーンショット 2021-12-20 005830.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/531b0cf3-329a-bff2-d1d9-ac70022a707d.png)

`Is Trigger`が設定された`Collider`に、`Collider`と`Rigidbody`が設定されたゲームオブジェクトが接触した/入った事などを知らせるイベントはあらかじめ用意されています。サンプルではMain CameraがCubeのCOllider内に入ったことを検知するために、`Add Global Transition -> System Events -> TRIGGER ENTER`を選択しています。`TRIGGER ENTER`イベントから呼び出されるステートにアクションを追加することで処理を記述できます。

![スクリーンショット 2021-12-20 005915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/b7cbedd7-2422-f322-b7d5-07069de3a933.png)

サンプルでは見やすくするためにCubeを表示していますが、CubeのMeshを非表示にして使えば、特定のゾーンに入った時だけイベントが起こるような使い方もできます。

##条件分岐
![Compare.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/a1341dfd-92c5-54d2-c490-107342e78708.gif)

条件に応じて何かを出し分けたい場面が多々あると思います。その場合は`~ Compare`系アクションを使う事で条件分岐を実現できます。
サンプルではMain CameraとCubeの距離に応じてマテリアルのカラーを変更しています。距離を測るには`Get Distance`アクションが使えるので、この値と閾値（Threshold）を比較し、小さければ`Blue`のステートへ、大きければ`Red`のステートへ移行するようになっています。

まずはMain Cameraの取得と`Threshold`を設定します。
![スクリーンショット 2021-12-20 000710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/17b6be42-8f85-2714-c370-86fe478567b2.png)

`Get Distance`アクションでMain CameraとCubeの距離を取得し、その値と`Threshold`を`Float Compare`アクションで比較します。`Blue`のステートでは距離の値が`Threshold`を上回った時に`RED`というトランジションが実行され、`Red`のステートに遷移します。

![スクリーンショット 2021-12-20 000728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/38c70871-bc0d-92d1-b567-602baaac5d64.png)

`Red`側のステートも同様ですが、こちらは`Threshold`の値を下回った時に遷移するように設定しています。

![スクリーンショット 2021-12-20 000758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/cca48fc8-7031-2a1b-43fb-d8e71176c318.png)

##繰り返し
![Create.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/967badb5-4a77-caa5-4bc7-be6b42d829eb.gif)

同じ処理を何度も繰り返したい場面が多々あると思います。繰り返し処理も`Int Compare`アクションで実現することができます。

![スクリーンショット 2021-12-19 122007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/846aeb09-2673-3170-7de7-9d0cfebe2402.png)

ループ用のVariableとして`loopCounter`を用意し、ステート内の最後にある`Int Compare`アクションで`loopCounter`の値を判定します。`loopCounter`が`Int Compare`アクションの`Int2`に設定した値を上回るまで、このステートの遷移先を自身に設定することで繰り返し同じ処理を行う事ができます。その際、`Int Compare`アクションによる判定の前に、`Int Add`アクションで`loopCounter`にプラス1するのを忘れないようにしましょう。

さらに応用として、生成するCubeに以下のFSMを追加します。START時の自身のY座標に応じてマテリアルのカラーが変わるようなロジックを組みました。

![スクリーンショット 2021-12-19 125632.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/8036e88c-a46c-4b7c-1a4f-55db34bbbcf1.png)

![スクリーンショット 2021-12-19 125515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/2a6345a9-0cbc-771f-cc82-c0d71a7e27f6.png)

Cubeの座標にランダムな数値が入り、生成された場所に応じてマテリアルのカラーが出し分けられました。

![スクリーンショット 2021-12-19 125435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/0a2e8bca-d33a-38c9-1291-76fa89bf035b.png)

##別のゲームオブジェクトにFSM内の情報を送る
![count.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/2c649b74-3afc-dd40-0a3b-9815bb4298d8.gif)

あるFSMで使用した数値を、他のゲームオブジェクト内で使いたい事がある場面があると思います。GameObjectを直接参照することも可能ですが、条件に応じて送り先を変えたり多数のゲームオブジェクトへ一斉に送信したいなど、直接参照すると都合が悪い場面もあります。
そんな時は`Send Event`アクションと`Set Event Int Data`アクション、そして`Get Event Int Data`アクションを使いましょう。

- `Send Event`アクションは指定したゲームオブジェクトやFSMに対してイベントを送信します。
- `Set Event Int Data`アクションはイベントを送信する際に、Int型のVariableを持たせることができます。
- `Get Event Int Data`アクションで、イベントの受信側は送られてきたVariableの値を取得することが可能です。

今回のサンプルでは上下に浮遊するキューブが下限に到達したときカウントアップし、それをUI Textとして表示します。まずはCubeとCanvasでTextを用意します。

![スクリーンショット 2021-12-20 020340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/e6dbfa83-eed8-faa1-58df-cb251284de0e.png)

先述の上下に浮遊するアニメーションに`Send Event Int Data`アクションと`Send Event`アクションを追加します。`Send Event`のプルダウンメニューを開き、New Eventで`COUNT_UP`イベントを作成し、`Text`へイベントを送信するように指定します。

![スクリーンショット 2021-12-20 020314.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/d5b32cb1-5b21-ecf3-b8fa-6d015833a810.png)

`Counter`というVariableを用意し、`Down`のステートに入った際にプラス1されるように`Int Add`アクションを追加します。

![スクリーンショット 2021-12-20 020245.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/e71f01a0-12eb-5105-9df4-3693c9f4e50e.png)

`Events`タブを開いて、`COUNT_UP`イベントが作成されているのを確認します。

![スクリーンショット 2021-12-20 020417.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/3b8b1fbb-59aa-af52-ecce-7bd47ed30995.png)

Text側でも`Events`タブを開き、`COUNT_UP`イベントを作成します。その後、Editor側で`Add Global Transition`から`COUNT_UP`を選択し、イベントで遷移するステートを作成します。

![スクリーンショット 2021-12-20 020154.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/78cb8b8f-0ed7-ee72-136a-55fc72f7021f.png)

`Get Event Int Data`アクションを使う事で、Cube側の`Send Event`アクションでセットされたVariableの値を取得することができます。その値を、そのまま`UI Text Set Text`で表示することでカウンターの実装ができました。

![スクリーンショット 2021-12-20 020212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/d6aab9ce-c69b-9314-7ed1-2d3dc7b609f2.png)



##時系列順にアクションを起こす

![timeline.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/b0a1deb5-6e3b-3dc0-e471-89cc9759465e.gif)

時系列順にFSMを実行したい場合があると思います。Playmakerには`Wait`アクションが用意されており、～秒待つという処理が記述できます。そちらを使ってステート遷移を時間で制御することも可能ですが、Timelineと組み合わせる事で視覚的に管理しやすく、複雑な動作も作りやすくなります。

まずは空のゲームオブジェクト（名前をCutsceneに変更しています。）を作成し、Timeline WindowからTimelineを作成します。

![スクリーンショット 2021-12-20 012540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/a07100a0-1e05-2f6d-c493-feb46b54e3f6.png)

次に適用したいFSMを個別に作成します。今回は先述した回転と浮遊のアニメーションを実行するゲームオブジェクトを作成しました。アクションを適用するゲームオブジェクトはCubeに設定します。
![スクリーンショット 2021-12-20 012622.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/9da48667-0496-d931-438c-610ee7c3343d.png)

![スクリーンショット 2021-12-20 012641.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/2c792549-1e59-bce0-d739-46c4a3885ce4.png)

FSMによるアニメーションを設定したゲームオブジェクトをTimeline上でドラッグアンドドロップし、`Activation Track`を作成しします。

![スクリーンショット 2021-12-20 012836.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/92bd26b8-1c2d-00a5-3104-5051aebbccdc.png)

Timeline上でActiveなゲームオブジェクトにアタッチされているFSMによってアニメーションが実行されます。今回のサンプルはシンプルなループアニメーションですが、条件に応じてマテリアルや動き方を出し分けたいなど、Playmakerのアクションで実現できるロジックを時系列順に動作させる事ができます。

##違うシーンに遷移する
STYLY Pluguin for Unityによって提供されている`Change Styly Scene`アクションを使う事で他のSTYLYシーンに遷移することができます。まず、遷移したいシーンをSTYLY Galleryで開き、シーンURLの`https://gallery.styly.cc/scene/~`の~以降に記載されているIDを確認します。このIDを`Change Styly Scene`アクションの`Scene Id`に入力すると、`Change Styly Scene`アクション実行時に指定したシーンへ遷移します。

![スクリーンショット 2021-12-19 232643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102231/44f82024-255a-a7a6-63be-54ae1e182f7e.png)

#おわりに
ざっくりとですが、よく使うPlaymakerのサンプルでした。Playmakerには様々なアクションが他にも用意されているので、ぜひ試してみてください！ありがとうございました！