FJCT_ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

Unity×NCMB。Unityゲームにハイスコア保存機能を追加しよう

では前回に続いて今回はランキング機能を追加する下準備となる「ハイスコアをサーバに残す」機能を追加します。

HighScore GameObject/クラスの作成

まず menuシーンを表示して、空のGameObjectを作成します。名前は HighScore とします。

次に Assets/Standard\ Assets/Scripts/ に新規 C#クラスを作成します。名前は HighScore とします。

内容は次の通りです。

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

public class HighScore : MonoBehaviour {
    public int score   { get; set; }
    public string username { get; set; }
    
    // サーバーにハイスコアを保存 -------------------------
    public void save()
    {
        // データストアの「HighScore」クラスから、Nameをキーにして検索
        NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("HighScore");
        query.WhereEqualTo ("Name", username);
        query.FindAsync ((List<NCMBObject> objList ,NCMBException e) => {
            
            //検索成功したら    
            if (e == null) {
                objList[0]["Score"] = score;
                objList[0].SaveAsync();
            }
        });
    }
    
    // サーバーからハイスコアを取得  -----------------
    public void fetch()
    {
        // データストアの「HighScore」クラスから、Nameをキーにして検索
        NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("HighScore");
        query.WhereEqualTo ("Name", username);
        query.FindAsync ((List<NCMBObject> objList ,NCMBException e) => {
            
            //検索成功したら  
            if (e == null) {
                // ハイスコアが未登録だったら
                if( objList.Count == 0 )
                {
                    NCMBObject obj = new NCMBObject("HighScore");
                    obj["Name"]  = username;
                    obj["Score"] = 0;
                    obj.SaveAsync();
                    score = 0;
                } 
                // ハイスコアが登録済みだったら
                else {
                    score = System.Convert.ToInt32( objList[0]["Score"] ); 
                }
            }
        });

    }

    public string print()
    {
        return username + ' ' + score;
    }

    private HighScore instance = null;
    void Awake ()
    {
        if (instance == null) {
            instance = this;
            DontDestroyOnLoad (gameObject);
            
            string name = gameObject.name;
            gameObject.name = name + "(Singleton)";
            
            GameObject duplicater = GameObject.Find (name);
            if (duplicater != null) {
                Destroy (gameObject);
            } else {
                gameObject.name = name;
            }
        } else {
            Destroy (gameObject);
        }
    }

}

ユーザクラス同様にシングルトンにしています。そしてfetchでニフティクラウド mobile backendから取得、saveで保存処理を実行しています。

スクリプトはGameObjectにアタッチしてください。

ゲーム終了時の処理を変更

デフォルトのままではゲーム終了時にすぐ再開するようになっています。それをいったんメニュー画面に戻りつつ、高得点だった場合にデータを保存するように変更します。

Assets/2dspaceshooter/Scripts/shiphealth.js の death メソッドを変更します。

//on death we need to do some stuff so the ship can look like it explodes and the gameover text shows up.
function death () {
  //here we turn off a bunch of stuff like the renderer and scripts for the ship so its not controllable or viewable by the player anymore, and not able to be hit by enemies.
  var playerControls = gameObject.GetComponent(playercontrols);
  var weaponSystem = gameObject.GetComponent(weaponsystem);
  var fire = GameObject.Find("fire");
  playerControls.enabled = false;
  weaponSystem.enabled = false;
  fire.renderer.enabled = false;
  collider.enabled = false;
  renderer.material.color.a = 0.0;

  //here we turn the game over text back on
  gameOverText.guiText.enabled = true;
  // ここから追加
  var score = weaponSystem.getExp();

  if (FindObjectOfType(UserAuth).currentPlayer() == null) {
  }else{
    var highscore = FindObjectOfType(HighScore);
    Debug.Log(highscore);
    if (highscore.score < score) {
      highscore.username = FindObjectOfType(UserAuth).currentPlayer();
      highscore.score = score;
    highscore.save();
    }
  }
  // ここまで追加
  //here we wait for 3 seconds so the scene doesn't load right away again.
  yield WaitForSeconds (3);
  //here we find the name of the scene we were just playing, and load it again.
  //var lvlName:String = Application.loadedLevelName;
  Application.LoadLevel("menu"); // 戻り先を変更
}

ここで必要になるスコアを返すメソッドを Assets/2dspaceshooter/Scripts/weaponsystem.js に追加します。

private var exp:int = 0;
  :

function expUp (totalExp : int) {
    exp = totalExp;
}

function getExp() {
  return exp;
}

expをアップする処理を Assets/2dspaceshooter/Scripts/experiencemanager.js に追加します。

private var totalExp:int = 0;
function Update () {
  :
    SendMessage("levelup", level, SendMessageOptions.DontRequireReceiver);
  }
  SendMessage("expUp", totalExp, SendMessageOptions.DontRequireReceiver);
}

//if an orb hits the player, we gain experience. (expAmount)
function OnTriggerEnter (other : Collider){
  if(other.name == "exp(Clone)"){
    expAmount += 1;
    totalExp += 1; // 追加
    Destroy(other.gameObject);
  }
}

メニュー表示時にハイスコアを取得

続いてゲームメニューを表示した際にハイスコアを取得し、表示するようにしましょう。menuシーンを表示します。そして、GUI Textを追加して名前をhighscoreとします。

GUIrescalerをアタッチします。
GUIrescalerをアタッチします。
Inspectorは次のようになります。

  • Position : X 0.05 / Y 0.15 / Z 0
  • Text : 0
  • Font : score
  • Font Size : 30

続いて Assets/2dspaceshooter/Scripts/menu.js を修正します。Update メソッドの追加と、Start メソッドの修正です。得点の記録用変数とGUI Textも追加します。

var exp:GUIText;
var highScore:int;
  :
function Update() {
    if (FindObjectOfType(HighScore).score > highScore) {
        highScore = FindObjectOfType(HighScore).score;
        exp.text = highScore + '';
    }
}

function Start() {
    if (FindObjectOfType(UserAuth).currentPlayer() == null) {
        logoutButton.text = "Login";
    }else{
        userName.text = FindObjectOfType(UserAuth).currentPlayer();
        var highscore = FindObjectOfType(HighScore);
        highscore.username = userName.text;
        highscore.fetch();
    }
}

ログインしていればハイスコアを取得します。その結果をUpdateメソッドの中で反映します。

ここまで終わったらmenuシーンに戻って、GUIの中にあるExpにhighscoreをアタッチします。

実行して確認

menuシーンを実行します。そしてログインして戻ってくると、ハイスコアが反映されているのが分かります。

さらにゲームを開始してハイスコアを取得すると、それがニフティクラウド mobile backendにも反映されるのが分かるかと思います。


ここまでがハイスコアを記録、表示する仕組みになります。次回はいよいよハイスコアランキングを表示する仕組みに入りたいと思います。