- 投稿日:2020-05-24T16:20:18+09:00
模倣学習を使って人らしい動作を獲得できるか? - 1. Unityで強化学習を試す -
目指すゴール
まずはキャラクターに頭をなでてもらいたい。
頭の位置を目標点としたIKと周期的な頭位置の変更などでも実現出来ると思いますが、
模表学習による人の獲得をゴールとして進めていきます。まずは強化学習で人らしい動きを獲得できないことの確認、
その後、模倣学習により、人の教示により人らしい動きを教えることをします。本記事では、サンプルの実行までをします。
強化学習と模倣学習の事例
敵と戦うようなゲームで模倣学習と強化学習を使った事例では、強化学習(学習手法が何かは不明)では岩に隠れながら敵と戦うような動作を獲得できなかったのに比べ、模倣学習ではできたとのことです。
他にも強化学習でうまくかなかった例として、CoastRunner7が挙げられていました。Unityで気軽に強化学習
Unityでは、ml-agentsというライブラリを使って、Unityで自分で作った環境内で、自分で設計したエージェントの動作を学習させることができます。
ここに必要な概念がまとまっています。Unityの知識が少しあれば、強化学習の知識などなくても理解できるはずです。サンプルを動かす
このチュートリアルがシンプルでわかりやすくて、自分でエージェント作るのに必要な基礎も習得できるのでおすすめです。
エージェントを作る場合、次のコードを書きます。
- (エピソードの初期状態)エピソードの初期化処理、エピソード終了定義、エピソード終了時の再初期化処理
- (観測値を作る) 観測値をベクトルなどの形式に変換する
- (アクションを受け取り報酬を返す)受け取ったアクションを環境に反映する。例えば、制御信号を、物理世界の力にする。環境の値を元に報酬を計算する
- (optional:テスト用コード) コントローラーやキーボード入力をアクションの値に変換
観測値を作る際のTipsとして、Analytical Solutionを書く場合に(つまり、自分でアルゴリズムを考えたりする場合に)計算に使いそうな要素を観測値として入れるのが目安らしいです。
(一点注意点ですが、PolicyGradientの改良版アルゴリズムでボールをゴールまで動かすというプログラムになっています。最後に作成する学習パラメータの設定ファイルのみ、PolicyGradientのパラメータの設定が不足していてエラーが出るので、それだけ修正しました。)
Unityで実行してみた結果がこれです。
Unity ml-agentsの強化学習サンプル pic.twitter.com/ZJ479bHHve
— Xiong Jie (@_xiongjie_) May 24, 2020結果を見てみる
Tensorboardで実行結果のログを見れます。
このサンプルだと、50000エピソードの繰り返し(6分程度で学習完了)で、
ほぼ100%はタスクを完了出来るようになっています。
他にも内部的なメトリックを見ることができ、モデルの改善とか比較とかにも使えそうです。エピソードの並列化
このサンプルのようにTrainingArea GameObjectを作り、
その子としてゲームオブジェクトを入れておくことで、エピソードの並列化が容易であるとのことです。
Game ObjectをAssetsにD&DするとPrefabが生成されて、
PrefabをSceneにD&Dすると、TrainingArea GameObjectと同等のGameObjectが作られる。
その上でPythonのmlagents-learn
コマンドを実行、Editor上でUnityを実行することで、エピソードが並列実行される。Editor上での実行について
PythonとUnityはソケットかなにかで繋がっているようですが、
なぜか、Editor上での実行ではなく、アプリとして実行した場合、同じローカル上でUnityアプリを実行したとしても、トレーニングが開始されません。
- 投稿日:2020-05-24T07:19:26+09:00
unity1weekに参加してみて
unity1weekに参加してみて公開するまで
unity1weekとは
Unityを使って1週間でゲームを作るイベントです。
以下、本家サイト
Unity1週間ゲームジャムゲームのテーマを確認
密が今回のテーマになります。
ゲームの内容と目的を考える
今回の個人的大目標は "unity1roomで何か最低限の状態をだす"でした。
密は、ほとんど思いつかなかったのでサーバーとクライアントが密につながっている
クイズゲームということにしています。作ったゲーム
タイトルはカメQです
4択のクイズで正解を選んだらスコアが増えるゲームとして作りました
*クイズの中身は現在作成中になります公開手続き
今回は、躓いたこともいくつかあったので作業手順も一緒に残していきます。
WebGlでビルド
unity1weekでは、unityroomに投稿する必要があるので、WebGlでビルドをしていました。
*実際のビルドには、30分前後もかかったりしたので注意が必要ですファイルのアップロードを選択
ゲームの概要を入力
WebGlの設定を入力
WebGlのアップロード作業
画面に出てくる拡張子とあっているものを選択してアップロードしていくだけ
ここで設定完了なので確認をしてみる
動かない....,,,,
エラーとしては、サーバー側がUnityroom側からのリクエストを受け付けないようになっていた
azure側のcsrfにunityroomを追加してみる
通信イメージ
unityroomの場合、外部にリクエストを送信するサーバーは別になっているので以下のような図形になります(2020年5月現在)
最後に
今回は、unityroomへのアップロード以外に、通信処理を入れた場合の設定値等についても知見を得られることが多くあり良かったです。
今回は参加できてよかったです。
- 投稿日:2020-05-24T02:52:13+09:00
[Unity]動画にshaderを使って簡単なエフェクトをかけてみる
はじめに
自分が手伝っているイベントのVRizeでちょっとshader使いたいねとなったので、一時期ちょっと勉強していた知識を頼りにshaderを書いてみました。ちなみに凄いこと出来るわけではないので凄い人は期待しないでください。
対象者
shaderの基本的な事を理解している人
やることはUVスクロールなのでそれが理解できれば大丈夫です。完成物
なんとなく3 映像でも同じことできるかなって思ってやってみたらいけたので。
— Yothuba (@Yothuba3) May 23, 2020
さっきよりはややこしくてRenderTextureで映像を流して、それをc#でTextureに変換→shaderに渡して加工してる pic.twitter.com/C2xBe4BudOこんな感じのテストでを作りました。
まずは画像をスクロールさせてみる
完成物だけ作りたい人はスルーしてください。
適当なplane(Cubeとかでも可)を用意して、以下のshaderコードと共にマテリアルをオブジェクトにアタッチしてください。
_MainTexに適当な画像を指定すればplane上で画像が表示され、スクロールするはずです。Shader "Unlit/scroll" { Properties { _MainTex ("Texture", 2D) = "white" {} _ScrollSpeed ("ScrollSpeed", float) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float _ScrollSpeed; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { if(i.uv.y > 0.7){ i.uv.x = i.uv.x + _Time *_ScrollSpeed * -2; } else if(i.uv.y > 0.4000){ i.uv.x = i.uv.x + _Time *_ScrollSpeed * 2.5; //.uv.y = i.uv.y + _Time *_ScrollSpeed * -0.5; } else{ i.uv.x = i.uv.x + _Time *_ScrollSpeed; //i.uv.y = i.uv.y + _Time * _ScrollSpeed; } fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }仕組みは簡単で、fragmentシェーダ内で
uv.x
に時間経過を取得できる_Time
を乗算することでTextureをuvのx方向にスクロールさせています。また、インスペクタから自由に速度を調節できるようにするために_ScrollSpeed
変数を宣言して使用しています。
更に、if文でuv.y
の値に応じて* -2
や* 2.5
などとしてやることで、部分的にスクロール速度が変化するようになっています。動画で同じことをする
動画でやる方法ですが、まずは動画を流す対象として
RenderTexture
をプロジェクトタブから用意します。
次に動画を流したいplaneにVideo Playerコンポーネントをアタッチします。
そうしたら、Video PlayerコンポーネントからVideo Clip
に流したい動画を指定し、Render Mode > RenderTexture
に変更し、Target Texture
に先ほど作成したRenderTexture
を指定します。(すべてVideo Playerの設定です)
後はRenderTextureを先ほどのshaderに...と思うと思いますがそのまま持っていくと映像が破綻しはじめます。
原因は調べていませんが、恐らくVideo Player
からRenderTexture
に映像を書き込む際にShaderで行った変更が適用されてしまっているのではないかなと考えたので、回避策としてRenderTexture
からTexture
に変換することでワンクッション置くことを考えました。
変換方法は調べたらすぐにでてきました。参考
参考を頼りに実装したスクリプトがこちらです。
作成したスクリプトは映像を流したいオブジェクト(今回であればplane)にアタッチしてください。using System.Collections; using System.Collections.Generic; using UnityEngine; public class movie : MonoBehaviour { public RenderTexture tex; private Material material; // Start is called before the first frame update void Start() { this.material = GetComponent<Renderer>().material; } // Update is called once per frame void Update() { Texture myTexture = toTexture2D(tex); this.material.SetTexture("_MainTex", myTexture); } Texture2D toTexture2D(RenderTexture rTex){ Texture2D tex = new Texture2D(512, 512, TextureFormat.RGB24, false); RenderTexture.active = rTex; tex.ReadPixels(new Rect(0,0, rTex.width, rTex.height), 0,0); tex.Apply(); return tex; } }RenderTextureからTextureに変換する部分は、参考ままに
toTexture2D
メソッドとして定義しています。
後は、Updateで毎フレームRenderTexture
をTexture
に変換し、material.SetTexture
でshaderにテクスチャを渡すことで、
好きなように先ほど作ったshaderや、オリジナルのshaderでエフェクトをかけれるようになります。終わりに
久々にshaderを書いたのでとても楽しかったです。(ほんの数行だけど)
何かあったら、コメントで教えていただけると幸いです。