Blog ブログ
Archive
OLDER
2018.05(1)
2018.04(1)
2018.03(2)
2017.11(2)
2017.10(1)
2017.08(1)
2017.07(4)
2017.06(3)
2017.05(2)
2017.04(3)
2017.03(2)
2017.02(2)
2017.01(2)
2016.12(3)
2016.11(3)
2016.10(3)
2016.09(3)
2016.06(2)
2016.03(1)
2016.02(1)
2016.01(2)
2015.12(4)
2015.11(1)
2015.10(3)
2015.09(3)
2015.08(3)
2015.07(2)
2015.06(6)
2015.05(2)
2015.04(2)
2015.03(5)
2015.02(8)
2015.01(2)
2014.12(4)
2014.11(2)
2014.10(1)
2014.09(1)
格闘アクションゲームのリアルタイム通信2
皆様こんにちは。
プログラマの島鼻と申します。
前回に引き続き通信処理について基本的な部分を解説してみたいと思います。
社内で行った勉強会を幾つかの回数に分けてお送りします。
前回の記事はこちらです。
もくじ
前回下記のような説明をしました。
相手の入力値が分かれば、互いにどのような操作をしているのかがわかります。
1フレームずつ相手と自分のプレイヤーの動きを再生すれば理論的に「同時(厳密ではない)」にプレイできるわけです。1フレーム単位で「じゃんけん」をしているようなイメージです。
しかし、ここにはある前提条件があります。
それが但し書きの下記です。
さて、1フレーム毎に動きを合わせるというのどういうことでしょうか?
自分の操作情報が決まって(相手にも送信)、相手の操作情報が送られてきます。
するとそのフレームに必要な情報が揃っているので1フレーム動きます。
理論的にはこれで問題なく動作しそうです。
ここまではすごく当然のことですね。
これはどういうことなのでしょうか?
各端末で同じように動かせば、当然同じ結果が得られるのではないでしょうか?
アクションゲームのリプレイ機能を作成したことがある方はピンとくるかもしれません。
ここで登場するのがコンピュータにおける不確定要素です。
主にリプレイ機能を作る上で障害になってくる部分でもあります。次章で簡単にリストアップします。
もくじ
- どうやって同期するのか?
- 再現(リプレイ)する。
- コンピュータにおける不確定要素
- 不確定要素「変数」に挑む
- まとめ
リプレイ機能を作る時、プレイ時と再生時で条件が異なることによるリプレイずれが起こることがあります。つまり、同じ入力を与えているのに、プレイ時と異なる動作をしてしまい最後まで再現が出来ないのです。
どういう場合に起きてしまうのか下記にまとめてみました。
結構たくさんあります。この他にも存在するかもしれません。ここにあるものはほんの一例で、どのゲームでも起きてしまうような事項です。
一つずつ見ていきましょう。
記録時の入力タイミングと再現する時に入力を与える処理順番が違う場合
リプレイ機能を追加する上でも、一番初歩的なミスです。入力を受け取ってから様々な処理を実行する訳ですが、例えば、そのフレームに使用するキー入力を決定した直後にキーを記録するのと、全ての処理が終わってからキーを記録するのとでは「その瞬間のキー入力」は変化している可能性があります。必ず、そのフレームで使用するキーを決定し、そのキーを記録するようにしなければ再現時に違う結果を生み出してしまいます。
また、再現時に記録したキーを更新するタイミングを記録時とは違うタイミングで更新してしまうと、実行される処理が違う結果を生み出してしまいます。
擬似乱数
こちらもよくあるミスですが、リプレイの記録及び、通信対戦の前にゲームに影響のある擬似乱数は初期化しておかなければなりません。通信対戦、リプレイの再現が始まる前にどれだけ擬似乱数が使われたかで、擬似乱数の返す値が異なってしまいます。
未初期化の変数
静的な変数に要注意です。この変数はゲームを起動している間、意図的に実装しなければ再初期化されることはありません。見落としがちですが、通信対戦やリプレイの記録、再現の前に同じ環境を作っておかなければなりません。
スレッドの実行タイミング
もしかして非同期で動作する処理がゲーム内に無いでしょうか?スレッドはコンピュータのリソース状況によりいつ処理が戻ってくるかは分かりません。インゲーム内にこの処理が依存している処理がは外しましょう。
システム時間及び、システム時間を使った動作
同じ処理が必ず同じ時間で完了するとは限りません。フレームがズレれば、その後の処理は異なる結果を出していくことでしょう。意外と忘れがちですが、システム時間で同期を取ってしまったり、システム時間で動いているものの完了を待って処理してしまったりするのは、よくある同期ズレの原因です。
当たり判定に擬似乱数を使うAPI
こちらも、ゲーム内で使用する乱数と統一しておかなければ、統制を取るのが難しくなります。
もし、サードパーティ製のシステムを使う場合はチェックしておくべきでしょう。
描画スレッドに処理を書く
これもよくある間違いです。描画スレッドは処理が重くなった場合その時々に応じて、処理をしないフレームがでてくる場合があります。そして、そこにゲームに必要な処理を書いてしまうと処理されたり処理されなかったりのズレが、まったく違う結果を生み出してしまいます。
不動小数点数
これはコンシューマ機のような規格が決まりきっているものであれば問題ありません。
PCで動作するようなアプリケーションの場合、CPUの違いから浮動小数点の丸め誤差が蓄積し、違う結果を出す原因となる場合があります。なるべく誤差の起き難い計算方法に工夫する必要があります。
キーコンフィグ
当然のことながら、対戦相手のキーコンフィグが変更されていると、変更点を知っておかなければなりません。キー入力と期待したボタンのアサインが違うと違う結果を生み出してしまいます。
少しだけ、リアルタイム通信でやらなければならないことが見えてきたでしょうか?
今回はここまでとします。
次回で、一旦完結です。
今回はこの辺に致しましょう。
採用情報
クラウドクリエイティブスタジオではプログラマを募集しております。
一緒に面白いゲームを作っていきましょう!