UNET② UNETの基本知識

UNETを使えば、TCP/IPのことをあまり意識しなくてもプログラムが書けて、たしかに楽です。しかし、登場するキーワード(機能名やクラス名)のあまりの多さに、入門者は混乱必至です。重要なキーワードや基本知識をいくつか説明します。一度で全ては理解できないと思いますが、サンプルプログラムなどを作ったりした合間に戻ってきて、何度か読み返してみてください。

そもそも呼称がグダグダ

Unityのネットワーク機能は、呼称が統一されておらず複数あり、非常にグダグダなので、Webで検索する時などは気を付けてください。

昔、Unity4の時代では、今とは違うネットワーク機能(NetworkViewとか)が搭載されていました。それがUnity5.1で新しいシステムに刷新されたのですが、当初は「UNET」と呼ばれていました。

しかし、Unity社は途中から「Unity Multiplayer」とか「ネットワーキング」とか呼びはじめて、完全にカオスです。

当ブログでは「UNET」という呼称で統一しています。

HLAPIとLLAPI

UNETの機能は大きく分けてHLAPI(ハイレベルAPI)とLLAPI(ローレベルAPI)の2つに分けられます。
HLAPIのほうが高機能で、Unityが色々と面倒を見てくれるものです。大抵はHLAPIを使えば十分ですが、HLAPIではやりたいことができないとか、もっと限界まで性能をチューニングしたいとか、そういうときはLLAPIを使います。
LLAPIはあまりUnityが面倒を見てくれず、ほとんどのことをプログラマーがやらなければなりません。素のTCP/IP(ソケット通信)のプログラムよりは少し楽だな、というようなものです。
このブログではHLAPIの使い方を紹介していく予定です。

ホスト/クライアント システム

UNETのHLAPIを使って作れるネットワークゲームホスト/クライアント型のゲームです。前回紹介したCEDEC 2010の記事にもありますが、ネットワークゲームの端末同士の繋がり方は色々な方式があって、例えば、サーバー集中管理方式や、P2P方式などがあります。それぞれを軽く説明します。

 

 

 

f:id:motoyamablog:20171028010326g:plain

クライアント/サーバー型
MMORPGFPS等、多くのゲームで一般的な方式です。サーバーが全ての情報を管理し、全てのプレイヤーに情報を配信します。十分な性能のネットワークとサーバーが必要ですが、それが用意できれば、最も安定したプレイを提供できます。

 

 

 

 

f:id:motoyamablog:20171028010404g:plain

P2P
P2Pとはピアツーピアの略です。管理するサーバーなどを介さずに、クライアント端末同士が直接やり取りする方式です。上図のような状態で通信するゲームを私は知りませんが、次のような形のP2Pなら一般的です。

 

f:id:motoyamablog:20171028010452g:plain

↑これもP2Pの一つの形です。これは、格闘ゲームのオンライン対戦で一般的な方式です。

 

 

 

f:id:motoyamablog:20171028010512g:plain

ホスト/クライアント型
UNETのHLAPIを使って作れるゲームはこの方式になります。この方式では、クライアントのうちの1台がホストとなります。ホストは、クライアントであると同時に、サーバーとしての役割も担います。ホストは、各クライアントから情報を受け取り、また各クライアントに送信します。データの流れはクライアント/サーバー型と同様です。違うのは、クライアント/サーバー型のサーバーはゲーム会社が用意したマシンだが、ホスト/クライアント型のホストは、プレイヤーの端末であるということです。
この方式のメリットは、クライアント/サーバー型では必須である専用サーバーを用意する必要が無いことです。数十万人が同時にプレイするようなゲームでは、サーバーの運用コストが馬鹿になりませんが、ホスト/クライアント型では、サーバーを各プレイヤーが担ってくれるために、ゲーム会社の負担が少ないです。
デメリットは、ホストの通信環境が悪いと全プレイヤーに悪影響が及んだり、ホストが落ちたらゲームが終了してしまったり、ホストとそれ以外のクライアントで若干の有利/不利が生じるなどがあります。
2~10人程度で対戦するゲームでよく採用される方式です。スプラトゥーンもこの方式らしいです。

 

ローカルクライアントとリモートクライアント

上記のホスト/クライアント型については理解できましたか?
追加で非常にややこしい話をします。ホスト/クライアント型において、クライアントは当然クライアントなのですが、ホストもまたクライアントであるということです。みんなクライアントなのです。しかし、ただのクライアントと、サーバーも兼ねているクライアントでは明らかに違います。そこで、UNETでは、それぞれの呼び方を区別しています。
ただのクライアントを「リモートクライアント」と呼び、ホストのクライアントを「ローカルクライアント」と呼んでいます。

f:id:motoyamablog:20171028010811p:plain

 

 

ローカルプレイヤー

UNETの資料には「プレイヤー」という単語がよく出てきますが、これは「ゲームを遊んでいる人」という意味ではなく、「プレイヤーオブジェクト(遊んでいる人が操作しているキャラクターのオブジェクト)」という意味です。気を付けてください。
そして、UNETには「ローカルプレイヤー」という概念があります。これは超重要なので確実に抑えてください。

ローカルプレイヤーについて理解するために、話が変わってしまいますが、まずはネットワークゲームではない、普通の1人用のゲームをUnityで作る場合のことを考えてみてください。その場合、プレイヤーキャラを制御するために「Player」とかそういうスクリプトを作りますよね?
で、マルチプレイヤーのゲームに話を移します。マルチプレイヤーなゲームには、プレイヤーキャラクターが同時にたくさん登場します。自分のプレイヤーキャラだけではなく、他人のプレイヤーキャラも画面に出てくるよねってことです。で、普通(?)に考えたら、自分のプレイヤーキャラと他人のプレイヤーキャラは別のプログラムを書いて実現すると思うのですが、UNETは違います。UNETでは、自分のプレイヤーキャラも他人のプレイヤーキャラも、同一のスクリプトで動かします
UNETでは、自分の操作するキャラも「Player」スクリプトで動き、他人の操作するキャラも「Player」スクリプトで動くのです。
同じスクリプトで動かしますが、自分のキャラと他人のキャラでは意味合いが全く異なります。そこで、UNETでは自分の操作するキャラのオブジェクトのことをローカルプレイヤーと呼び、特別扱いします

これは本当に超重要なので、しつこく説明します。
わかりやすく説明するために、オンライン対戦のボンバーマンの画像を拝借します。

f:id:motoyamablog:20171028011009p:plain

上図では、さくらさんと、はまちさんと、たいやきさんと、にくまんさんが対戦しています。
この画面には、4体のボンバーマンが存在します。どれもプレイヤーキャラクターですが、さくらさんの端末におけるローカルプレイヤーは白ボンであり、さくらさんが操作可能なのは白ボンだけです。さくらさんが黒ボンや青ボンを操作することは当然できません。
同様に、はまちさんの端末におけるローカルプレイヤーは黒ボンであり、はまちさんが操作可能なのは黒ボンだけです。
簡単ですね。単純に「ローカルプレイヤー = 自分のキャラ」ということです。
簡単なはずなのですが、いざUNETでプログラムを書いていると、絶対に混乱します。今のうちにしっかり覚えておきましょう。

サーバーによる一元管理

クライアント/サーバー型およびホスト/クライアント型のシステムでは、原則的に、サーバー(ホスト)がゲーム中の主要なデータを全て管理します。各種の処理もサーバー内で行います。例えば、当たり判定とか、その結果プレイヤーがダメージを受けたとか、死んだとかそういう判定や計算も全てサーバーで行います。

f:id:motoyamablog:20171028011202g:plain

上図のように、クライアントは入力情報や、入力の結果生じたコマンドなどをサーバーへ送信します。サーバーはそれを受け取り、当たり判定などを行います。そしてその結果をクライアントへ送信します。クライアントは受信した内容に基づき、画面を更新します(キャラを動かすなど)。

このように作ることが、クライアント/サーバー型およびホスト/クライアント型のネットワークゲーム制作の原則です(原則というからには例外があります。後述します)。この手法にはメリットとデメリットがあります。

サーバーによる一元管理のメリット

  • プレイヤー間の不整合が起きない。例えば、下手な実装をすると「Aさんの画面内でBさんを殺したのに、Bさんの画面では生きてる」とか「ドロップしたレアアイテムをAさんとBさんが同時に拾おうとしたら、二人ともGETできてしまった」とか、そういう問題が起こりえますが、サーバーで一元管理していれば起こりません。
  • チート(不正行為)しづらい。判定処理などはサーバー上で行うので、チートしづらいです。

サーバーによる一元管理のデメリット

  • ラグ(通信遅延)の影響で、操作感が非常に悪くなる。

これはどういうことか説明します。完全に上記の原則に従って実装すると、プレイヤーがコントローラーのボタンを押しても、ゲーム画面はすぐには反応しません。「ボタンを押した」という情報がネットワーク経由でサーバーへ送信され、それを受け取ったサーバー内で何らかの処理(発砲とか移動とか)が行われます。そして、サーバーがクライアントへ処理の結果を送信し、クライアントの画面に結果が反映されます。つまり、操作が画面に反映されるまで、最短でもネットワーク1往復分の時間がかかります。LAN内での通信だったり、インターネットだとしても通信環境が非常に良い場合は、ほとんど気にならないレベルかもしれませんが、大抵は「このゲーム、モッサリしててイライラするわー」ってなります。

というわけで、多くのネットワークゲームがサーバー一元管理方式を採用してはいますが、100%原則に従っているわけではありません。操作感を損ねないために、大抵、プレイヤーの移動処理などはクライアント側で行い、結果(移動後の位置など)をサーバーに送信します。

 

次へ進む

目次へ