AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

飛べるようになった

ジャンプというより飛行モード( ゚Д゚)
f:id:yasu9780:20170218220941p:plain


ビルの上に行けるようになった。
f:id:yasu9780:20170218220949p:plain


飛ばす時に役に立つのがQueryちゃんの飛行モーション( ゚Д゚)


歩行時はプレイヤーもNavMeshAgentなので、普通にtransform.positonを更新するだけNavMeshの障害物を突き抜けないで移動できる。
ただし飛行時は、NavMeshAgentをenable=falseにしているので、壁にめり込んでしまう。
RigidBodyとColliderで壁対策をするとたいへんなので、CharacterControllerを使うことにした。
これだと、Colliderは壁として突き抜けなくなる。


meshにたいしては、staticでnavigationStaticを設定し、同時にmeshColliderでisTriggerをFalseにしておけば、
NavMeshAgentとしても突き抜けないし、CharacterControllerとしても突き抜けないで移動できる。
同時に、このColliderで、カメラからのRayCastチェックをすれば、プレイヤーが映っているかどうかのチェックもできると思う。
その線で行きましょう。


CharacterControllerはあまり使ったことが無いのと、MeshColliderもあまり使ったことが無いので色々と調べたい。
MeshCollider同士は衝突できないというけど、どちらかにConvexをOnしておけばいいらしい。
今回は使わないけど。


でもプレイヤーってNavMeshAgentだけど経路探索をまったく使ってないので、実はCharacterControllerとして常時使えばいいのかもしれない。
これなら、ジャンプでいちいちNavMeshのon/offしないでいいし。
実装がシンプルになる。
これは明日ちょっと実験してみよう

学校シミュレーター進捗

  • ドアの自動開閉
  • 分身生成
  • ドラッグ中の死体を投げる処理
  • カメラ用のトリガーを校舎内であちこち設定
  • 壁の不具合を調整


現在、ジャンプ機能を作ってますが、これがなかなか手ごわい。
navMeshを切りつつ、着地判定をしつつ、飛ばしつつ、ボタン押してないなら重力落下もさせないといけない(´・ω・`)
現状、ジャンプボタン押すと地面にめり込む



ドアの自動開閉も、引き戸なんで本来は、入る時は、右のドアを左に。出るときは左のドアを右に。
みたいに、ドアの表と裏で違う処理をしないいけないけど、入る時に、左のドアのトリガーに引っかかって出ると思ってしまったり、逆もあるので。
本来一方通行で判定しないといけないんでしょうけど、非常にややこしい。
もう面倒くさいので、両方に自動的に開くようにした。
もう引き戸じゃないけどw
本家だと、ドアの前に立つとOpenのコマンドが出て、openして初めて開くので自動ドアではないですね。
ただ、ドアをしめておいても、NPCはすぐに開けられるので、開け閉めする意味がないような気がします。
NPCが開けられないなら、殺す前にドアを閉めておいて逃げられないようにすることができるんでしょうけど。


分身作成はragdollをInstantiateですね。

f:id:yasu9780:20170218160811p:plain
100体生成でPCで30fps。androidだと10fps切るのかな? まだ試してない


死体投げは、投げるモーション実行→右手connect切り離し→AddForceって手順で投げましたが、
ジャイアントスイングしたら飛ぶ距離が変わると面白いのかもしれません。
HiSchoolSimulatorの実況動画でぐるぐる死体を回して投げてる人がいたので。
回してる間は、RigidBody的にはVelocityがあるはずなんですよね。それが飛ぶ距離に反映されれば、本当の意味でゲーム的。
投げモーションを再生してAddForceだと、ただの紙芝居ですもんね。

カメラ用のトリガは、地道な作業ですが、これをやっておけばカメラが壁を検出してヤンデレちゃんに寄るので、カメラに写ってない状態を避けられる。
カメラワークは非常に難しいけど、操作性にも直結するので大事だと思う。

実際に歩き回ってると、こんなところに隙間が!とかここ地面見えてるよとか、ここドアの下に隙間がある!
みたいに建築上の不具合を発見する。ゲームシーンビューだと小さいので気づかないが。
気分が建築現場の作業員( ゚Д゚)



100体生成時のprofiler数値

 CPU 29.61ms GPU35.02ms

CPU Usage
 物理計算 16ms 人体RigidBody 101体
MeshSkinning 2.6ms 人体 101体

GPU Usage
meshSkinning 5ms(202DrawCalls) 人体 101体(1体あたり2drawCalls)
batchRenderer 3ms(137drawCalls) 髪の毛 101髪+背景


SetPassCall 45なんで、SkinnedMesh増えても数に比例して増えてない
髪の毛はmeshなんで、同じ髪型ならbatchingされて効率いい

GPUUsageは低いのに、Other項目がやたら大きい。これは何をしてるんだろ?
CPUは圧倒的に物理エンジンが動いてる。meshSkinning自体は100体でも大したことない

YandereSimulatorのAI定義

KUMAGAMESさんのTweetより

YandereSimulatorのAIは、ステートマシンツールを使ってるようです。
あそこまで複雑なら、さすがに使いますよね('ω')
見た目がAnimatorに似てますね。

AssetStoreでも色々とビヘイビアツリー関係は売ってますが、PlayMakerを筆頭にけっこういい値段します。
一方でオープンソースで公開されているものもありますね。


ビヘイビアツリーみたいなビジュアルプログラミングは、初心者に分かりやすいし、作った後の動作確認もやりやすいけど、作る動作がかったるいんですよね。
Animatorも本当にかったるい。毎回、同じようなことを繰り返して作らないといけないし。
部分的にカットしてペーストできるとか、部品共有的なことができればいいんだけど。

https://pbs.twimg.com/media/C43p0h9VUAAqp1U.jpg:large


あれ? オカルト部は?

やっぱり部活を作らないといかんね。
プール作ったし、プール授業と、水泳部を作ろうかな|д゚)
空手部作るなら、空手着を着せて、キックとかパンチとか適当に技を出させて、部室内でランダムウォークさせればいいか。



Animatorに似ているとうか、これってAnimatorそのもの?


Animatorでステートマシンやるのが一番なのかな。ちょっと研究してみるかな

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

エプロンの各頂点から一番近い既存の頂点を探す

エプロンを切り出してmeshとして保存した段階で、もともと持っていたボーンとの重みづけは失われている。
ならば、エプロンの各頂点から一番近い重みづけをもっている頂点を探して、その重みづけをコピーすれば
エプロンは、身体の動きに応じて曲がるようになるのではないか?という仮定のもとに、
まず一番近い頂点と、その重みづけデータをとってみた。
いきなりやると重いので、まずは100頂点で調べた。


f:id:yasu9780:20170215193225p:plain


頂点探すために、6000回ループを100回やるので、C#にとってはなかなか重い。
(あらかじめ頂点のY座標でソートなどしていれば、バイナリーサーチで早くできる)

全頂点に対し、一番近い頂点を探して重みづけをコピーした。

使用前

f:id:yasu9780:20170215175847p:plain

使用後

曲がった! エプロンが曲がった! ( ;∀;)
f:id:yasu9780:20170215200753p:plain

あとはsharedMeshをAssetに保存してやれば永続的に使える('ω')

一部、下のセーラー服が見えてたりするので、改良の余地はあるが、ぴったりした服を重ねて着せる場合など活用できるはず。
現在は合成頂点番号を決め打ちしているので、skinnedMeshとmeshを合成して重みづけまで変更するようにすれば、汎用性が出る。
というか、これってアセットストアで売れるかも?('ω')

少なくともこの人の要望には応える

https://forum.unity3d.com/threads/simplelod-generate-lod-levels-and-combine-skinned-meshes.282127/page-7#post-2580607

蹴りモーション

蹴りモーション実行中。エプロン下部はスカートの重みづけがコピーされていることが分かる。
スカートがめくれるとエプロンもめくれてる
細かく見ると荒も見えるけどおおむね満足できる。
f:id:yasu9780:20170215203129p:plain

足ボーンとの紐づけはない

もともスカート自体が、大腿部のボーンと紐づいてないので、足を動かしても、重みコピーされた状態のエプロンも動かない。
アセットに付属のモーションで、歩行でスカートが揺れるのは、GenericAnimationとしてスカート揺れもモーションが追加されるため。
HumanoidAnimationであればスカートは揺れないので、足がスカートを突き破る。

f:id:yasu9780:20170215205033p:plain


blenderの重みづけ自動がどういうアルゴリズムか分からないけど、各頂点から近いボーンを4つピックアップして、距離に応じて割合を案分してやれば
自動ウェイト機能が作れるのではないだろうか。
これをやれば、おそらくスカートボーンに100%重みづけがあるスカートの頂点が、足の動きに連動するはず。

これはちょっと想像するとかなり難しそう。
たとえば、右大腿部の頂点は、右大腿部ボーンや右膝ボーンと重みが欲しいが、いくら近くても左膝ボーンとの重みづけは欲しくない。
しかし、場所によっては、右大腿部より左ひざの方が近い頂点があるかもしれない。近いかどうかでは限界がある。面が繋がっているかどうかも考慮しないといけない。
空間距離ではなく、面上での距離。UV距離といってもいいかもしれないが。
情報としては頂点と三角形の情報があるのだから、経路をたどっていけば、面上との距離は算出できるだろう。
オープンソースなんだからBlenderのソースを見た方が早いかもしれない。

エプロン合成後のボーンウェイトを調べる

ヤンデレちゃんにエプロンを合成したあとのボーン重みづけの状態を調べてみた。

エプロン合成前は頂点数6085のmesh(髪の毛を削除しているのでその分、標準Hモデルより少ない)

エプロン合成後は、6327頂点に増える
エプロンmesh自体は241頂点なので、丁度エプロンの分だけ頂点数が増えている。


bonesはSkinnedMeshのSkinnedMeshRendererが所有している。
boneWeightsは、mesh自体が所有している。
bindpossesは、meshが所有している。

合成後のSkinnedMeshに関して、boneWeightsを調べてみると

f:id:yasu9780:20170215175847p:plain
↑mesh自体は合成されているが、Spineボーンを動かすと、紐づけされていないエプロンは動かない。


boneWeightsの数は頂点数に一致するので、すべての頂点が、1~4種類のボーンに対する重みづけをもっているという仕様。


ある頂点に関して、以下のようにboneWeightが定義されていると、ボーン0に100%関連付けられ、他のボーンには0%なので、ボーン0の動きに対して100%この頂点は影響を受ける。
index0 = 0 weight0 = 1
index1 = 1 weight1 = 0
index2 = 2 weight2 = 0
index3 = 3 weight3 = 0


以下の定義では、ボーン0に50%、ボーン1に50%と定義されるので、ボーン0とボーン1の動きに50%づつ影響を受ける。
例えば、肘付近の服や肌は、上腕と前腕の影響を受けるように定義することで、うまく曲がっている(はず)
index0 = 0 weight0 = 0.5
index1 = 1 weight1 = 0.5
index2 = 2 weight2 = 0
index3 = 3 weight3 = 0

元の話に戻ると、頂点6086以下はエプロンのメッシュから合成された頂点と考えられるけど、それぞれのボーンの重みづけ状況を調べると
150/1 150/0 150/0 150/0
となっている。これは150番ボーンに100%重みづけられ、150番ボーンに0%、、150番ボーンに0%、、150番ボーンに0%と定義になっている。
ある意味矛盾した定義(´・ω・`)
しかもボーンは150個なので、おそらく最後のボーンに機械的に紐づけられているだけだろうと推測
150番ボーンはボーンヒエラルキー的に、おそらく右手の親指の末端ボーン。
なお、末端ボーンは動かしても影響がない。これが149ボーンだったら、右手親指を動かせば、エプロンが影響を受けるかもしれない


ということで、SimpleLODはSkinnedMeshの合成に対応とはあるが、おそらくボーン重みづけはなにもしてない
末端ボーンと紐づているが、重みを100%であり0%と定義されているので、事実上、ボーンの影響を受けない仕様。
元々、SkinnedではないただのMeshであるエプロンは重みづけ情報を持っていない。

SimpleLODでテクスチャアトラスを焼く

テクスチャをまとめる使い方がやっとわかった。

menuからbake atlasを選んだら、まとめたいマテリアルを画像ではなく、左側の大きな枠をD&Dしてやれば、それか子階層になって、プロパティはは親に準じる状態になってマテリアルが2から1にまとまる。
さらにもう一つD&Dとしていけば、するたびにマテリアルが減っていく。
間違って画像の方をD&Dしてたので、マテリアルが全然減らないからおかしいなあと思ってた。

f:id:yasu9780:20170215033342p:plain


教室のマテリアルが12個あったので、drawCallやSetPassCallも12出てましたが、
マテリアルを3つにまとめたので、SetpassCallが3まで減りました。
ガラスだけ分けてますが、mobile/diffuseみたいな光を見るやつで透明対応のShaderにまとめれば、一つにできそう。


f:id:yasu9780:20170215033109p:plain

setPassCall 3になった(^ω^)
頂点減らすよりも効果がありますね。


昔お世話になったtakujidevさんの記事を読んで、ゲーム全体でなんとなく評価するんじゃなくて、素材パーツ一つ一つを吟味しようと思い立ちました。
tf.hateblo.jp


SimpleLODは本当に良いツールです。ものすごく簡単で、ものすごく動作が早いです。
たとえば、meshの合成ですが、複数のメッシュを子階層に持つ親を選択した状態で、ToolsからSimpleLODを選び、mesh合成を選んだら、もう完成です。ワンクリックで終了。
これが、MeshBakerFreeだと、とても覚えられないような複雑な構成の操作をやらないといけません。

baker0のWindowを出して、objectを選ぶためのボタンを押してメニューを出し、オブジェクトを選んだら、Windowに転送されるので、今度はフォルダーを作って、マテリアルの保存場所を作って、
オプションを選んで、マテリアルアトラスをつくて、今度はbaker0に戻ってbakeを押して、みたいな何段階もわかれた手順をやらないといけません。
挙句エラーでどうしてもできなった合成が、SimpleLODで一瞬で終わりました(´・ω・`)

https://www.assetstore.unity3d.com/jp/#!/content/25366

SimpleLODでHumanoidに服は着せられないみたい

ヤンデレちゃんセーラー服に、エプロンだけのメッシュを配置して、SimpleLODでマージてみましたが、たしかに一つのmeshになりましたが、Animatorで動かすと、エプロンはボーンと重みづけされないので、
エプロンだけ取り残された形で動きました。
文字通り、ボーンの重みづけには触ってない仕様のようです。
帽子とか、手に槍といったものなら接続はできるようです。それはボーンの子供に配置するのと変わりませんし。


フォーラムでも同様な質問がありました。
https://forum.unity3d.com/threads/simplelod-generate-lod-levels-and-combine-skinned-meshes.282127/page-7#post-2580607

Ok, an update.. the meshes are getting combined into one and it is indeed working properly, and I am grabbing the proper animator component, but it's not animating. I can force the mesh to start working properly with the animations by changing any setting in the animator component while the game is running.. like changing the culling mode to something else other than what it's currently set to at the time... but until I do this it is just tpose all the time.

So I'm thinking the animator component needs to be initialized after the mesh combine, not before. Struggling on the how of making this work, but this is really not an issue with this asset so I'll take my plight elsewhere. Thanks for the great tool.

CrisisSystem, Apr 4, 2016


マージしても動かない。Humanoidで再初期化してみたけど無理だったと。
Blenderには、自動重みづけでボーンとメッシュを重みづける機能があります。技術的にはエプロンのメッシュにボーンからの重みを自動的に付加することは可能なはずです。
いづれそのようなアセットも登場するでしょう。
SimpleLODはすべてC#で書かれていて、DLLは使っておらず、100%Unity上で動いているので、改造することはできるかもしれません。