Unityはゲームが簡単に作成できる環境です。週末プログラマーとしてゲーム開発に勤しむ方も多いのではないでしょうか。しかし、ただゲームを作っただけでは一人一人が個別に遊ぶだけになります。インターネットが活かせればもっと面白くなるはずです。
とはいえゲームを開発して、ネットワークの飛び先(つまりサーバ)まで開発するとなると非常に大変です。そこで使いたいのがmBaaSになります。モバイルアプリに限らずサーバサイド/バックエンドの仕組みを提供しますのでゲーム開発に打ち込めるようになるのです。
ニフティクラウド mobile backendではUnity SDKを提供しています。今回はこのUnity SDKを使ってゲームにログイン機能を追加してみたいと思います。
必要なもの
ニフティクラウド mobile backnedのID
Unity
ゲームのテンプレートを用意する
今回はUnityのAsset Storeでダウンロードできる無料ゲームをベースにしたいと思います。ダウンロードしたのは、
2D Space Shooter Starter Kit - Mobile Ready
になります。2Dグラフィックスのシンプルなシューティングゲームです。
新規でUnityプロジェクトを立ち上げます。今回は2Dを選択しています。
ゲーム構成の変更
このゲームのシーンは次のようになっています。game1とgame2は、Y軸のみ動作(game1)とX/Y軸動作(game2)の違いとなっています。
Loginのシーンを取り込む
ニフティクラウド mobile backendで提供しているLoginのプレハブをダウンロード&解凍してください。また、Unity SDKについてもダウンロード&解凍してください。
解凍して出てきた LogIn.unity を Assets/2dspaceshooter/Scenes の中にドラッグ&ドロップします。
Loginの修正
背景画像が当たっていませんので、Hierarchy のBackgroundsを削除します。
Game Object作成とNCMB設定
Login シーンにおいて、GameObject > Create Empty をクリックして、空のGame Objectを作成します。名前は NCMBSettings とします。
UserAuth作成
もう一度空の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; } 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); } } }
LogInManager の作成
さらに空のGame Objectを作成し、名前を LogInManager とします。
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("menu"); } 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" ); } }
これでログイン/新規登録画面の作成は完了です。
再生する
では LogInシーンを再生してみます。次のような画面が出てきたら成功です。
menuシーンを編集する
さて、このゲームでは最初に表示されるのはmenuシーンのはずなので、こちらの画面にログイン画面へのアクションを追加します。menuシーンに切り替えます。
GameObject メニューのCreate Other > GUI Text を2回実行して、それぞれ Logout と Username とします。どちらもGUIの中に入れてまとめて管理できるようにします。
Logout
- Position: X 0.8 / Y 0.15 / Z 0
- Text: Log out
- Font: score
- Font size: 30
Username
- Position: X 0.8 / Y 0.95 / Z 0
- Text: (空文字)
- Font: score
- Font size: 30
- Color: 赤
編集後に再生すると次のような配置になります。Usernameは仮でテキストを入力しています。
UserAuthを移動する
このゲームはJavaScriptで作られているため、そのままではC#と連携できません。そこで必要なファイル(今回はUserAuth)を移動する必要があります。
Assets直下にStandard Assetsというフォルダを作成します。さらにその下にScriptsというフォルダを作成します。
menu.jsを編集する
Assets/2dspaceshooter/Scripts/menu を開きます。内容を次のように変更します。
#pragma strict //we create a blank texture that actually has no texture attached so we can hide unity's generic button graphics. they are added to the buttons below to do this. private var blankGfx:Texture; var logoutButton:GUIText; var userName:GUIText; function OnGUI () { //Play 1 Axis if(GUI.Button(Rect(Screen.width/3,Screen.height/2.07,Screen.width/3,Screen.height/6), blankGfx, "")){ Application.LoadLevel("game"); } //Play 2 Axis if(GUI.Button(Rect(Screen.width/3,Screen.height/1.47,Screen.width/3,Screen.height/6), blankGfx, "")){ Application.LoadLevel("game2"); } if( Input.GetMouseButtonDown(0)){ if( logoutButton.guiText.HitTest(Input.mousePosition) ) { FindObjectOfType(UserAuth).logOut(); Application.LoadLevel("LogIn"); } } } function Start() { if (FindObjectOfType(UserAuth).currentPlayer() == null) { logoutButton.text = "Login"; }else{ userName.text = FindObjectOfType(UserAuth).currentPlayer(); } }
Startファンクションを追加して、ログイン状態によってテキストを変更しています。OnGUIではマウスのクリック状態やその場所によってログアウト処理を実行しています。
GUIのアタッチ
HierarchyにあるGUIをクリックすると、InspectorにLogout button/User Nameが追加されています。最初は何もアタッチしていませんので、左のHierarchyからLogout/Usernameそれぞれをドラッグしてアタッチします。
menuシーンの再生
ではmenuシーンを再生してみます。最初は Log inというラベルが表示されるかと思います。
ここまでの手順でログイン機能が追加できました。慣れれば1時間もあればできるようになります。サーバサイドの用意が一切不要で、既存のゲームにログイン機能を追加したいという時にはぜひお試しください。
次回はスコアの保存について紹介します。