Photonの使ったオンラインゲーム開発の方法は、
本ブログをはじめ、ネットで調べると出てきます。
ただ、いくら情報量の多いUnityとはいえ、
基礎的なノウハウの解説でとどまり、
独自に作り込んでいくには、試行錯誤して開発していかねばなりません。
本記事で取り上げるPhotonの"カスタムプロパティ"という機能は
オンラインゲーム開発では、とても基礎的なことではありますが、
開発初心者にとっては専門用語が多く、取っつきにくいと思われます。
カスタムプロパティとは、
情報や設定を、ルームやプレイヤーにもたせることができる機能です。
ここでは、 初心者の気持ちがよくわかる私が
もっとかみ砕いて解説していきます。
1.カスタムプロパティはどんな時に使う?
オンラインゲーム開発では、
同じルーム内で一緒に遊ぶプレイヤーたちと、
常に情報を共有するように、設計しなければいけません。
あるプレイヤーのHPが減少したという情報は、
RPCメソッドとして、減少させるプログラムを組めば、共有されます。
しかし、このような情報は、通常シーンが変わるとリセットされ、
減少したHP情報を、持ち越して、再度共有しなければいいけません。
(可能ではあるけれど、処理が増えてしまいます)
シーンが変わってもリセットさせたくない情報は、
カスタムプロパティを使えば、
とてもシンプルに共有される情報を扱うことができます。
HPは通常1つのシーンで扱うので、RPCメソッドで良いでしょう。
しかし、例えば、
前のシーンでキャラクターやゲームルールを選択してシーンを移動する場合、
選んだ情報を引き継いで、
次のシーンでキャラクター生成、ゲームルールの適用が行われる必要があります。
ここで取り扱われる情報とは、
・キャラクター生成は、各プレイヤーがそのキャラクターを選んだ情報
・ゲームルールの適用は、ルームのホスト(MasterClient)が設定した情報
となります。
前のシーンで、これらの情報をカスタムプロパティとして保存し、
次のシーンで読み込みます。
そして、カスタムプロパティは、
冒頭で、ルームまたはプレイヤーにもたせる機能だと説明しましたが
●キャラクターを選んだ情報は、プレイヤーに対して保存したカスタムプロパティ (CurrentRoom.CustomProperties)
●ゲームルールを設定した情報は、ルームに対して保存したカスタムプロパティ (LocalPlayer.CustomProperties)
です。
ルームのそれは、全員に共通の情報で、
プレイヤーのそれは、各プレイヤーがもつ情報(それは共有される)
ということで、カスタムプロパティのタイプを使い分けます。
このようにゲームとしては
必須であろう設定、選択した情報を扱うのにカスタムプロパティは使われるわけです。
そして、
カスタムプロパティが情報を保存する仕組みは、Hashtableです。
Dictionaryのような連想配列だと思ってもらえば、わかりやすいと思います。
Dictionaryに関しては、
下の記事で即使えるようにまとめてます↓
Hashtableは、Dictionaryの劣化版?
Object型として情報を格納するモノです。
(Dictionaryは、string型やint型など任意の型で格納できる)
さて、自分がやりたいこととカスタムプロパティの機能は合ってそうですか?
ここまで理解できていれば、もう十分です!
では、実践的な内容をみていきましょう。
2.具体的なコード
それでは、カスタムプロパティを実装するコードを紹介します。
(基本の使い方は、Dictionaryとほぼ同じです)
*Photonを扱うので、「using.Photon.Pun」をスクリプト冒頭に記載しましょう。
2−1. ルームに対するカスタムプロパティ
カスタムプロパティの設定
まずは、宣言の部分。
Startメソッドや適当なメソッドなど、カスタムプロパティに情報を保存したい時に記載すればOKです。
ExitGames.Client.Photon.Hashtable gameRuleProp = new ExitGames.Client.Photon.Hashtable();
長ったらしく難しそうですが、
「ExitGames〜Hashtable」は、Photonで共有されるHashtable機能を使うための決まり文句と捉えれば、単純です。
gameRulePropは、任意の変数です。
ここでは、前のシーン(メンバーが集合するルームなど)で、
マスターがゲーム時間を決めることを想定してください。
そして次に
gameRuleProp.Add("TIME", 120); PhotonNetwork.CurrentRoom.SetCustomProperties(gameRuleProp);
1行目では、gameRulePropという配列に
"TIME"というKeyで、120というValueの要素を格納しました。
2行目では、現在のルームにカスタムプロパティを適用する処理です。
カスタムプロパティの読込
先ほど格納した情報を、ゲーム開始時や任意のタイミングで取り出し、適用します。
if(PhotonNetwork.CurrentRoom.CustomProperties.TryGetValue("TIME", out object setTimeObject))
{
battleTime = (int)setTimeObject;
}
エラーを吐かないように、
if文で"TIME"というKeyをもつ要素があり、
オブジェクト型(任意の変数setTimeObject)として出力できることを確認した後、
そのValue(120)をint型として、任意に設けておいた変数battleTimeに代入します。
(int(またはfloat) battleTime; とスクリプト内で宣言しておきましょう)
配列gameRulePropは、
前のシーンなどで〜.SetCustomProperties(gameRuleProp);
という処理をすると、以降は使わないところがポイント。
あとは
battleTime -= Time.deltaTime;
で時間を減らす等して、制限時間のあるゲームをスタートさせます。
私の作ったオンラインゲーム"Our Casual Battlefield"では、
時間だけでなく、どんな特別なルールにするか、どんなMonsterを登場させるか、というのも同様に実装させています。
よかったら、一度触って確かめてみてね^^
2−2. プレイヤーに対するカスタムプロパティ
カスタムプロパティの設定
まずは宣言。
ルームと概ね同じです。
ここでは、あえて「宣言」と「配列名.Add」を一挙に処理するコードを示します。