ニコ生ゲームを作ろうと思ったら物理的に考える その7
物理回の最後は物理マルチゲームについてです。
結論を先にいうと、厄介な不具合が発生する恐れがあります。
その際の注意点を紹介していきます。
今回の記事用に作ったゲームはありませんが、以下の過去作が物理マルチです。
残念ながらソースコードは公開していません。
昔の書き方がメチャクチャでお見せできないためです。
■目次
- 物理マルチで発生する不具合
- 展開ズレの事例
- 物体配置時の注意点
- 公式提供の修正パッチ
物理マルチで発生する不具合
物理マルチ特有の不具合として、プレイヤーごとにゲームの展開が異なってくるというものがあります。
よくあるのが最後のスコア結果がプレイヤー毎に違っていて発覚するケースです。
呼び方としてはパラレルワールドとか違う世界線などと呼ばれることもありますが、個人的には展開ズレと呼んでいます。
一般的には同期ズレという言葉がありますが、Akashic Engine のマルチは同期はさせていません。やろうと思えば同期もできるはずなんですが技術が足りずやっていません。
冷静に考えたら同期の処理はしていませんが、一致している状態を「同期している」と呼んでいい気がしてきました。同期ズレでいいと思います。
この展開ズレはプレイしている環境のブラウザ(chrome,firefox,ニコ生アプリ等)が異なると発生しやすいイメージがあります。しかしプレイヤーの報告を聞いていると同じブラウザでも発生していそうです。
展開ズレの事例
1つ目はエアリアルサッカーでの事例で、こちらの画像になります。
これは左がChromeでプレイした映像で、右がFireFoxでプレイしています。
下にある135度の角に向かって四角い物体で体当たりをしているのですが、左右で跳ね返る方向が大きく変わっています。
2つ目はドアラッシュでの事例ですが、こちらの動画になります。
四角い角をぎりぎり通り抜けようとしてあたったことになるかどうかで、大きく結果が変わってしまっています。
物体配置の注意点
1つ目の事例は、実はこの135度の角に2つの物体がありました。
下のようなイメージです。
このせいでどちらの物体に衝突したことになるかで、大きく反射角度が変わったのではないかと思っています。
これは三角形を作るのがめんどくさかっただけなのですが、不具合を回避するため領域が重ならないように三角形を配置しました。
この対策はうまく行ったようで、たまに発生していたレベルのものが全く発生しなくなりました。
結論として物体配置の注意点としては「衝突が起こりうる角には物体を重ねない」になります。
そもそもの理想としては一つの物体で作ってしまうことです。
ただ、このときは坂と坂の上で摩擦の設定を変えたかったので、苦肉の策で別の物体として配置していました。
公式提供の修正パッチ
2つ目の事例は物体の重なりは無く、単純な四角形と単純な円形の衝突でした。
これは公式にも質問してみたのですが、三角関数の誤差がブラウザによって異なることがあるようで、それが原因だったのではと思っています。
小数点以下10桁というレベルですが、計算の過程で増幅して結果が変わってしまう事があるそうです。
対策としてこちらのpatchBox2DMathの項目にあるパッチを適用しました。
導入方法ですが、パッチのファイル自体はakashic-box2dをインストールしたときについでに導入されています。
ゲーム内で使用できるようにするのに以下の2つが必要です。
- game.jsonへの登録
追加した追加機能はgame.jsonに登録する必要があります。
akashic-box2dはインストール時に登録されますが、patchは手動で追記します。
追記内容は moduleMainScriptsに1行、globalScriptsに3行あります。
"moduleMainScripts": {
"@akashic-extension/akashic-box2d": "node_modules/@akashic-extension/akashic-box2d/lib/index.js",
"@akashic-extension/akashic-box2d/patch": "node_modules/@akashic-extension/akashic-box2d/patch/index.js",
"box2dweb": "node_modules/box2dweb/box2d.js"
},
"globalScripts": [
"node_modules/@akashic-extension/akashic-box2d/lib/Box2D.js",
"node_modules/@akashic-extension/akashic-box2d/lib/ContactManager.js",
"node_modules/@akashic-extension/akashic-box2d/lib/index.js",
"node_modules/@akashic-extension/akashic-box2d/lib/parateters.js",
"node_modules/@akashic-extension/akashic-box2d/patch/box2d.js",
"node_modules/@akashic-extension/akashic-box2d/patch/math.js",
"node_modules/@akashic-extension/akashic-box2d/patch/index.js",
"node_modules/box2dweb/box2d.js"
] - main.jsへの登録
akashic-box2dと同じように以下の文字列を追加します。
let patch = require("@akashic-extension/akashic-box2d/patch");
patch.patchBox2DMath(box2d, { tableSize: 8192 });
ただし、記載場所はbox2dの後ろである必要があります。
let box2d = new b2.Box2D(world); のような行があればその後ろです。
導入できているかどうかを知る方法はわかりませんが、エラーはなくなると思います。
ドアラッシュに関してはちょくちょく起きていた不具合を抑制する効果がありました。
ただし、展開ズレを完全に無くせたわけではありませんでした。
こちらもざっくりとした対策として、物体を回転させたり曲線の動きで三角関数を多用するのは避けたほうがいいかもしれません。
ただし、この指針の効果は確認できていません。
Akashic Engine関連の書き方紹介はおそらく今回で終わりです。
特にプログラミングに詳しくもないのに偉そうな記事を書くのは抵抗がありましたが、Akashic Engine関連で調べた結果を記録していけばいつかうっすらと参考にされる機会があるんではないかと思い続けてきました。
一方で記事に紹介できるような書き方を優先して、ゲームの面白さの優先順位を下げてゲームを作ってきてしまった感があります。
更にまた一方ではモチベーションを保つためサンプルをニコ生ゲームとしてリリースしつつゲームに盛り込む要素もこだわってしまい、参考にしやすいシンプルな形にはなっていなかったとも思います。
色々反省は多かったですが、得た代償として最後まで続けられたと考えればまあいいかというところです。
この記事以外にも、コピペできそうなコードや解説を公開しています。
こちらに記事のリンクがまとまっていますので御覧ください。