土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

Unity Tips(5:CanvasとButtonの話)

RectTransformを持った空のGameObjectを作成する方法

 canvas上で動作させるGameObjectは、通常のTransformではなくRectTransformを持たせる必要があるのですが、「RectTransformを持つ空のGameObject」を表すクラスは無いようで、動的に生成する場合は以下のようなコードになるそうです(公式に認められている方法ではないので注意)。

 GameObject myGO = new GameObject("MyGO", typeof(RectTransform));

 GameObjectのコンストラクタでは、生成時から保持するコンポーネントを可変長引数で設定できます。

public GameObject(string name, params Type[] components);

 Transformはハードコーディングされているので、コンストラクタを使ってRectTransformを追加するのは危険のようにも思えますが、実行してみると確かにtransformプロパティの中にRectTransformが代入されているので、恐らくUnity内部で差し替えが行われているのかと思われます(知りませんが)。
参考サイト:
http://answers.unity3d.com/questions/948887/what-is-the-correct-syntax-to-create-a-new-object.html

CanvasのButtonにMouseEnterやMouseDownのイベントをハンドリングさせる

 CanvasのButtonコンポーネントはOnClick/OnSubmitしかイベントを取得できません。……って、なんでだよ! (まあ、あくまで標準ボタンだからかな……)

 というわけで、まともなボタンハンドリングがしたい場合、一から作った方がいいようです。Canvas用の空GameObjectが既にあったとして、こんな感じのコードをAddすればOK。他のイベントもインターフェイス増やせば動くんでないでしょうか。

public class MyButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData){ 
        //クリック時の処理
    }
    public void OnPointerEnter(PointerEventData eventData){ 
        //マウスオーバー時の処理
    }
    public void OnPointerExit(PointerEventData eventData){ 
        //マウスアウト時の処理
    }
}

上の補足。マウスオーバーの取得について

 調べた限りだとOnPointerOverというUIイベントはないっぽい(OnMouseOverイベントはあるが、canvasオブジェクトでは機能しないっぽい? 未検証)。

 OnPointerEnterが発生してからOnPointerExitが発生するまでの間がOverということになるけど、Over中であることを取得したい事もあるので、Enter/Exitイベントタイミングで値を保存しておくのがよさげ。

InputManager上の仮想キーをゲーム実行中に更新する方法

 どうもないっぽい(まじかー)。仮想キーのデータはInputManager.assetに格納されているのですが、UnityEditorのAssetDatabaseでないとアクセスできないので、実行時には動かせないぽい。
 うーん、これどうしようもないんかな……。ゲーム内でキーコンフィグしたい場合、Unityの仮想キーが実用上利用できないことになってしまうのですが……。なんか土屋が勘違いしている気がしなくもない。

GetAxisではUp/Downが取れない

 抽象化されたキー入力を取得するInput.GetAxis()では、ボタンが押された/離れた最初のフレームを認識するGetButtonDown()/GetButtonUp()に相当する情報が取れません。
 もともとGetAxis()は0〜1の値を取得するメソッドなので当たり前の話ではあるのですが、少なくとも土屋はこの1フレーム目を取得したいことが非常に多く、そのためにはGetButtonDown()/GetButtonUp()を使う必要があり、それだとGetAxis()は使えないです。うーん、GetAxis()自体はなかなか良いのでちょっと残念だな。