ページ

2013年12月20日金曜日

実際にPhotonCloudを使ってみる~基本編③~

第一回

第二回

最近諸々あってあまりUnityに触れません。
開発の遅れが少し心配です。

さて、第三回は、前回作成したキューブを各プレイヤーが動かせるようにしましょう。
ですがその前に、PhotonCloudによる同期について説明する必要があります。

そもそも同期とは、複数のゲーム画面で同じ処理を行う、または変数の値を等しくする、という意味です。
PhotonCloudでこれを行う場合、主に2つの方法があります。

①OnPhotonSerialize
継続的に変数を同期します。
設定により、厳密に同期するか、ざっくり同期するか選択可能です。
どちらの場合であっても、モバイル環境ではそれなりに負荷がかかることに注意です。
キャラクターの位置情報の同期などに使用することが多いです。

②RPC
リモートプレジャーコールと言うらしいです。
「リモートプレ…あぁいや、RPCか」なんてカッコつけて使いましょう。
こちらは同期というより、厳密には同じ関数を実行する、という言い方が正しいです。
その際、実行元のプレイヤーが持つ変数が渡された状態で関数が実行されるため、結果的に変数の同期もできるというわけです。
分かりにくいのでいずれ実例を含めて紹介します。
任意で同期することができるため、例えば誰かが被弾してHPが減ったとき、その情報を渡しつつ、HPバーを更新する、なんてことができます。

以上、二種類の方法がありますが、今回は移動の同期のため、上記の継続的な同期を使用します。

それではまず、移動できるように物理演算を付加し、キー入力によって動作するようにします。

新たに「moveTarget.cs」を作成し、以下のように記述します。

「moveTarget.cs」

using System.Collections;

public class moveTarget : MonoBehaviour {

private Rigidbody myRigid;
private bool upSw;
private bool downSw;
private bool leftSw;
private bool rightSw;

void Start () {
//一応リジッドボディをキャッシュ
myRigid = this.gameObject.GetComponent();
}

void Update () {
//上
if( Input.GetKey(KeyCode.UpArrow) ){
upSw = true;
}else{
upSw = false;
}
//下
if( Input.GetKey(KeyCode.DownArrow) ){
downSw = true;
}else{
downSw = false;
}
//左
if( Input.GetKey(KeyCode.LeftArrow) ){
leftSw = true;
}else{
leftSw = false;
}
//右
if( Input.GetKey(KeyCode.RightArrow) ){
rightSw = true;
}else{
rightSw = false;
}
}

void FixedUpdate(){
if(upSw){
myRigid.AddForce(Vector3.forward * 10f);
}else if(downSw){
myRigid.AddForce(Vector3.forward * -10f);
}else if(leftSw){
myRigid.AddForce(Vector3.right * -10f);
}else if(rightSw){
myRigid.AddForce(Vector3.right * 10f);
}
}

}

ざっくり解説すると、
このスクリプトがアタッチされたオブジェクトのリジッドボディを取得し、
それに対してAddForceで力を加えています。
これの制御をキーボードからのキー入力で行っているわけですね。
PhotonCloudと無関係なので、詳しくは自力で何とかしてください。

これを前回作成したプレファブにアタッチします。
その際、リジッドボディを付加することを忘れないでください。
リジッドボディのパラメータはDragを1、UseGravityをオフに、FreezePositionからYにチェックを入れて下さい。
画面を見やすくしたいので、カメラのトランスフォームを変更します。
位置をx:0, y:40, z:0に、角度をx:90, y:0, z:0と入力して下さい。



一旦ビルドして動かしてみましょう。
このスクリプトではキーボードの矢印キーに対応していますので、色々押してみてください。
動きましたか?
なにやら動けば成功です。
一度ウインドウを閉じ、今度は多重起動してみましょう。

すると、あれれ、どちらのオブジェクトも動きやがりましたね。
オブジェクトがどのプレイヤーから生成されたものなのかを判別し、 自分の物だけ動くようにしましょう。

先ほどの「moveTarget.cs」に以下のように追記します。

「moveTarget.cs」

using UnityEngine;
using System.Collections;

public class moveTarget : MonoBehaviour {

private Rigidbody myRigid;
private bool upSw;
private bool downSw;
private bool leftSw;
private bool rightSw;
private PhotonView myPV;

void Start () {
//photonViewを取得し、自分のオブジェクトでなければスクリプト停止
myPV = PhotonView.Get(this);
if(!myPV.isMine){
this.enabled = false;
}
//一応リジッドボディをキャッシュ
myRigid = this.gameObject.GetComponent();
}

《後略》


◆PhotonView.isMine
PhotonViewが自分の物であるか、他のプレイヤーの物であるかを判定します。
自分の物である場合、trueが返されます。

これを使い、自分の物でない場合はスクリプトをオフにしてしまいましょう。
もう一度多重起動して確かめていただくと、一つのオブジェクトしか動かないことが確認できるかと思います。

では、いよいよ同期に入ります。
アタッチしているPhotonViewに、同じくアタッチしているリジッドボディをドラッグします。
リジッドボディと書かれた辺りを引っ張ってみてください。



このように設定できればOKです。
PhotonViewにはトランスフォーム、リジッドボディ、スクリプトなどを格納することができ、
これが同期の対象となります。
スクリプトを同期する場合、具体的に何を同期するのか
「OnPhotonSerialize」による記述が必要です。

それでは多重起動してみましょう!
複数の実行環境で同期して動いているのが確認できたでしょうか。

今回はここまで、次回はRPCについてお話します。

例によって変な部分がありましたら是非お教え下さい。

2013年11月23日土曜日

実際にPhotonCloudを使ってみる~基本編②~

最近PhotonCloudに動きがあったそうで、何やら新しいサービスが開始されるそうです。
この講座が無意味になるような内容じゃなかったら良いのですが・・・。

それでは、前回に引き続き基本編です。
今回のテーマは可視化。
色んな物が見えるようにしてみましょう。

前回の「lobbyMain.cs」 にGUILayoutを追記します。

「lobbyMain.cs」

public class lobbyMain : Photon.MonoBehaviour {

<省略>

void OnGUI(){

GUILayout.Label( PhotonNetwork.connectionStateDetailed.ToString() );

}


}
実行してみましょう。
左上に何やら文字列が表示されましたね?
これが現在のネットワーク接続状況です。
「Joined」と表示されれば無事にルームへと入室できたことが分かります。

◆PhotonNetwork.connectionStateDetailed
現在の接続状況を返してくれる。
デバッグ的に画面に表示させる他、接続が完了するまでは処理をしない、
といった条件判断にも活用できる。


続きまして、ネットワークゲームなので操作できるキャラクターが欲しいところですね。
ということで、

・プレイヤーがルームに入室すると、そのプレイヤーのキャラクターを画面に表示する

部分をまず作ってみたいと思います。


①プレファブの設定

キューブでもスフィアでもなんでもいいので、ヒエラルキーから追加します。
名前を適当に変更します。
この場合は「playerObj」としました。

photon viewというスクリプトをアタッチします。
これは検索で出すもよし、Add ComponentからMiscellaneousを辿って追加することもできます。

それをプロジェクトのResourcesフォルダ内にドラッグし、プレハブを作成した後、ヒエラルキーに残ったオブジェクトを削除します。




②スクリプトの設定

「lobbyMain.cs」に以下のように追記します。

「lobbyMain.cs」

public class lobbyMain : Photon.MonoBehaviour {

<省略>

//ルームに入室したときに自動で実行される
void OnJoinedRoom(){

Vector3 createPos = Vector3.zero;
createPos.x = PhotonNetwork.room.playerCount * 1.5f;
PhotonNetwork.Instantiate("playerObj",createPos,Quaternion.identity,0);

}

void OnGUI(){

GUILayout.Label( PhotonNetwork.connectionStateDetailed.ToString() );

}

}
ウェブプレイヤー辺りで書き出し、 多重起動してみましょう。
以下のようになれば成功です。




窓を増やせば増やすほど、ボックスが増えていきますね。
このボックスがそれぞれのプレイヤーです。

スクリプトの解説ですが、上から
  1. createPosという原点を格納した変数を作成
  2. createPosのx座標を現在のプレイヤー数×1.5に設定
    ※オブジェクトが重なるのを避けるため
  3. ネットワーク上にオブジェクトを作成
という流れになっています。

◆PhotonNetwork.room.playerCount
現在自分がいるルームに何人プレイヤーがいるかを取得

◆PhotonNetwork.Instantiate
Instantiateをルームに入室している全てのプレイヤーで実行させるようなもの。
この命令で作成されたオブジェクトをオンラインで同期することができる。


今回はここまでです。
次回はこのオブジェクトを動かし、その動きをネットワークで同期します。

何かおかしいところがありましたら、是非お教え下さい。

2013年11月13日水曜日

200時間働いたのに時給26円になってしまった話【アプリ収支報告】



私のスマホアプリ第一弾となったペタリーですが、発表から約二ヶ月が経ちました。
DL数や収益も落ち着いてきましたので、ここを区切りとして成果報告をしたいと思います。

何をどうすればどうなるか、という参考になれば幸いです。

ではまずぶっちゃけデータから。

DL数 : 2,930
収益 : \5,187
掲載サイト数 : 4サイト(こちらから申請したものは3)
製作時間 : 約200時間
時給換算 : 約26円

わーお、ブラック起業も裸足で逃げ出しちゃうぜ!
続いて、収益方法と宣伝方法についてご紹介します。

◆収益方法
アプリ内の体力回復アイテム販売
appCを使った成果報酬型広告

◆宣伝方法
facebook, twitterでの告知
レビューサイトへのレビュー依頼


まず今回の出発点はほとんどUnityが分からないという状態でした。
ひよこが描かれた見るからに初心者向けの参考書を片手に制作しています。
そのため、開発のノウハウが無いばかりか、そもそもスマホ市場がどのようなものかすらあまり理解していなかったことが最大の反省です。
 (とはいえ、やらなければノウハウも獲得できないので、反省しつつも手法は正しいと思っています)

もう一つ、このデータからみて大きな反省は、DL数の少なさですね。
広告による収益を主とするなら、DL数はこの100倍は欲しいところです。
appC単体の利益が3800円程度なので、30万ちょっとぐらいは稼げていたかもしれません。

では何故流行らなかったのか、ということについて考える必要があります。
私なりに思うのは、
  1. 初見でゲーム内容が伝わりにくかった
  2. ゲーム内にSNS連携機能を持たせていなかった
  3. 広告宣伝不足
1と2について、現状広告によって利益を出しているゲームはカジュアルゲームが非常に多いです。
すぐに理解できて手軽にプレイできるから、とりあえずやってみようと思えるのではないかなぁと。
内容がよくわからないのでは、プレイするまでいかないということかもしれません。
またこれはレビューする側もそうで、わかりやすいゲームの方がレビューもしやすいのでしょうね。

3について、もうこれは資金不足としか言えないですね。
炎上覚悟でばらまくという手法もありはするんでしょうが、まだそこまで落ちたくないです。


次に、今回の客単価についてです。
純粋にDL数から考えるなら、一人あたりの単価は1円ちょっとです。
あまりよろしくないというか、むしろアウトーです。
何故こういう状態になったのか、考えてみます。
  1. ゲーム性と収益方法のミスマッチ
  2. 広告表示までのタイムラグ
  3. バグ多すぎ
1について、ペタリーはもはやカジュアルゲームという枠から外れています。
主観では全然カジュアルだろと思っていたんですが、そんなことなかったようです。
アーマードコアをやっているとその辺りの感覚が鈍るので注意です。

ただ問題はカジュアルかそうではないか、ということではなく、ペタリーが即座に面白さがわかるタイプのゲームではないことにあります。
即ち、ちょっとプレイしてつまらんからアンインストールするわけですね。
長く遊ばせることが広告収益をあげる一つの方法でありますから、これは宜しくありません。

GooglePlayのレビューの通り、バグに対する文句こそあれ、ゲームとしての文句はほぼありませんので、途中までは無料で、それ以降は有料になるような収益方法の方が良かったのかもしれません。
面白さが分かったユーザーをターゲットにする感じですね。

 2と3について、これは開発力不足ですね。
ゲームが重たいみたいで、広告が表示されるまで少しラグがあったり、場合によっては表示されなかったこともあります。
あとバグですね。
レビューでも散々言われているんですが、そのどれもが再現できなくて原因不明です。
強制終了とか一度も起きてないんですよね・・・。
うーん、端末固有のバグなのかなぁと考えているのですが、にしては多い気が。


では、まとめです。
今回の三代反省点は
  1. 開発力不足
  2. 収益方法のミスマッチ
  3. 宣伝不足(ゲームシステムと予算的な意味で)
かなと思います。
2については次回作にすぐ反映できそうですね。
1についても、うん、今回の制作でレベルが上がったと信じています。
問題は3ですね。
これは誰しもが抱える問題かと思いますが、宣伝なぁー・・・これどうしたらいいんでしょう。


余談ですが、Unityのアセットとレビュー掲載費で1万ぐらい使っているので、時給26円どころか赤字です。
以上、誰かの参考になれば良いのですが・・・

2013年11月9日土曜日

実際にPhotonCloudを使ってみる~基本編①~

それでは今回から、実際のスクリプティングについて解説しようと思います。
誰かのお役に立てれば良いのですが・・・。

なお、解説は全てC#で行います。
悪いことは言わないので、こういう外部のプラグイン的な物を使うときはC#が良いです。
JSだとPhotonCloudのファイルをPluginフォルダに移動したり、ところどころ書き換える必要があるっぽいので。

さて、以前の記事にPhotonCloudについての流れが書いてありますね。
この1~7に沿って実際の構文を記します。


1.ゲームにログイン

 処理的には
  • ゲームロビー(PhotonCloud)への接続
を指します。

「lobbyMain.cs」

public class lobbyMain : Photon.MonoBehaviour {

void Start () {
  
PhotonNetwork.ConnectUsingSettings("0.1");

}

}

以上です。簡単ですね。
これを適当なゲームオブジェクトに追加してあげれば大丈夫です。
ポイントはMonoBehaviourにPhotonを継承して、Photon.MonoBeheviourとすること。
継承って何なのかよくわからないんですが、Photonというクラスで定義された関数やらを使えるようにすること、みたいです。

◆ConnectUsingSettings("0.1")
「0.1」という文字列のロビーに接続する、みたいなイメージです。
使い方としては、ゲームのバージョンアップの際など、新旧のアプリケーションが同じロビーに接続するとまずい時などに使います。
一例ですが、ここを「0.2」にすると、同じ「0.2」と定義されたアプリケーションが同じロビーへと接続されます。


2.好きな部屋を選ぶか、自分で部屋を作って入室

処理的には
  • 現在募集中のルームを検索して、存在すれば入室
  • なければ自分で作成して入室
となります。

「lobbyMain.cs」

public class lobbyMain : Photon.MonoBehaviour {

void Start () {
  
PhotonNetwork.ConnectUsingSettings("0.1");

}

//ロビーに入室した後に自動的に実行される
void OnJoinedLobby(){

PhotonNetwork.JoinRandomRoom();

}

//RandomJoinが失敗したとき(ルームが存在しなかったとき)に自動で実行される
void OnPhotonRandomJoinFailed(){

PhotonNetwork.CreateRoom("testRoom");

}

}

先ほどのスクリプトに追記しました。
OnJoinedLobbyやOnPhotonRandomJoinFaildに関しては、コメント行がそのまま説明です。
詳しいことは分かりませんが、そういうものだと理解してください。
なぁに、車の構造を知らなくても運転は出来るんですよ。私免許持ってないですが。

◆JoinRandomRoom()
存在する部屋を検索し、そのどれかに入室するという意味です。

◆CreateRoom("testRoom")
「testRoom」という名前の部屋を作成し、入室するという意味です。
部屋の名前は重複せず、検索のキーにもなります。


絵的に何の変化も無いのでわかりにくいですが、一応これだけで複数のプレイヤーが同じルームに打ち込まれる処理が完成しました。

次回はもうちょっと絵的に分かりやすくして、条件設定をしてみましょう。

おかしいところがありましたら、何卒ご教示ください。

2013年11月1日金曜日

実際にPhotonCloudを使ってみる~導入編①~

それでは今回から、PhotonCloudを実際にUnityで扱う方法についてお話したいと思います。

まずは導入編。
どこで何をどうするのかについてです。


①PhotonCloud公式からユーザー登録をする
http://cloud-jp.exitgames.com/ こちらからどうぞ
何はともあれユーザー登録です。
登録は特に難しいところもないので割愛しますね。


②UnityへPhotonCloudを導入する
アセットストアにて「photon」 と検索すると以下のようなアセットが見つかりますので、これをUnityへ読み込みます。
 

 
③ PhotonCloudの公式サイトへログインし、AppIDをコピーする


④UnityへPhotonCloudをインポートすると表示される画面からsetupをクリック

後、先ほどのAppIDを入力し、CloudRegionからJapanを選択



このウインドウを閉じ、とりあえずは導入完了です。
PhotonCloudはデフォルトだと同時20接続まで無料です。
ですので、この状態でも開発上でのテストは十分行えますね。

次回はスクリプティングの基礎から行います。


例によって、何かおかしいところがありましたら、是非ご教示ください。

2013年10月25日金曜日

PhotonCloud基礎知識③-ルームとプレイヤーのプロパティ

今回はルームとプレイヤーのプロパティのお話です。

例えば制限人数4名のルームを作成し、そのルームでオンラインプレイをしたいとしましょう。
その場合、ルームに対して「この部屋は最大4人ですよ」という情報を持たせなければなりません。

こうしたルーム自体が持つ情報のことをプロパティと表現します。

最大人数・現在人数や部屋の名前などなど、最低限こういうのは合った方がいいよね!
というものがあらかじめ設定されており、こうしたプロパティにアクセスすることで情報を持ってくるわけです。

同様に各プレイヤーにもプロパティが設定されています。
プレイヤー名や識別IDなどなど、こちらも最低限これはいるよねーというものが用意されています。

以上のように、ルームとプレイヤーに対してプロパティが設定されているのですが、これだけでは作れるゲームに限界が出てきます。

例えば、ルームの情報として最大人数だけでなく、対戦するマップの情報を持たせたい、とか。
ゲームルールがバトルロイヤルなのかチームマッチなのか設定しておきたい、とか。
そうした情報をルームに持たせておけば、その情報によって検索を行い、自分の希望とマッチした空きルームへとプレイヤーを接続させることができるので、便利ですよね。

プレイヤーのプロパティにしても同様で、ゲームの準備が完了しているか情報を持たせるとか、 プレイヤーが赤チームなのか青チームなのかの情報を持たせるとか、色々応用が出来そうです。

このようなユーザーが独自に設定するプロパティのことを「カスタムプロパティ」といいます。
カスタムプロパティを自分で設定することで、様々なゲームのバリエーションに対応できるというわけですね。


というわけで、まとめです。
  1. ルームやプレイヤーにはプロパティと呼ばれる情報が設定されている
  2. プロパティの項目は自分で増やすことができ、それをカスタムプロパティという
続きはまた次回。
お前それおかしいということがありましたら、ぜひご教示ください。

2013年10月20日日曜日

PhotonCloud基礎知識②-ロビーやらルームやら

台風がまた来ているようですね。
かなり勢力が強いようで、このまま直撃しないことを願うばかりです。

さて、引き続き基礎の基礎、PhotonCloudの解説を行いますね。

今回のテーマはロビーとかルームって何?というところです。
PhotonCloudというサーバーにユーザーを接続させ、ゲームを行うわけですが、
この辺りの流れと構造についてご紹介します。

PhotonCloudにはロビーとルームというものがあります。
まずはこの2つの説明から。

①ロビー
いわゆる大部屋です。
PhotonCloudに接続した全てのユーザーは初めにここに通されます。
この状態ではゲームのプレイは不可能です。

②ルーム
実際にゲームを行う部屋だと考えてください。
こちらが指定した条件でルームを作成し、そこにプレイヤーを通して、ゲームを行うようなイメージです。

 なので実際の流れとしては、
  1. ロビーへ接続
  2. 最大人数、ゲームルールなどの設定をしてルームを作成(または検索して入室)
  3. ルーム内のプレイヤーでゲーム開始
という感じです。
意外とこの辺りの構造は「察しろ」と言わんばかりの扱いなので、
この場で説明させていただきました。

調べればわかるけど調べる時間が勿体ないことってよくありますからねー。

もしおかしいところがあればご教示ください。
それではまた次回。

2013年10月18日金曜日

PhotonCloudの基礎知識

アプリで収益を上げると考えた際、その一つの答えはオンラインゲームです。
ソーシャルゲームだってある意味ではオンラインゲームですよね。

私が構想しているのはMOゲームというジャンルで、ネットのFPSみたいなシステムですね。
モンハンみたいな感じといえば分かりやすいでしょうか。

そうしたオンラインに対応したゲームをUnityで制作するとした場合、選択肢は幾つかあります。
ありますが、現状での最適解はPhotonCloudにぶら下がることです。

理由としては、
  • 面倒なサーバーの用意や設定を全てあちらがやってくれる
  • 同時接続数20までは無料
  • ある程度日本語のドキュメントがある
  • Unity押し(ていうかUnity用に作ったんじゃないのかってぐらい)
詳しい方はもっと良い理由を挙げられるのかと思いますが、私にはこれだけで即決するに十分な理由でした。

高校生のときにPhotonを使ってオンラインゲームを制作された方もいるそうで、対抗意識を燃やしたってのもあったりなかったり。

さてさて、そんなPhotonですが、何せ扱う側は7月にUnityを始めたばかりの素人。
色々な困難がありました。
この記事群では、そんなPhotonに関する知識を発信できればなと思います。

後に続く方々のため、そしてその見返りに誰かが何かしてくれることを期待しています。


------------------------------------------


◆そもそもPhotonCloudって何?

千里の道も何とやら、まずは根本的なところからお話します。
簡単に言ってしまえば、Unityでオンラインゲームを作るための仕組みです。
オンラインゲームをされたことがある方なら分かりやすいと思うのですが、
このような流れを見たことはありませんか?
  1. ゲームにログイン
  2. 好きな部屋を選ぶか、自分で部屋を作って入室
  3. その部屋に他のプレイヤーが集まる
  4. 全員が準備完了になるとゲーム開始
  5. オンラインで他のプレイヤーがキャラクターなどを操作し、リアルタイムにプレイ
  6. 何らかの条件でゲーム終了 結果報告へ
  7. 部屋に戻る
PhotonCloudを用いると、大体こんなことができます。
というより、ある種これが全てです。

後はこの応用であり、例えば全てのプレイヤーを自動的に同じ部屋にぶち込むように設定すれば、よくあるオンラインRPGの完成です。
(実際には負荷とか色々怖いですが)

 もちろん、これらの機能はPC、スマートフォン問わずに実現可能です。

注意としては、あくまでゲームを皆でプレイするという機能しか無いとも言えることです。
プレイヤーのデータを保存したりは出来ないよという。


では、まとめです。
  • PhotonCloudを使うと比較的楽にオンラインゲームが作れる!
  • 皆でゲームをプレイするという部分に関する機能を提供する
  • サーバーにデータの保存はできない
以上、何となくご理解いただけたでしょうか。
これだけPhoton,Photonと文にすればSEOはバッチリだね。

初心者の視点なのでミスがあるやもしれません。
「お前それ間違ってるから」ということがあればぜひご教示ください。

2013年10月16日水曜日