はいもーど!
Trance_Modeです。
11/11日にアップデートされたワールド「Trance's Hotel with NPC」についての解説?記事です。
とにかく苦戦を強いられる戦いで思っていたよりも作業に時間を取られる結果になってしまいました。。。
作業時間は丸々一か月以上は費やしたと思います。
・添い寝
・なでなで
・ポッキーゲーム
主な機能はこの3つでしょうか。
Let's Just Pokky Game Udon3!!(以下JPG3)には無かった機能が色々と追加されました。
以前の記事で上げていた今後の展望の
・表情の追加
・モーション追加
・服装の追加
・服装変更時モーション
・quest対応
・ミラー、コライダー昇降機能の追加
・EXMenuのデザイン変更
・pokkyリロードUI追加作成
を達成した感じですね。
ほかの要素はワールドの違いがあって達成できなかった部分もあります。
またこのワールドはクエスト対応に向けたワールドなのでミルクちゃんしかいません。PC版はまた別にワールドを分けてJPG3のアップグレード版として正規に実装予定です。
ではまずNPCの話をする前にTrance’s Hotelについての話をしましょう。
なんでホテル?なのかですがワールドの機能としてとにかくベッドが欲しかったのでじゃあホテルでしょ!という事でホテルになりました。確か。
そこでBoothでベッド付きのアセットを探していると良さげな物があったので購入しました。
内装にも拘りたくて以前購入していたUnity Asset Storeにあるアセット、Night Clubのテクスチャ達を借り使用した所しっくり来ました。
他配置の調整や各アセットの法線がおかしい箇所の修正等の細かな修正を加えました。
初期の頃
内装が決まってきた頃
完
Trance's Hotel with NPCの前は「Trance's Hotel」でNPCはいませんでした。
というのもJPG3の内装は可愛い雰囲気で悪くはないのですがもう少し作りこまれた空間が良かったので次のアップデートに向けてテストとしてワールドだけ作りこもうという試みでワールドのみでアップロードしていました。
可愛い理想的なホテルを作りたかったのですが自ら凝ったワールドを一からモデリングするには手間がかかるのとNPCの実装に時間を掛けたかったのでベッドがあって部屋っぽい良さげなアセットに頼ることにしました。
そう、ホテルした理由これだ。
ただ購入したアセットの内装の作りがほぼ出来上がっていてそれに手を加えていると可愛いではなく高級っぽい内装のホテルに寄って行ってしまったんだと思います。
とこんな感じでTrance's Hotelが出来上がりアップロードされていました。
それとJPG3にもありますが私のワールドの他のワールドにはあまり無い機能がこのEXMenuですね。
EXMenuのデザインも変更しました。
JPG3のUIはプロトタイプでデザインは変更しようと決めていました。
文字も見やすくなりまあまあな出来にはなったのかなーと思います。
ただ左手での起動しか対応していない為ユニバーサルデザインではない問題はあります。今後のアップデートでどちらの手でも起動できるように改善予定です。
またポストプロセスのシステムも変わりました。
かなり細かいラィティングの変更が可能になりました。
ただわざわざラィティング変えたりしないんだよなぁ...とか考えたりします。悩み所。
部屋が明るいなぁと思う場合はColor CorrectionのExposureを変更すれば暗くできます。
長期休みにも入り内装もほぼ出来たので肝心のNPC作成に取り掛かりました。
休み中にある程度の完成とアップデートを予定していました。
ただ上のツイートの通り全然完成しなかったですね。(笑)
まずNPCのシステムが重いのでワールド自体を軽くしようと考え
・各オブジェクトの最適化
・mesh bakerを使いメッシュの統一化
・標準プロファイラを使い各アセットの負荷を調べ使用を辞める、変更する
・Animatorの設定
等の調整を行いました。
各オブジェクトの最適化は主にUI部分です。
必要のないImageのRaycast Targetのチェックを外す
CanvasのEvent Cameraにカメラの設定をする
等です。
詳しくはこちらの記事が参考になると思います。
3つ目の標準プロファイラを使い各アセットの負荷を調べ使用を辞める、変更するですがBoothは便利なアセットが沢山あり面白いものもあるのですが実はそれ単体でかなりの負荷がかかっている事があります。
同じようなものでも実装が異なるものもあり中には20fpsくらいの差が出るものありました。
それらのアセットの使用変更や使用を辞める等の処置を施しました。
4つ目はAnimatorの設定、主にカリングモードの設定です。
画面外で動かなくていいものはAlways Animateから変更します。
負荷が軽くなります。
・IK,服、小物
実はテスト当時ミルクちゃんの他の服や小物は詰め込まれていてIK操作もできていました。
ただ同期の問題や容量問題で見送られ実装はPC版で実装されると思います。
・好感度パラメータ
好感度パラメータも実装予定でした。(見送り)
・AudioLink
AudioLinkも実装予定でした。(見送り)
クエスト版なら要らないかなーという事と容量的な問題と負荷要因です。
・Lightmapの埋め込み
最初はどうしても部屋のライティングをリアルタイムらしく変えたくてLightmapをマテリアルに埋め込みシェーダーでLightmapの明るさ変えればいいじゃん!と思い試してみましたがライトプローブの問題やノーマルマップの反映が分からん!ガラスのマテリアル(transparent)実装分からん!があり諦めました。
ライトマップ埋め込み
ベイクしてるやつ
(ほぼ同じ)
(黒いのはDynamicなので関係ない)
ライトマップ埋め込みが出来ればライトマップを変えたり明るさを変更するだけで部屋の雰囲気を変えることが出来るので実装したい所でした。
ただシェーダー力が足りずlightmapが使えるstandardシェーダーを作成するまでに至りませんでした。
こう見返してみると今のライティングの方が個人的には綺麗になったかなーと思いますね。
ちなみにベイクはBakeryを使用しました。
値は以下です。
ミルクちゃんのアニメーションはモーションキャプチャーで誰かさんが撮った物です。
まだ出来には満足していません。。。
可愛いモーションください...
表情やモーションは全てアニメーションで制御しています。
こんな感じ
Base Layerに主なモーション、Breathに呼吸モーション、Faceに表情モーション、Armに腕以外がマスクされたモーションが入っています。
どういうモーションが可愛くて面白いと感じるか考えるだけで一苦労で参考になりそうなゲームを探したりしてみましたが中々無くアイデア力が欲しいなぁと言った所です。
npcシステムはNav Mesh Agantを使用しています。
Navigationエリアベイク時にNavigation Staticなオブジェクト(白いやつ)を置き不要な箇所がベイクされないようにしました。
またベッドとお風呂にOffMeshLinkを設定し移動できるように設定しました。
値は以下です。
お風呂に入る際のドアにNav Mesh Obstacleを付けてドアが閉まっているとき通らないようにする事も考えましたがスタックする場合があり実装を見送りました。
NPCのシステムは主にAnimator, Nav Mesh Agent,
ThirdParsonCharacter(U#), 作成したNPCController3で構成されています。
つまりNPCController3にほぼすべての機能が詰め込まれてます。
こんな感じ
主にmode変数とstate変数でモーションを決めfaceState変数で顔の表情を決め他の変数の値によってそれらの値が決まりAgentが動く形式です。
Agentの移動の動作はThirdParsonCharacterに任せています。
Character.Move()で値を渡すだけで動きます。
ターゲットに近い場合と遠い場合でAgentのスピードを変更して走ったり歩いたりモーションが変わるようにしています。
またfinalIKは最初使用していたのですがU#で値の変更が出来ないこともありOnAnimatorIKで視線の制御をしました。Vector3.LerpやMathf.Lerpを使い視線目標までゆっくり移動させる, stateによってlookWeightの値を変更する等の実装をしました。
また最初はLaycastを使い視線の制限を掛けていましたがplayerの判定が
うまく取れない為カプセルコライダーにplayerが入ったときにplayerの判定を取るように変更しました。
今の所NPCには主な機能として
・プレイヤー移動
・ランダム移動とポイント移動
・プレイヤーポイント移動
・立ちどまりモーション
・プレイヤーポイントヒット
があります。
プレイヤー移動はカプセルコライダーにプレイヤーが入ったときrandomStateCountPlayerに入っているstateをランダムで実行しプレイヤーの方に移動します
ランダム移動とポイント移動はカプセルコライダーにプレイヤーが入っていないとき(randomStateCount)に入っているstateをランダムで実行し指定のポイントに移動するかNPCを始点にランダムメートル以内の移動できる位置に移動します
プレイヤーポイント移動はこたつやベッド等指定のポイントにプレイヤーが入ったときrandomStateCountPointに入っているstateをランダムで実行し指定のポイントに移動します
立ちどまりモーションはmodeがstandmodeのときrandomStateCountStandに入ってるstateをランダムでその場で実行します
プレイヤーポイントヒットはplayerの手や頭や物がnpcの指定の位置に入ったときに実行されます
主にこの5つがまとまった機能としてあります。
あとは服が変更されたときやポッキーが入ってきたときの関数実行によるstateの変更ですね。
またmodeがstandmode sitmode sleepmode等がありstateが50個くらいあります。
standmodeの時のstate1の時やsitmodeの時のstateが1の時でモーションを変えることが出来state数の節約ができます。
まだ実装されていないですがプレイヤーのheightを取ってプレイヤーの目線位置に合わせてstateやmodeを変えることもできそうです。
JPG3にはありますね。
mode変数によってモーションの変更が幾分楽なのでmode変数を変えて歩行モーションを変えたりも出来ます。
これは好感度メーターが実装されたとき使えそうです。
mode変数,state変数とnpcの位置変数と回転変数、sleep時のpose(state)変数が[UdonSynced]変数になっています。それ以外の変数は全てローカル下で動いています。sleep時のpose(state)変数は一つのstateとして扱えばstate変数に合併出来ますが実装過程により増えてしまいました。[UdonSynced]変数は出来るだけ使いたくないので合併したいところです。
主にswitch文で動いています。つまりstate分だけswitchで分岐があります。
Update関数で各switch文に対して
・faceStateの決定
・視線の決定
・agent.stoppingDistanceの値決定、立ちどまりモーションを実行するかの選択
・プレイヤーポイントヒットを可能にするかの選択
・どのようにUpdateStateするか
があり関数としてまとめられていています。
立ちどまりモーションは主にanimationのAnimation Eventでスクリプトの関数を呼び出しUpdateStateを実行します。
stateによってプレイヤーの手や頭とnpcのポイント位置の距離を計算するか、指定のポイントとプレイヤーの位置を計算するか、プレイヤーとNPCの距離の計算をするか決めます。それがどのようにUpdateStateするかに入ります。
UpdateStateはオーナーだけしか実行することが出来ずかつdeferChangeState > 0の時に実行されます。
ここでmodeとstateがupdate内で起こった変数の値により変更されます。また位置変数と回転変数の更新も行われます。
sleep時の変数はstateがsleepmodeの場合変更されます。
そしてUpdateStateでもswitch文で各state内でdeferChangeStateの値決定、SetDestination()の実行が行われます。
またContinuousも出来るだけ使いたくないのでManualでRequestSerialization()とRequestSerialization()で値を同期しています。
そんなこんなでなんとか同期できるNPCが出来ました。
問題はオーナーの受け渡しは出来ないところです。
何故かどうしてもNPCのオーナーを変えると視線だけローカルで動いてしまい実装に間に合いませんでした。。。
次のアップデートまでには出来るようにしておきたい所です。
ミルクちゃんだけなのはこのNPCController3が完成したら他のアバターに付けるだけで動いてしまうのである程度の完成度になるまでアバターの設定ではなくスクリプトの挙動に対して時間を掛けたかったからです。
正直なところ完成度は30パーくらいですね。。
IKの実装が出来なかったのと挙動がまだまだいまいちなのでもう一度見直して作成しなおしたいですね。
次の長期休みでどこまでできるかといった所です。
UIやポスターも作ってみました。
最初から遅くても11/11日にはとりあえずの所でアップロードしようと考えていたのでなんとか動くようにして完成しました。
まだまだやりたいことや実装できなかったことが沢山あるので少しずつ実装出来ていけたらいいなと思います!
早く他のアバターに対応させたい...服や小物も追加したい...(購入しただけで全然使っていないものがいっぱいある)
ただ持ってるもの全部実装したらとんでもない量になりそうなのと負荷的に大丈夫なのかっていう所がありますね。
あとNPC増やしたい。
ちゃんとしたスクリプトが出来上がれば対応は簡単な気がしています!
ちゃんとしたスクリプトが出来上がれば!
まだSetLookAtWeight()がうまく動かない問題やオーナー受け渡し問題があるのでまずそこを直したいですね。
Discordサーバーあります!
どなたでもwelcomeです。
使用したアセットやこれから新しく作る物の宣伝や進捗も載せようと思っています。
支援者の方にはロールを付与していますので、支援者の方や気になる方は是非覗いてみてください。
以上!
(実装予定)
水中エフェクト
ドアエフェクト
プレイヤー視線によるモーション変更
トイレモーション
シャワーモーション
シャワーパーティクル
眼鏡などのアクセサリー
服
キャラ
ポテチ、モーション
ルンバモーション
猫,モーション
銃、モーション
ジャンプモーション
audiolink機能
曲に合わせたダンスモーション
好感度パラメータによるモーション変更
NPCネームプレート,ネーム設定
オーナー受け渡し
playerHeightによるモーション変更
香水、モーション
カメラ、モーション
表情
ステート追加
sleep時の分岐モーション
視線制御
IKPickup
NPCPickup
NPC人数の追加
UdonChipsを使用したゲームシステム
Trance_Mode