コードによるUI作成で行いたいと思って試作中です。
NPCキャラが商店になっていて、キャラクターに近づくと商店のウインドウが表示されます。
状態遷移としては、
- 商品一覧を表示する
- 一覧:キャンセルを押すと画面は消える
- 一覧:購入を押すと、確認ダイアログが出る
- 確認:再度購入を押すと購入が確定
- 確認:キャンセルを押すと、商品一覧画面に戻る
確認パスが入ると、階層でダイアログが二つ出ていることになります。
WebでCGIだと簡単なんで意識しなかったけど、アプリとして作ると面倒くさいですねえ。
商品一覧windowを出しているときに、購入ボタンを押すと、いったんWindowを削除して、確認Windowを表示して、そこでキャンセルすると、再度商品一覧Windowを表示するって方向でやりました。
じゃないとスタックとかでWindow情報を保持しないといけないし。
といっても、そんな深い階層のWindowとか使わないし。
作りこみで確認Windowだけ特別扱いでもいいかもしれないけど、透明度設定してるのに二重にWindow作っても見にくいしね。
OnTriggerでNPCの商魂が発動
pauseフラグでキャラの動きを止めます。アニメーションもIDLEに。
void OnTriggerEnter(Collider other) { if (humanPlayerFlag && _parent.name == "EyeGlassTightSkirt") { anim.SetFloat("Speed", 0); pause = true; makeDialog("Store", "What do you want?","Purchase"); } if (humanPlayerFlag && _parent.name == "LongPonny") { anim.SetFloat("Speed", 0); pause = true; makeDialog("Second Hand Store","I will purchase\nyour items.", "Sell"); } }
商店と中古屋の2店がある場合の遷移定義
ボタンをクリックすると、押されたボタンの名前と親であるフレームの名前を引数にonButtonClickが呼ばれる
void onButtonClick(string name,string paName) { Debug.Log("Button Click: " + name +"::"+ paName); DestroyAll(GameObject.Find("Canvas/Frame_" + paName)); // 道具屋 if (paName == "Store_Confirm" && name == "Confirm") { Debug.Log("You purchase it"); } if (paName == "Store" && name == "Purchase") makeDialog("Store_Confirm", "Do you really buy it ? ", "Confirm"); // 中古買取専門店 if (paName == "Second Hand Store_Confirm" && name == "Confirm") { Debug.Log("You sell it"); } if (paName == "Second Hand Store" && name == "Sell") makeDialog("Second Hand Store_Confirm", "Do you really sell it ? ", "Confirm"); // Cancel if (name == "Cancel" || name == "X") { if (paName == "Store_Confirm") makeDialog("Store", "What do you want?", "Purchase"); if (paName == "Second Hand Store_Confirm") makeDialog("Second Hand Store", "I will purchase\nyour items.", "Sell"); if (paName=="Store" || paName== "Second Hand Store") pause = false; } }
UI部品は以下。prefabで部品を呼び出して、動的に大きさや位置をコードで指定して生成します。
void makeDialog(string title, string message,string action) { GameObject canvas = GameObject.Find("Canvas").gameObject; GameObject frame = GameObject.Instantiate((GameObject)Resources.Load("UI/FrameAlpha")) as GameObject; frame.name = "Frame_" + title; RectTransform rt = frame.GetComponent<RectTransform>(); rt.localPosition = new Vector3(0, 0, 0); // position rt.sizeDelta = new Vector2(400, 300); // size frame.transform.SetParent(canvas.transform, false); makeText(frame, 0, 0, 350,250, title + "\n\n"+message); makeButton(frame, +180, 130, "X", title); makeButton(frame, -100, -100, action,title); makeButton(frame, +100, -100, "Cancel", title); } void makeText(GameObject pa, float x, float y, float hsize,float vsize,string text) { GameObject item = GameObject.Instantiate((GameObject)Resources.Load("UI/Text")) as GameObject; item.GetComponent<Text>().text = text; item.transform.SetParent(pa.transform, false); RectTransform rt = item.GetComponent<RectTransform>(); rt.localPosition = new Vector3(x, y, 0); // position rt.sizeDelta = new Vector2(hsize,vsize); // size } void makeButton(GameObject pa,float x, float y, string text,string paName) { GameObject item = GameObject.Instantiate((GameObject)Resources.Load("UI/Button") ) as GameObject; item.name = "Button_" + text; item.transform.SetParent(pa.transform, false); RectTransform rt = item.GetComponent<RectTransform>(); rt.localPosition = new Vector3(x, y, 0); // position rt.sizeDelta = new Vector2(2 + text.Length * 12, 30); // size Text txt = item.transform.FindChild("Text").gameObject.GetComponent<Text>(); txt.text = text; Button bt = item.GetComponent<Button>(); string a = text; string b = paName; bt.onClick.AddListener(() => { onButtonClick(a,b); }); }