編集
このままだとNAT越えできないのでSTUNクライアント機能を記事に含めることを検討しています。
【注意!】対象読者について
残念ながらこの記事はUnityでC#プログラミングがある程度できる人を想定しています。
初心者の方でも実行できるような形で配布していますが、活用する面で難しい部分があるかもしれません。
この記事でできるようになること
リアルタイムオンラインゲームが作れます!!
ただしあなたの努力次第で...笑
この記事はあくまでプレイヤーオブジェクトの同期のみで「その他のオブジェクト、ゲームロジックの同期」には対応していません。
それはオンラインゲームによってはFPSから横スクロールアクションなど、同期するもの/しないものが変わってくるからです。
同じ理由でプレイヤーの移動スクリプトは含まれていません。
ただしプレイヤー同期は含まれているので、それを参考に追加、削除が可能です。
これがUDPをわざわざ使う醍醐味のようなもので、これで「しんどいかも」と思ったら残念ながらPhotonをはじめとする外部サービスを強くおススメします。これ以降は「俺はUDPなんや!ごちゃごちゃうるせえから次いけ!」っていう人中心に読んでもらいたいです。
なのでこの記事を読むと具体的には「プレイヤー2人がわちゃわちゃしているシーン」が作れます。
もしすでにプレイヤー移動の基盤がしっかりしている人であれば、一気にオンラインゲーム実現が近づくと思います。
手順
スクリプト
まずスクリプトは以下で公開しています。これを全コピーしましょう。
便利なエディター拡張
外部の方のエディター拡張で申し訳ないのですが、オンラインゲーム開発には「ParrelSync」がとても便利です。
エディターを2つ起動はできないので、今までデバッグを「ビルドしたゲーム」と「エディター」で行っていたのですが、ParrelSyncを使うとそのような手間なしにエディターを複製することが可能です。
以下のダウンロードページからLatestが付いている「ParrelSync-1.?.1.unitypackage」をダウンロードし、追加したいプロジェクトを開いた状態でダブルクリックしてください。
ParrelSync 紹介フォーラム
github
ダウンロードページ
ParrelSyncがimportできたら上にParrelSyncというボタンができるのでそこから
[Clones Manager]→[Add new clone]→[Open in New Editor]と進みます。
ParrelSyncをダウンロードしたら、EmptyオブジェクトにダウンロードしたMultiplayer.csをアタッチでします。
ここで各プロパティの説明をします。
MyPortはクライアントのポート番号です。
OpponentPortは相手のポート番号です。
例えばParrelSyncでエディターを複製した後に、オリジナルのポートを3000、クローン側のポートを3001とすると、
オリジナルのエディターではmyPortに3000を、opponentPortに3001を、
クローン側のエディターではmyPortに3001を、opponentPortに3000を入力します。
この作業はStart内にClonesManager.IsClone()で条件分岐することで自動化ができます。
EnableSmoothingは受信間を線形補完するかです。
例えば1秒に4回送受信する場合、1/4秒の間は相手が完全に停止していることになります。そこで、1/4秒の間も敵が移動するように
敵の位置を更新の間で線形補完を行います。
Playerは同期するプレイヤーのオブジェクトです。
OtherPlayerObjectsは同期する相手側のオブジェクトです。
実行方法
両方のエディターで再生ボタンを押したのちに、Multiplayerコンポーネントの右上のContextMenuからRegisterを押します。
上の正しい設定をした後に、両方のエディターでRegisterを押すと同期が開始します。
gif動画でフレームが低くなって分かりにくいですが、左上がEnableSmoothingあり、右下がスムージングなしです。
ここで注意するのは赤が各クライアントにおけるプレイヤーオブジェクトであり、それぞれの視点ではそれぞれがプレイヤーなので全体では一致しません。
うまくいかない場合
- Multiplayerスクリプトをアタッチしましたか?
- 動画ではシーンビューでプレイヤーオブジェクトを無理やり動かしています。当然ながら相手のオブジェクトは動かすことができません。
- Portの設定は2つのエディターで交互になるように割り振ってください。詳しくはプロパティで説明しています。
- 必ず再生ボタンを押した後にコンテキストメニューからRegisterを選択してください。
終わりに
さて、ここで実装したのはUDPを使ったP2Pの二人のみの場合の実装です。
また位置、回転以外の同期には対応していません。
それ以外の部分は冒頭に述べたように読者の皆様に作ってもらいます。
オンラインゲームを実装するために、Webアプリを使ったロビーサーバーでIPアドレス、ポートを共有できればこの方法で通信ができます。
サーバー・クライアント方式で実装するためにはさらに高度な制御ロジックが必要です。
この記事がリアルタイムオンラインゲーム実装に役立つことを期待しています。
このスクリプトを理解するには
- スレッドを使っていますが、変更は必要ありません
- メッセージ種類の判別にEnumを使っています
- P2Pの実装のためにNAT越え(NATパンチスルー)を行っています
- BitConverterを使ってfloat⇔byte[]の変換を行っています。