はじめに
Unity WebGL x WebSocket でたくさんのオブジェクトを同期する前回の仕組みを利用して、データの永続化の実験をしてみました。
デモ
マイクラもどきです。全員がログアウトしてもデータをサーバに保持しておくようにしました。みなさんのご協力のお陰で面白い空間ができたと思います!ありがとうございます。
よくよく考えると別に WebGL ビルドしなくてもデスクトップアプリとしても動くので同時に配布しました。WebGL だとやっぱり表現力が弱いので見た目はデスクトップアプリのほうが綺麗ですね。
現在は停止しております:
Online DemoWin: https://dl.dropboxusercontent.com/u/7131835/Programs/CrowdCraftOnlineWin.zipMac: https://dl.dropboxusercontent.com/u/7131835/Programs/CrowdCraftOnlineMac.zip
ブロックの数が現状かなり多いので重くて動かない可能性もありますがご了承下さい。
コード
コードは前回と同じ場所にプロジェクト一式あげてあります。
仕組み
基本的には前回と同じ仕組ですが、isSavedToServer
フラグの立ったオブジェクトに紐付いたコンポーネントはサーバ側に永続化されるようにしました。例えば保存されているファイルは以下の様な感じです。
これを各クライアントのログイン時に送って復元しています。後は前回と同じようにログインしている各クライアントのローカルな情報を随時サーバ経由でブロードキャストします。
反省
バグをいくつか出しながらも、みなさんのご協力のお陰で何とか遊べるレベルにはなったのではないかと思います。
ただ、オブジェクトはいくらでも置けるようにした結果、現在保存されているデータは 31000 行くらいあり、ブロックに1つにつき位置情報を保存するコンポーネントと色情報を保存するコンポーネントがついているので、合計で 15000 個くらいのブロックが置かれていることになります。ご体験いただいた or お察しの通りめちゃくちゃ重いです。
重い原因は一番はブロックの描画、二番目が MonoBehaviour.Update()。後者は汎用的な作りにした関係上仕方ないけど、前者は何とかしたいなぁ。どうすりゃいいんだろ。シェーダ軽くしようかな。
— 凹 (@hecomi) 2015年1月6日
後者は、仕組み的に分散してオブジェクト管理する方式やめてマスターが居る方式にすれば軽くなると思う。今は WebSocket + サーバでデータ保持だけど、マスターいる方式で WebRTC + LocalStorage or IndexedDB も検討したい。
— 凹 (@hecomi) 2015年1月6日
この後、renderer.material.color
にアクセスするとマテリアルのコピーが走るのでキャッシュしてダイナミックバッチングが効くように、とか色々調整してちょっとは軽くなりましたが、それでもまだ重くてしんどいです。ブロックは Particle System で描いてコライダだけ GameObject にするとか、何か色々と工夫しないと厳しそうな感じがしますが、これだけ大量のオブジェクトを同期するのは特殊ケースだと思うのと、このゲームのためだけに最適化しても微妙な気がするので次に移ろうと思います。
おわりに
今回は実験も兼ねていたので、どれくらい行けるか制限を設けずにやってみましたが、思っていたよりはうまく動いたと思います。次は AI をどう動かすかの実験か、WebSocket x サーバデータ保持に代わる WebRTC x LocalStorage の実験をしてみようと思います。