AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

コードで商店UIを動的生成する

f:id:yasu9780:20161118041838p:plain

コードによる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); });
    }