サーバー構築不要!スマートフォンアプリ向けの新クラウド

トップ >ドキュメント >チュートリアル(Unity):ステージにコメントを残す

チュートリアル(Unity)

ステージにコメントを残す

概要

このページでは、mobile backendを使ってプレイヤーのコメントを保存・表示する機能を実装します。

プレイヤーが敵の攻撃を受けてゲームオーバーになった際に、メニュー内の「Comment」ボタンを押すことで、ゲームオーバーになった「場所」にコメントを残せるようにします。他のプレイヤーがその「場所」に差し掛かると、かつてその場所で残されたコメントを表示します。mobile backendを使えば、このような非同期的なコミュニケーションを実現することも可能です。

コメント入力

コメント表示

なお、ログイン機能を実装していない場合は、「ログイン機能を作る」を先に済ませておいてください。

今回のチュートリアルで解説しているプロジェクトの完成版は以下のリンクからダウンロードできます。

Waveについて

今回のサンプルゲームでは、敵が編隊を組んで登場します。この編隊のことを「Wave」といいます。このゲームでは、5種類のWaveが決まった順にループして現れます。

今回のチュートリアルでは、ゲームオーバー時に「どのWaveで倒されたか」を記憶しておき、他のプレイヤーが当該Waveに差し掛かったときにコメントを表示するようにします。1つのWaveにコメントが複数ある場合は、その中から1つをランダムに選んで表示させます。

シーンファイルとアセットファイルのダウンロード

下記リンクからzipファイルをダウンロードします。
ダウンロード

解凍すると、以下の3つのファイルが出てきます。

  • Comment.unity ... コメント入力画面を実装するシーンファイル
  • Comment.anim ... コメントを表示させるときのアニメーションを定義
  • CommentGUI.prefab ... コメントを表示するゲームオブジェクトのプレハブ

これら3つのファイルを、以下の手順に沿ってプロジェクトに導入してください。

Comment.unity

プロジェクトの「Scenes」フォルダにドラッグしてコピーしてください。その後、Unityの File → Build Settingsを開き、今コピーしたシーンを「Scenes In Build」に追加(ドラッグ&ドロップ)してください。

CommentGUI.prefab

プロジェクトの「Prefabs」フォルダにドラッグしてコピーしてください。その後、Stageシーンを開き、ヒエラルキーパネルにCommentGUIプレハブをドラッグ&ドロップしてください。

Comment.anim

プロジェクトの「Animations」フォルダにドラッグしてコピーしてください。その後、先ほどStageシーン内に作成したCommentGUIオブジェクトのAnimationコンポーネントに、Comment.animをアタッチします(下図参照)。

Animationのアタッチ

コメントを投稿できるようにする

それでは、まずコメントを投稿してサーバーに保存できるようにしましょう。

mobile backendと通信してコメントを保存する

早速、mobile backendと通信してコメントの保存を行うクラスを作っていきます。Scriptsフォルダの中に「Comment.cs」という名前のC#スクリプトを新規作成し、下記の内容を記述してください。

using NCMB;
using System.Collections.Generic;

public class Comment
{
  public int    wave   { get; private set; }
  public string text   { get; set; }
  public string player { get; private set; }

  // コンストラクタ -----------------------------------

  public Comment(int _wave, string _text, string _player)
  {
    wave   = _wave;
    text   = _text;
    player = _player;
  }

  // サーバーにコメントを保存 -------------------------

  public void save()
  {
    // Commentクラスのオブジェクトをつくる
    NCMBObject obj = new NCMBObject ("Comment");
    // フィールドを設定して保存
    obj["Wave"]   = wave;
    obj["Text"]   = text;
    obj["Player"] = player;
    obj.SaveAsync ();
  }

}

mobile backendにデータを保存するときは、SaveAsyncメソッドを使います。フィールドを設定してからSaveAsyncを実行、という流れがデータストアの基本的な使い方です。

今回は、このComment.csをGame Objectにアタッチしないで使いましょう。ゲームオブジェクトにアタッチせずに使う利点は、以下のようなものがあります。

  • Unityに依存しない (Startメソッドなどを実装しない) コードを書くことができる
  • 他のシーンでも、そのクラスを使うことができる

今回実装したCommentクラスは、MVCデザインパターンでいうモデルクラスにあたります。その場合、このようにUnityに依存しない形でコードを書くほうがよいでしょう。実際このクラスは、Unityを使わずに単体テストを行うことができます。

ゲームオーバーになったWaveを記憶する

ゲームオーバーになったときに、何番目のWaveを遊んでいたのかを記憶するようにします。
ゲームオーバーになると、「Manager」クラスの「GameOver」メソッドが実行されます。また、Waveを管理しているのは「Emitter」クラスです。このクラスが「currentWave」というフィールドを持っているので、GameOverメソッドからEmitter.CurrentWaveを取得してローカルに保存するように実装しましょう。

まず、Emitter.csを開き、currentWaveをpublicにします。

   // 現在のWave
    // privateからpublicに変更し、ゲッターを設定
    public int currentWave { get; private set; }

次に、Manager.csを開き、GameOverメソッドを以下のように編集します。

  public void GameOver() {

    PlayerPrefs.SetInt ("lastWave", FindObjectOfType<Emitter>().currentWave );
    PlayerPrefs.Save ();

    FindObjectOfType<Score> ().Save ();
    // ゲームオーバー時に、タイトルを表示する
    title.SetActive (true);
  }

これで、最後に遊んだWaveが保存できました。

コメント入力画面を作る

Commentシーンに「CommentInputManager」という名前で空のオブジェクトを作成し、同名のスクリプトを新規作成・アタッチしてください。その後、スクリプトを以下の内容に編集してください。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class CommentInputManager : MonoBehaviour {

  public string inputText;

  // ボタンが押されると対応する変数がtrueになる
  private bool submitButton;
  private bool backButton;

  void OnGUI () {
    drawMenu();

    // 送信ボタンが押されたら
    if( submitButton ) {
      // 最後に死んだWaveと、現在のプレイヤー名を取得
      int lastWave  = PlayerPrefs.GetInt ("lastWave", 0);
      string player = FindObjectOfType<UserAuth>().currentPlayer();
      // コメントを作ってサーバーに保存
      Comment comment = new Comment( lastWave, inputText, player );
      comment.save();
      Application.LoadLevel("Stage");
    }

    // 戻るボタンが押されたら
    if( backButton ) {
      Application.LoadLevel("Stage");
    }
  }

  private void drawMenu() {

    // テキストボックスの設置と入力値の取得
    int boxW = 360; int boxH = 50;
    GUI.skin.textField.fontSize = 30;
    int maxLength = 10;
    inputText = GUI.TextField (new Rect(Screen.width*1/2 - boxW/2, Screen.height*1/2 - boxH/2, boxW, boxH), inputText, maxLength);

    // ボタンの設置
    int btnW = 180, btnH = 50;
    GUI.skin.button.fontSize = 20;
    submitButton = GUI.Button( new Rect(Screen.width*1/4 - btnW/2, Screen.height*3/4 - btnH/2, btnW, btnH), "Submit" );
    backButton   = GUI.Button( new Rect(Screen.width*3/4 - btnW/2, Screen.height*3/4 - btnH/2, btnW, btnH), "Back" );

  }
}

ログイン画面や新規登録画面とほとんど同じ構成です。
これで、コメント入力画面が完成しました。

メインゲーム画面とコメント入力画面を切り替える

Manager.csを開き、OnGUIメソッド内を以下のように編集してください。

  void OnGUI() {
    if( !IsPlaying() ){
      drawButton();

      // コメントボタンが押されたら
      if ( commentButton )
        Application.LoadLevel("Comment");

      // これ以降はそのまま
      // ・・・
  }

これで、タイトル画面のボタン押下でコメント入力画面に遷移することができます。

動作確認1

ここまでできたら、1度動作確認をしてみましょう。以下のことが確認できるはずです。ただし、動作確認はLogInシーンを開いてから行ってください。

  • タイトル画面のボタンを押すとコメント入力画面に遷移できる
  • 1度ゲームを遊んでゲームオーバーになってからコメント入力画面に行き、コメントを送信すると、mobile backendの管理画面からコメントが確認できる

コメントの保存確認

コメントを表示する

それでは続いて、コメントを画面に表示する機能を実装していきましょう。

先ほど作成したComment.csを開き、Commentクラスに以下のメソッドを追加します。

  // サーバーからコメントをランダムに取得  -----------------

  public void fetchRandomly (int currentWave)
  {
    // データストアの「Comment」クラスから、Waveをキーにして検索
    NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("Comment");
    query.WhereEqualTo ("Wave", currentWave);
    query.FindAsync ((List<NCMBObject> commentList, NCMBException e) => {

        if (e != null) {
           //取得失敗時の処理
        } else {
           //取得成功時の処理
           if ( commentList.Count != 0 ) {
             //取得したコメントの数を上限として、乱数を生成
             System.Random random = new System.Random();
             int i  = random.Next(commentList.Count);  
             //ランダムに選んだコメントを保持する
             wave   = System.Convert.ToInt32 ( commentList[i]["Wave"]   );
             text   = System.Convert.ToString( commentList[i]["Text"]   );
             player = System.Convert.ToString( commentList[i]["Player"] );
           }
        }
      });
  }

  // コメントを表示するときに使う文字列を整形する
  public string print()
  {
    return text + "\n(by " + player + ")";
  }

データストアに保存されているレコードを検索するときは、NCMBQueryクラスを使います。
WhereEqualToメソッドで条件を指定したあと FindAsyncメソッドでレコードを取得、というのが基本的な流れになっています。
条件の指定方法は、今回用いたWhereEqualTo以外にも色々なものが用意されています。
詳しくはSDKリファレンスをご覧下さい。

次に、Stageシーンに「CommentManager」という名前で空のオブジェクトを作成し、同名のスクリプトを新規作成・アタッチしてください。その後、スクリプトを以下の内容に編集してください。

using UnityEngine;
using System.Collections;

public class CommentManager : MonoBehaviour {

  private int     oldWave;
  private Comment comment;
  private GameObject commentGUI;

  void Start () {
    oldWave = -1;
    comment = new Comment(0, null, null);
    commentGUI = GameObject.Find ("CommentGUI");
  }

  void Update () {
    // waveの切り替わりを監視し、切り替わったらコメントをフェッチ
    int currentWave = FindObjectOfType<Emitter>().currentWave;
    if( oldWave != currentWave)
      {
       oldWave = currentWave;
       comment.fetchRandomly(currentWave);
      }

    // コメントのフェッチが終わったら画面に表示
    // フェッチの完了は、textフィールドが埋まったかどうかで判定
    if( comment.text != null && FindObjectOfType<Manager>().IsPlaying() )
      {
       commentGUI.guiText.text = comment.print();
       commentGUI.animation.Play();
       // 表示が終わったらまたnullに戻す
       comment.text = null;
      }
  }
}

Waveの切り替わりを監視し、切り替わったときに先ほど定義したComment.fetchRandomlyメソッドを実行しています。
これで、Waveの切り替わり時にコメントを取得・表示できるようになりました。

動作確認2

おつかれさまでした!これで、コメント機能の実装がすべて完了しました。LogInシーンを開いてゲームを実行し、コメントが表示されることを確かめましょう。事前にコメントを複数登録しておくと、コメントがランダムに表示されることを確かめられます。

  • ゲームを進めると、画面左下にコメントが表示される
  • Waveにコメントが複数ある場合は、ランダムに1つ選ばれて表示される

コメント表示

お探しの内容が見つからなかった場合はユーザーコミュニティ もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。

推奨画面サイズ1024×768px以上

ページの先頭へ