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

トップ >ドキュメント >チュートリアル(Unity):ログイン機能を作る

チュートリアル(Unity)

ログイン機能を作る

概要

このページでは、ゲーム開始時にログイン画面を表示し、ログインや新規プレイヤー登録を行う方法を学びます。
今回は、ログイン画面とメインゲーム画面をそれぞれ別のシーンに分けて実装していきます。
はじめはログインシーンが表示され、ログインに成功したらメインゲームシーンを読み込んで表示します。

画面遷移概要

シーンファイルのダウンロード

下記リンクから、ログイン画面を実装するシーンファイルをダウンロードします。
ダウンロードした「LogIn.unity」を、プロジェクトの「Scenes」フォルダにドラッグしてコピーしてください。

LogInシーンのダウンロード

シーンのコピーが完了したら、Unityの File → Build Settingsを開き、今コピーしたシーンを「Scenes In Build」に追加(ドラッグ&ドロップ)してください。

このシーンには、既に以下のものが実装されています。

  • ログイン画面で表示するテキスト(GUIText)
  • 新規登録画面で表示するテキスト(GUIText)

このページでは、以下の内容を実装していきます。

  • ログイン画面と新規登録画面を切り替える機能
  • mobile backendと通信して、ログイン、ログアウト、新規登録、ログイン中のプレイヤーのIDの取得を行う機能

ニフティクラウド mobile backendの初期設定

mobile backendのアカウント登録がまだの方は、こちらから無料アカウントの登録を行ってください。

下記リンク(クイックスタート)にしたがって、新規アプリ作成とmobile backendの初期化(NCMBSettingsオブジェクトの作成)を行ってください。
このとき、NCMBSettingsは先ほど追加したLogInシーンに作成してください。

クイックスタート(Unity)

mobile backendと通信して、ログインや新規登録を行う

それでは早速mobile backendを使って、ログイン機能や新規登録機能を実装していきましょう。会員管理機能を使うにはNCMBUserクラスを使用します。

LogInシーンに空のGame Objectを作成し、「UserAuth」にリネームします。
その後、同名のC#スクリプト作成し、以下の内容を記述してアタッチしてください。

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

public class UserAuth : MonoBehaviour {

  private string currentPlayerName;

  // mobile backendに接続してログイン ------------------------

  public void logIn( string id, string pw ) {

    NCMBUser.LogInAsync (id, pw, (NCMBException e) => {
    // 接続成功したら
    if( e == null ){
      currentPlayerName = id;
    }
    });
  }

  // mobile backendに接続して新規会員登録 ------------------------

  public void signUp( string id, string mail, string pw ) {

    NCMBUser user = new NCMBUser();
    user.UserName = id;
    user.Email    = mail;
    user.Password = pw;
    user.SignUpAsync((NCMBException e) => { 
    
    if( e == null ){
      currentPlayerName = id;
    }
      });
  }

  // mobile backendに接続してログアウト ------------------------

  public void logOut() {

    NCMBUser.LogOutAsync ( (NCMBException e) => {
    if( e == null ){
      currentPlayerName = null;
    }
    });
  }

  // 現在のプレイヤー名を返す --------------------
  public string currentPlayer()
  {
    return currentPlayerName;
  }

}

ログイン、新規登録、ログアウトはそれぞれ「NCMBUser.LogInAsync」「NCMBUser.SignUpAsync」「NCMBUser.LogOutAsync」メソッドを使います。ここでは、ログイン中はプレイヤーIDを自身のフィールドに格納するようにし、ログインしていない場合はnullをセットするようにしています。

LogInAsyncメソッドのように末尾に「Async」が付いているメソッドは、その名のとおり「非同期処理」を行っています。そのため、接続に成功してプレイヤーIDをフィールドに格納するまでの間、その他の処理が止まることはありません。

なお、SignUpAsyncメソッドでメールアドレスの入力は必須ではありません。しかし、メールアドレスを登録すると、以下のような利点が得られます。

  • パスワードのリセットができる
  • 登録時に本人確認メールの送信ができる

そこで、今回はメールアドレスの入力を必須にしています。

ログイン画面と新規登録画面を切り替える

つづいて、ログイン画面と新規登録画面を切り替えられるようにします。
LogInシーンに空のGame Objectを作成し、「LogInManager」にリネームします。
その後、同名のC#スクリプト作成し、以下の内容を記述してアタッチしてください。
これによって、ログイン画面と新規登録画面をボタンで切り替えることができるようになります。

using UnityEngine;
using System.Collections;

public class LogInManager : MonoBehaviour {

  private GameObject guiTextLogIn;   // ログインテキスト
  private GameObject guiTextSignUp;  // 新規登録テキスト

  // ログイン画面のときtrue, 新規登録画面のときfalse
  private bool isLogIn;

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

  // テキストボックスで入力される文字列を格納
  public string id;
  public string pw;
  public string mail;

  void Start () {

    FindObjectOfType<UserAuth>().logOut();

    // ゲームオブジェクトを検索し取得する
    guiTextLogIn  = GameObject.Find ("GUITextLogIn");
    guiTextSignUp = GameObject.Find ("GUITextSignUp");  

    isLogIn = true;
    guiTextSignUp.SetActive (false);
    guiTextLogIn.SetActive (true);

  }

  void OnGUI () {

    // ログイン画面 
    if( isLogIn ){

      drawLogInMenu();

      // ログインボタンが押されたら
      if( logInButton )
         FindObjectOfType<UserAuth>().logIn( id, pw );

      // 新規登録画面に移動するボタンが押されたら
      if( signUpMenuButton )
         isLogIn = false;
    }

    // 新規登録画面
    else {

      drawSignUpMenu();  
    
      // 新規登録ボタンが押されたら
      if( signUpButton )
         FindObjectOfType<UserAuth>().signUp( id, mail, pw );
      
      // 戻るボタンが押されたら
      if( backButton )
         isLogIn = true;
    }

    // currentPlayerを毎フレーム監視し、ログインが完了したら
    if( FindObjectOfType<UserAuth>().currentPlayer() != null )
       Application.LoadLevel("Stage");

  }

  private void drawLogInMenu()
  {
    // テキスト切り替え
    guiTextSignUp.SetActive (false);
    guiTextLogIn.SetActive (true);
    
    // テキストボックスの設置と入力値の取得
    GUI.skin.textField.fontSize = 20;
    int txtW = 150, txtH = 40;
    id = GUI.TextField     (new Rect(Screen.width*1/2, Screen.height*1/3 - txtH*1/2, txtW, txtH), id);
    pw = GUI.PasswordField (new Rect(Screen.width*1/2, Screen.height*1/2 - txtH*1/2, txtW, txtH), pw, '*');
    
    // ボタンの設置
    int btnW = 180, btnH = 50;
    GUI.skin.button.fontSize = 20;
    logInButton      = GUI.Button( new Rect(Screen.width*1/4 - btnW*1/2, Screen.height*3/4 - btnH*1/2, btnW, btnH), "Log In" );
    signUpMenuButton = GUI.Button( new Rect(Screen.width*3/4 - btnW*1/2, Screen.height*3/4 - btnH*1/2, btnW, btnH), "Sign Up" );
    
  }

  private void drawSignUpMenu()
  {
    // テキスト切り替え
    guiTextLogIn.SetActive (false);
    guiTextSignUp.SetActive (true);
    
    // テキストボックスの設置と入力値の取得
    int txtW = 150, txtH = 35;
    GUI.skin.textField.fontSize = 20;
    id = GUI.TextField     (new Rect(Screen.width*1/2, Screen.height*1/4 - txtH*1/2, txtW, txtH), id);
    pw = GUI.PasswordField (new Rect(Screen.width*1/2, Screen.height*2/5 - txtH*1/2, txtW, txtH), pw, '*');
    mail = GUI.TextField   (new Rect(Screen.width*1/2, Screen.height*11/20 - txtH*1/2, txtW, txtH), mail);
    
    // ボタンの設置
    int btnW = 180, btnH = 50;
    GUI.skin.button.fontSize = 20;
    signUpButton = GUI.Button( new Rect(Screen.width*1/4 - btnW*1/2, Screen.height*3/4 - btnH*1/2, btnW, btnH), "Sign Up" );
    backButton   = GUI.Button( new Rect(Screen.width*3/4 - btnW*1/2, Screen.height*3/4 - btnH*1/2, btnW, btnH), "Back" ); 
  }

}

OnGUIメソッド内では drawLogInMenu() または drawSignUpMenu() を実行しており、それぞれログイン画面と新規登録画面のテキストボックスとボタンを定義しています(mobile backendとは関係のない部分なので、解説は省略します)。ボタンが押されると、押されたボタンに対応したフラグがtrueになります。ですので、例えばログインボタンが押されたときの処理は、OnGUIメソッド内の「if( logInButton )」以下に実装していけばよいことになります。

OnGUIメソッドの最下部で、UserAuth.currentPlayerの値を監視しています。先ほど実装したログインや新規登録は非同期処理でしたので、処理が完了するまで画面が固まることはありません。処理が完了し、UserAuth.currentPlayerに値が入ったタイミングで、メインゲームシーンに遷移します。

動作確認1

以上で、ユーザーの新規登録とログイン機能を2D Shootingに追加することができました。正しく動作しているか、次の方法で確かめて見ましょう。

  • 新規登録すると、mobile backendのダッシュボード内「会員管理」メニューにそのプレイヤーが存在する
  • 登録済みのIDとパスワードでログインすると、メインゲーム画面に遷移する

UserAuthをシングルトン化する

今回作成したUserAuthクラスのcurrentPlayerメソッドやlogOutメソッドは、様々なシーンで使うことになりそうなので、UserAuthオブジェクトをシングルトン化します。

以下のメソッドを、UserAuthクラスで定義してください。

// シングルトン化する ------------------------

  private UserAuth 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);
    }
  }

これで、他のシーンでもUserAuthクラスを使えるようになりました。

タイトル画面にメニューをつくる

最後に、タイトル画面にボタンメニューを表示します。タイトル画面での入力待ちうけは、StageシーンのManagerオブジェクトが担当してます。既存のManager.csを開き、全体を以下の内容に書き換えてください。

using UnityEngine;

public class Manager : MonoBehaviour
{
  // Playerプレハブ
  public GameObject player;
    
  // タイトル
  private GameObject title;

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

  void Start ()
  {
    // Titleゲームオブジェクトを検索し取得する
    title = GameObject.Find ("Title");
  }
    
  void OnGUI() {
    if( !IsPlaying() ){
      drawButton();

      // ログアウトボタンが押されたら
      if( logOutButton )
         FindObjectOfType<UserAuth> ().logOut ();

      // 画面タップでゲームスタート
      if ( Event.current.type == EventType.MouseDown) 
         GameStart ();
    }
    
    // ログアウト完了してたらログインメニューに戻る
    if( FindObjectOfType<UserAuth>().currentPlayer() == null )
      Application.LoadLevel("Login");   
  }
    
  void GameStart() {
    // ゲームスタート時に、タイトルを非表示にしてプレイヤーを作成する
    title.SetActive (false);
    Instantiate (player, player.transform.position, player.transform.rotation);
  }
    
  public void GameOver() {
    FindObjectOfType<Score> ().Save ();
    // ゲームオーバー時に、タイトルを表示する
    title.SetActive (true);
  }

  public bool IsPlaying () {
    // ゲーム中かどうかはタイトルの表示/非表示で判断する
    return title.activeSelf == false;
  }

  private void drawButton() {
    // ボタンの設置
    int btnW = 140, btnH = 50;
    GUI.skin.button.fontSize = 18;
    leaderBoardButton = GUI.Button( new Rect(0*btnW, 0, btnW, btnH), "Leader Board" );
    commentButton     = GUI.Button( new Rect(1*btnW, 0, btnW, btnH), "Comment" );
    logOutButton      = GUI.Button( new Rect(2*btnW, 0, btnW, btnH), "Log Out" );
  }
}

ログイン画面の実装と同様に、OnGUIとdrawButtonメソッドでボタンの描画と画面遷移を行っています。

動作確認2

この作業によって、メインゲーム画面に下図のようなボタンが表示され、ログアウトができるはずです。

メインゲームメニュー

今回は同時にランキング表示ボタンとコメント投稿ボタンも追加しました。ランキング表示ボタンの実装は「ハイスコアをサーバーに保存する」と「ハイスコアランキングを作る」で、コメント投稿ボタンの実装については、「ステージにコメントを残す」で解説します。

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

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

ページの先頭へ