2013年4月8日月曜日

Unityゲームを終了する

UnityでAndroidにビルドしていると思うこと
「ホームボタンでしか戻れないうえにバックグラウンドで生きてんの…?」

当然バッテリーはマッハなため非常によろしくない. が, デフォルトではそんな処理はしてくれない.
なのでスクリプトでつける必要があったのでメモメモφ(・ω・ )


Unityゲームを終了する


1. メソッド

Application.Quit();
これだけ.
このメソッドを呼ぶことでアプリケーションは閉じてくれる.

2. 実際に使ってみる

空の GameObjectを作り, GameManagerとでもしておく. 
void Update(){
    if (Application.platform == RuntimePlatform.Android && Input.GetKey(KeyCode.Escape)){
        Application.Quit();
    }
}
こんな内容のスクリプトを作り, GameManagerに持たせてやると, ゲーム中「戻る」キーを押すことでゲームが終了できる.
プラットフォームが Androidであることを確認してるけど, 「戻る」キーとか iPhoneには無いよなぁ….
毎フレーム呼び出すのが気持ち悪いなら何かしらボタンを作って, そこから反応してやると誤爆も少なくなっていいかも.

3(おまけ). ダイアログっぽい何か作ってみた

いいと思ったのでやってみようとした. ただ…ダイアログってどう作るんだ…?3Dには強いが2Dにはいまいち余計な手間がかかってしまうイメージ.

   3-1. 構想

      ヨクワカラナイのでとりあえず構想.
      ダイアログを開くボタンを押す → ダイアログからYesを選ぶ → ゲームが終わる!
      こうしたいなー(・з・)的な簡単な構想. 
      何やらいろいろやり方はアルっぽいけどよくわかんない('A`)
      AssetStoreにありそうだなー…
      ダイアログっぽいものを書く OnGUIを持ったスクリプトを動的に追加することで「ダイアログを開」き, このスクリプトを削除して「ダイアログを閉じ」たい. 
   

   3-2. ダイアログを開くボタン

      とりあえずボタン. これはシンプル.
using UnityEngine;
using System.Collections;

public class ButtonTest : MonoBehaviour {

 public bool isOpened = false;
 
 void OnGUI(){
  float sw = Screen.width;
  float sh = Screen.height;
  
  if (GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu") && !isOpened) {
   Debug.Log("push!");
   isOpened = true;
  }
  
 }
}
sw, shはそれぞれ現在のスクリーンの幅/高さを取得. 割合でボタンの座標を決定してやると端末変わった時とかに順応しやすいかと.

ボタンを表示させているのが 7行目, GUI.Button(). なお GUIクラスは OnGUI()メソッド以外から呼ぼうとすると怒られる…(・ω・`)
このメソッドはボタンを作りつつ, 押されたときに trueを返すできる子. 一粒で二度おいしい.
最初の引数で表示位置を, 次の引数でボタンに表示するラベルを宣言. なお Rectについてはこんなのもございます(宣伝)

isOpenedはなんてことはない bool. これで制限をかけて, ボタン連打でダイアログ地獄, なんてのを避ける(予定).
これを空の GameObjectでも作って載せてやり, 実行するとボタンが左上に出るはず.

こんな感じ. なおこの状態で押しても, isOpenedをなんとかする方法がないので, ログは一個しか出てこないハズ.


      3-3. 「ダイアログ」を用意する

ここが一番困った. AndroidのDialogクラスみたいなのは見当たらないし, 仕方ないので別のクラスを自作し, そこでOnGUI()でもしてそれっぽく見せてみる.
using UnityEngine;
using System.Collections;

public class TestDialog : MonoBehaviour {
 
 public ButtonTest test;
 
 void Start(){
  test = this.gameObject.GetComponent<buttontest>() as ButtonTest;
 }
 
 void OnGUI () {
  float sw = Screen.width;
  float sh = Screen.height;
  GUI.Box(new Rect(sw / 3, sh / 3, sw / 3, sh / 3),"TestDialog");
  
  if (GUI.Button(new Rect(sw * 2 / 5, sh * 2/ 5, sw / 5, sh / 10), "yes")) {
                        Debug.Log("quite");
                        test.isOpened = false;
                        Destroy (this);
                        Application.Quit();
  }
  if (GUI.Button(new Rect(sw * 2 / 5, sh * 11 / 20, sw / 5, sh / 10), "no")){
                        Debug.Log("cancel");                        
                        test.isOpened = false;
                        Destroy (this);
  }
 }
}
こんなクラス. このスクリプトを 3-2. で作ったスクリプトを載せた空のオブジェクトに動的にくっつけることで表示させよう, という魂胆. menuボタンのイベントで動的にくっつければ, あたかもボタンでダイアログを開いたように見えるという寸法.

Start()はとりあえず 3-2のスクリプトの取得. isOpenedを書き換えて, 「開きっぱなしの状態」をキャンセルする.
15行目, GUI.Boxで, ただの四角い領域を描画. ついでに"TestDialog"とタイトルっぽく入れてみる.
中にはボタン2つ. yesと noボタン. この yesボタンの if()の中で Application.Quit()でも呼んでやれば目的は達成できるはず. でも実機じゃないと確認できない(・ω・`)
そしてDestroy(this)で このスクリプト を破棄することで, ダイアログ(?)を破棄する. アプリ終了する前に Destroy()しておくべきなのだろうか…

後は3-2の方, ボタンのイベントの中を
if (GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu") && !isOpened) {
   Debug.Log("push!");
   this.gameObject.AddComponent<TestDialog>();
   isOpened = true;
  }
と, AddComponent()してやることで, ここで作ったスクリプトを動的に足す.
これで, menuボタンを押すと,
みょん. それっぽいものが出てきてくれました.
Inspectorの方を確認して, 動的にスクリプトが追加されているのも確認しておくといいかも.
ちなみに3-2の方, ボタンの if()文を,
if (!isOpened && GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu")) {
   Debug.Log("push!");
   this.gameObject.AddComponent<TestDialog>();
   isOpened = true;
  }
としてみると, ダイアログっぽいものを開く際変化する isOpenedのほうの条件に引っかかるのか, そのあとの条件となっている menuボタン描画メソッドが呼ばれなくなり,

menuボタンが消える. これはこれで使いようがありそうだったのでメモメモφ(・ω・ ).





おまけのが充実してる気がするけど仕様です. ( ´∀`)ノシ キニシナイ

0 件のコメント:

コメントを投稿

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...