クーの自由研究

マスターのかえるのクーは、弟子達の召喚術により新たな依り代を得てⅡ世として復活しました。

Particle Systemで少し飾り付けをしてみます

週末こそはUnity三昧

こんにちわ、こんばんわ。かえるのクーの助手の弟子の「井戸中 」(いとなか )です。

f:id:luriAPupileOfKoo:20210404173013j:plain

連休中はML-Agentsを中心に遊びましたが、肝心のUnityはまったく理解が進んでいません。そこで、連休中につくったSpaceBallという超絶簡単(コメント含めて100行程度)な強化学習プログラムを題材にして、それに飾り付けをしてみます。(まぁ作ったというより、チュートリアルの球の2次元動作(x, z) を 3次元動作(x, y, z)にしただけのパクリ応用ものです。)

見栄えは大切

SpaceBallは強化学習の様子はわかるのですが、改善の余地がありすぎです。このブログはこの週末を使って、勉強をしていく記録にします。(なのでこの記事の完成は日曜(5/9)の深夜になると思います)どこまでできるかわかりませんが、以下をやってみたいです。

・SpaceBall は空間に漂う球がもう一方に衝突するように学習するプログラムですが、いろいろ問題があります。

(1)衝突したのか、時間切れで次のエピソードにいったのかわからない。

(2)音とかがないのでつまらない。

(3)いまいち学習の詰めがあまい。(学習結果がどうみても最善ルートになっていない)

そこで残念なところを修正します

(1)の対処:

  • a. UnityのParticleSystem で爆発のエフェクトをかける。
  • b. 時間切れの場合は、球体のMaterialを変更して、色をかえてわかるようにする。
  • c. 緑球が出現するときにちょっとしたエフェクトをかけて、それっぽくしたい。

(2)の対処:

  • 報酬をもらったとき、罰(マイナス報酬)をもらったとき、衝突したとき、球が出現しなおしたときに、効果音をつけてそれっぽくしたい。

(3) の対処:

  • 近傍までいってなかなか衝突しないケースを、報酬の与え方、および観測パラメータを追加することにより学習を改善したい(こちらは純粋に強化学習系の興味です。)

簡単な爆発エフェクトであれば標準のParticle Systemでそこそこできる?

f:id:np2LKoo:20210508062033p:plainf:id:np2LKoo:20210508062058p:plain

 粒子を放射する系のエフェクトが簡単に作れるようです。

では、この情報をもとに球が衝突したときに爆発/破壊っぽいエフェクトがでるようにしてみます。(現在は衝突したらそこから消えるのみで、衝突がわかりにくいです)

爆発は上の公式の説明によれば、「ParticleSystem」(粒子生成システム?)は単体のオブジェクトとして存在させることも、既存のオブジェクトに対して「コンポーネント」として設定させることもできるようです。SpaceBallでは、Agent側()にいろいろ制御プログラムを仕込んでいるので、単体オブジェクトとして操作することにします。

試行用に新規のプロジェクトを作成してParticleSystemを操作してみます。最新版の2020.3系では上の説明の操作とはかなり違っていましたが、基本は同じはずです。

以下はUnity2020.3系の操作です。

- 1. GameObjectメニュー/2. Effects/3. Particle System

f:id:np2LKoo:20210508065349p:plain

で ParticleSystem という名前のオブジェクトができました。4.名称をExplosionにそれっぽく変更しておきます。円錐状(Corn)に絶え間なく粒子(Particle)が放出されます

f:id:np2LKoo:20210508070222p:plain

これを球状に放出するようにします。

Explosionオブジェクトでの右側 InspectorのPerticleSystemのShapeの5.Shape をCornからSphereに変更します。放射状に放出されるようになりました。

f:id:np2LKoo:20210508071938p:plain

 ループ再生になっているとわかりにくいので、6.Loopingのチェックボックスを外します。Durationが粒子の放出期間(秒)、Start Lifetimeが粒子の生存時間のようなので、調整します。爆発っぽく短くします。7. Durationを0.2 に、8. Start Lifetimeを2 にしてみます。エフェクトの実行は 9. Particle Effect小窓のPlayボタンをクリックします。

f:id:np2LKoo:20210508074616p:plain

放出される粒子数が極端に少なくなってしまいました。粒子数を増やしましょう。

EmissionのRate over time が1秒あたりに放出される粒子数のようです。粒子数は100個くらいを想定します。0.2秒の放出期間なので、9. EmmisionのRate over timeを500に設定します。かなり大きな球をイメージしているので、爆発といいながらも「ぐしゃっ」とこわれる感じにします。10.Start Speedを0.3にしてみます。なかなかいい感じになってきました。

f:id:np2LKoo:20210508084639p:plain
緑色の球がこわれものなので、粒子の色は緑系にします。11. 粒子の色をグラデーション色で12. (RGB)=13.(32,255,64)-14.(255,255,64)としてみます。

 凝ればきりがなさそうですが、(1)aの目的としては充分だと思います。

f:id:np2LKoo:20210508090300g:plain

 次は(1)bのオブジェクトのマテリアル変更です

球の色はマテリアルで与えています。このマテリアル自体の色をかえる方法もあると思いますが、オブジェクトに設定するマテリアル自体をプログラムで変更(すげ替え)します。衝突報酬をもらえなかったとき、Agent球の色をからに変更することにします。こちらは、前回のSpaceBallの環境を変えてやってみます。

1. Assets フォルダ内にResourcesフォルダ を作成して、作成済のマテリアル系を移動します。(Materialsフォルダではなく、必ずResourcesフォルダとします)

2.ついでにScriptsフォルダもつくってSpaceBall.cs ファイルを移動します。

3.さらについでにTFModelsフォルダもつくってSpaceBall.nnファイルを移動します。

ここまでは整理として行います。

f:id:np2LKoo:20210508094720p:plain

4.Resourcesフォルダ内にRedという名前のマテリアルを作成します。((1)bの主役)

f:id:np2LKoo:20210508095351p:plain

では、SpaceAgentに対して、(1)bマテリアルの操作と、(1)aで作成したエフェクトの再生をコーディング(元のSpaceAgentへ追加・変更)してみます。あいかわらずフォーマットがくずれているのはご容赦ください。+ マークの行を追加しました。(+ の入力は不要です)

public class SpaceAgent : Agent
{
    public Transform target;
+    public Transform explosion;
...
+    Material _material//マテリアルの初期値を退避します
+    bool isSuccess//衝突が成功したかどうかのフラグ

    // 初期化時に一度だけ実行されます
    public override void Initialize()
    {
        this.rBody = GetComponent<Rigidbody>();     // 物理計算オブジェクトを取得
        Physics.gravity = new Vector3(0, 0, 0);
+        _material = GetComponent<Renderer>().material;
+        isSuccess = true;
    }

    // エピソード毎の最初に実行されます。
    public override void OnEpisodeBegin()
    {
        this.epsodeCount++; //エピソードの回数をアップします
        this.actionCount = 0//アクションの回数をリセットします
+        if (isSuccess)
+        {
+            GetComponent<Renderer>().material = _material//オリジナルのマテリアルを設定します。
+        }
+        else
+        {
+            Material material = Resources.Load("Red"as Material//ResourcesフォルダにあるRedというオブジェクトをLoadします
+            GetComponent<Renderer>().material = material// 赤色のマテリアルを設定します
+        }
+        isSuccess = false;
...
 
    }

...

    // 行動を起こすタイミングでの行動の値を決定します
    public override void OnActionReceived(float[] vectorAction)
    {
...
        if (nowDistanceToTarget <= 1.2f)
        {
+            explosion.position = target.position;
+            var exp = explosion.GetComponent<ParticleSystem>();
+            exp.Play();
+            isSuccess = true;
...
        }
...
    }

}

プチ説明:

爆発エフェクト用のオブジェクト参照用に explosionを追加しています。このあとインジェクション(オブジェクト注入)を設定します。

initialize():最初に一度だけ実行される:で最初に設定されているSpaceAgentのマテリアルオブジェクトを退避します。

OnEposodeBegin():各エピソードの開始時に実行される:で前回成功したら、オリジナルマテリアルを設定、前回失敗なら赤色マテリアルをロードして設定します。

OnActionRecieved():行動決定のタイミングごとに実行される:衝突判定がなされたら、explosionのエフェクトを実行します。

実行結果例は今回の最後に動画を貼る予定です。たいしたことないので期待しないでください。

 ソースを変更して保存すると、

f:id:np2LKoo:20210508195530p:plain

SpaceAgentのSpaceAgent(Script)欄にExplosionのインジェクション欄(?正式名称を知りません)がでてきます。素敵すぎます。

ExplosionオブジェクトをこのExplosion欄にドラッグ&ドロップすれば、プログラムからこのオブジェクトが参照できる次第です。

ここまでで、(1)aと(1)bが完成です。8888

 (1)cのターゲット出現エフェクト

では、次にTarget出現のエフェクトをやってみます。できれば異世界転生モノのようなエフェクトにしたいのですが、キラキラさせるだけくらいにするかもしれません。

検索により、自分でつくるよりFree Assetsでよさげなものを使用したほうがよいと考えました。

これを導入してみます。

 導入しました。良いのですが、ボールに合わせてみるとしっくりくるものがあまりなかったです。このAssetを導入し、(1)bでやったようなソースの修正をして、オブジェクト関連を定義する「だけ」なので、新規の情報はほとんど無いので、記載はスルーします。どんな出来栄えかは、貼る予定の結果(動作例)を確認ください。

2. 効果音をつけてみる

まずは、実験用PC機にサウンドドライバを入れていないので、そこからです。音がでました。

では勉強をはじめます。Unityの音に関しても情報がたくさんあります。(どれも分りやすいのでとくにリンクは貼りません)3Dサウンドを使うと、音のなる方向や大きさを自動的に調整してくれるようなので、設定でそれを使ってみます。音も他のコンポーネントと同じようにオブジェクトにコンポーネントを設定し、その取得も同じ感じです。

音はてきとーにフリー素材をダウンロードします。音がどこでなるかにこだわってみたいと思います。

SE音の種類とオブジェクトの決定

衝突音爆裂エフェクト側でならす:爆裂音

Target出現音Target側でならす:魔法転送音

衝突できなかった時の残念音Agent側でならす:なんか残念な音

プチ報酬の音Agent側でならす。衝突(成功、失敗)の後、何アクションかの間(2秒ほど)はならさない。(Agentで出す音を報酬音にしない)

   - 報酬はアップ音:オオルリの声

   - マイナス報酬はダウン音:コガラの声

衝突報酬音Agent側でならす。報酬が高いと高い音にする。:ピアノの音

BGM音

・BGMは、聞いている人(Listener)に直接ステレオで聴かせるために、MainCamera側でならしてみます。なんか天体っぽいBGM

音は以上の7つです。SoundSourceコンポーネントは4か所への設定です。なんかうるさくなりそうですが、やってみます。

- 1. Resourceフォルダ選択/2. 気に入った音をここに複写/3. HierarchyのMain Cameraを選択/4. InspectorのAdd Componentボタンをクリック/5. Auを検索しAudio Sourceを選択

f:id:np2LKoo:20210509121149p:plain

BGMはカメラに直接設定します。

- 6. AudioClip でBGMを設定/7.Play On Awake をチェック/8. Loopをチェック/9. VolumeでBGMとして邪魔にならないくらいの音量を設定 (あとはデフォルトの通常設定とおり)

f:id:np2LKoo:20210509122305p:plain

 あと、同様にSpaceAgent, Target, Explosionへそれぞれ、3., 4., 5. と同様の操作を行いAudio Sourceコンポーネントを設定します。(全部で4つのAudioSourceです)

SE音を再生するよう、プログラムを修正します。(ここにソースを貼ると修飾が複雑なためかフォーマットが崩れるので、別のページにはります。GITには恥ずかしいのでアップしません(汗))

 

SpaceAgentへの音設定をします。

- 10. HierarchyのSpaceAgentを指定/11. サウンドオブジェクトをPGのサウンドクリップ変数へそれぞれ設定/12. Play On Awakeのチェックを外す/13. Loopのチェックを外す/14. Spatial Blendを0.96にする(この値でほぼ3D優先:見た目の位置で音がなる)

f:id:np2LKoo:20210509124301p:plain

Targetの音設定をします。(このPGでは音の制御はSpaceAgent側で行っています)

- 15. HierarchyのTagetを選択/16. Audio SourceのPlay On AwakeとLoopのチェックを外す/17. Spatual Blendを 0.9にする(1にすると完全に3D優先となりますが、遠くの音が小さすぎるので、このあたりにしています)

f:id:np2LKoo:20210509125337p:plain

Explosionの音を設定します。(このPGでは音の制御はSpaceAgent側で行っています)

- 18. HierarchyのExplosionを選択/19. Audio SourceのPlay On AwakeとLoopのチェックを外す/20. Spatual Blendを 0.9にする

f:id:np2LKoo:20210509130355p:plain

プロジェクトを保存したあと、Play▶で実行します。

長くなってしまったので、(3)はまた別の機会ということで。。。

では一応の完成版として動画を貼ります。(前回のは学習中の動画なので、本来のスピードはこちらとなります)

衝突がはっきりわかり、報酬の大きさもわかるので、自分としては満足のいくものとなりました。 たまにフレームアウトするのはご愛敬ということで。。。

ボールと音の位置がそれなりにあっているのがわかると思います。

エフェクトってとても大切ですね。

※学習の経過(だんだんできるようになる様子)がみたい方は前のページをご覧ください。