UGUI 選択可能 (選択可能およびボタン) のいずれか

        Selectable は UGUI のコア コンポーネントです。最も一般的に使用される Button に加えて、Scrollbar、Dropdown、Slider、Toggle、InputField などのコンポーネントの基本クラスでもあります。この記事では、Selectable と Button のソース コードを分析し、その実装原理を探ります。
いつものように、UGUI ソース コードのダウンロード アドレスを添付します。

        Selectable の前に、4 つの属性が追加されていることがわかりました。

[AddComponentMenu("UI/Selectable", 70)]
[ExecuteInEditMode]
[SelectionBase]
[DisallowMultipleComponent]

        AddComponentMenu はコンポーネント メニューにオプションを追加します。順序は 70 です。 GameObject の AddComponent ボタンをクリックするとメニューが表示されるので、UI オプションをクリックすると、最後のものが Selectable になっていることがわかります。
        ExecuteInEditMode は、コンポーネントがエディターで実行されることを示します。

        SelectionBase は、このオブジェクトを選択ベース オブジェクトとしてマークします。

        DisallowMultipleComponent は、同じタイプのコンポーネントがゲームオブジェクトに表示されることを許可しません。 2 つの Selectable コンポーネントを 1 つのオブジェクトに追加したり、InputField コンポーネントを Button オブジェクトに追加したりすることはできません。

        Selectable は UIBehaviour を継承し、7 つのインターフェイスを継承します。
   

public class Selectable
        :
        UIBehaviour,
        IMoveHandler,
        IPointerDownHandler, IPointerUpHandler,
        IPointerEnterHandler, IPointerExitHandler,
        ISelectHandler, IDeselectHandler

        UIBehaviour は、すべての UI コンポーネントの基本クラスです。これは、EventSystem ディレクトリに配置されます。IsDestroyed を除き、その他はすべて仮想関数です。これをイベント システムの一部と考えることもできます。これにより、Awake (スクリプトのインスタンスがロードされたとき (つまり、AddComponent のとき)、OnRectTransformDimensionsChange (RectTransform の寸法が変更されたとき)、およびその他のメソッドで UnityEngine からイベントを受け取ります。
        Selectable の Awake は、Graphic コンポーネント インスタンス m_TargetGraphic を取得します (Image コンポーネントは Graphic から間接的に継承されます)。選択したトランジションが Color Tint の場合、Selectable の状態が変化すると (通常、強調表示、押下、無効)、m_TargetGraphic の CrossFadeColor メソッドが呼び出され、現在の画像が指定された色に徐々に変更されます。

        OnEnable (呼び出されるタイミングについては、Untiy3D コンポーネントのヒント (1) OnEnabled と OnDisabled を参照してください)、インスタンスは Selectables s_List の静的リストに追加されます (s_List は、使用可能なすべての Selectables を格納し、UI ナビゲーション クエリに使用されます)、次に、インスタンスのステータスを [通常] または [強調表示] (または [無効]) に設定します。

        OnDisable (呼び出されるタイミングについては、Untiy3D コンポーネントのヒント (1) OnEnabled と OnDisabled を参照)、インスタンスの状態をクリアします (必要な場合)。色と画像を復元し、通常のアニメーションを再生します)、s_List からインスタンスを削除します。

        OnDidApplyAnimationProperties (アニメーション プロパティの適用後) では、OnSetProperty メソッドを通じて InternalEvaluateAndTransitionToSelectionState が呼び出され、現在の状態が更新されます。

        OnCanvasGroupChanged(CanvasGroup変更時)では新しいGanvasGroupのinteractableを判定し、GanvasGroupのinteractableがfalseの場合はSelectable自体を無効化します。次に、現在の状態を更新します。

        次に、Selectable によって継承されたいくつかのインターフェイスを見てみましょう。まず、UGUI カーネル探索 (3) 入力モジュールを見て、これらのインターフェイスのトリガー タイミングを理解します。

        IMoveHandler から継承され、OnMove メソッドを実装する必要があります。移動方向に応じて、次の選択可能なコンポーネントに移動します。

        IPointerDownHandler から継承され、OnPointerDown メソッドを実装する必要があります。 EventSystem.current.SetSelectedGameObject を呼び出して、自身を現在選択されているオブジェクトとして設定し (独自の OnSelect と先行オブジェクトの OnDeselect を呼び出します)、isPointerDown を true としてマークし、状態を更新します (isPointerInside と isPointerDown の両方が true の場合、Pressed 状態になります) )。

        IPointerUpHandler から継承され、OnPointerUp メソッドを実装する必要があります。 isPointerDown を false としてマークし、状態を更新します。

        IPointerEnterHandler から継承され、OnPointerEnter メソッドを実装する必要があります。 isPointerInside を true としてマークし、状態を更新します。

        IPointerExitHandler から継承され、OnPointerExit メソッドを実装する必要があります。 isPointerInside を false としてマークし、状態を更新します。

        ISelectHandler から継承され、OnSelect メソッドを実装する必要があります。 hasSelection を true としてマークし、状態を更新します (hasSelection が true の場合、Highlighted 状態になります。また、後述する isPointerInside と isPointerDown は Highlighted 状態を判断する基準にもなります)。

        IDeselectHandler から継承され、OnDeselect メソッドを実装する必要があります。 hasSelection を false としてマークし、状態を更新します。

        IsHighlighted メソッド:

 protected bool IsHighlighted(BaseEventData eventData)
        {
            if (!IsActive())
                return false;
 
            if (IsPressed())
                return false;
 
            bool selected = hasSelection;
            if (eventData is PointerEventData)
            {
                var pointerData = eventData as PointerEventData;
                selected |=
                    (isPointerDown && !isPointerInside && pointerData.pointerPress == gameObject) // This object pressed, but pointer moved off
                    || (!isPointerDown && isPointerInside && pointerData.pointerPress == gameObject) // This object pressed, but pointer released over (PointerUp event)
                    || (!isPointerDown && isPointerInside && pointerData.pointerPress == null); // Nothing pressed, but pointer is over
            }
            else
            {
                selected |= isPointerInside;
            }
            return selected;
        }

      パラメータは入力モジュールによって渡されるイベント データであり、主にイベント応答オブジェクトがこのオブジェクト (または null) であるかどうかを判断するために使用されます。
        上記の OnPointerDown およびその他のメソッドは、EvaluateAndTransitionToSelectionState メソッドを通じて状態を評価し、更新します。このメソッドでは、UpdateSelectionState が IsPressed および IsHighlighted を呼び出して現在の状態を判断します。 InternalEvaluateAndTransitionToSelectionState は、現在のコンポーネントが無効になっているかどうかを判断し、DoStateTransition メソッドを呼び出します。

 protected virtual void DoStateTransition(SelectionState state, bool instant)
        {
            Color tintColor;
            Sprite transitionSprite;
            string triggerName;
 
            switch (state)
            {
                case SelectionState.Normal:
                    tintColor = m_Colors.normalColor;
                    transitionSprite = null;
                    triggerName = m_AnimationTriggers.normalTrigger;
                    break;
                case SelectionState.Highlighted:
                    tintColor = m_Colors.highlightedColor;
                    transitionSprite = m_SpriteState.highlightedSprite;
                    triggerName = m_AnimationTriggers.highlightedTrigger;
                    break;
                case SelectionState.Pressed:
                    tintColor = m_Colors.pressedColor;
                    transitionSprite = m_SpriteState.pressedSprite;
                    triggerName = m_AnimationTriggers.pressedTrigger;
                    break;
                case SelectionState.Disabled:
                    tintColor = m_Colors.disabledColor;
                    transitionSprite = m_SpriteState.disabledSprite;
                    triggerName = m_AnimationTriggers.disabledTrigger;
                    break;
                default:
                    tintColor = Color.black;
                    transitionSprite = null;
                    triggerName = string.Empty;
                    break;
            }
 
            if (gameObject.activeInHierarchy)
            {
                switch (m_Transition)
                {
                    case Transition.ColorTint:
                        StartColorTween(tintColor * m_Colors.colorMultiplier, instant);
                        break;
                    case Transition.SpriteSwap:
                        DoSpriteSwap(transitionSprite);
                        break;
                    case Transition.Animation:
                        TriggerAnimation(triggerName);
                        break;
                }
            }
        }

           状態に応じて色、画像、またはアニメーション名を設定し、StartColorTween、DoSpriteSwap、または TriggerAnimation メソッドを通じて状態の変更を UI に反映します。


        最後にButtonコンポーネントについて説明します。 Button は Selectable を継承し、さらに 2 つのインターフェイス、IPointerClickHandler と ISubmitHandler を継承します。また、UnityEvent タイプのイベント onClick も追加します。 onClick イベントでは、ユーザー定義のリスナーを追加できます。特定のメソッドは、エディターまたは onClick.AddListener を通じて追加できます。

        OnPointerClick は、Press メソッドを呼び出して onClick をコールバックします。

        また、OnSubmit は Press メソッドを呼び出し、状態を Pressed に切り替え、コルーチンを開始して OnFinishSubmit を呼び出し、状態を現在の状態 (UpdateSelectionState によって取得された状態) に徐々に変更します。

        Selectable と比較すると、Button はクリック イベントと確認イベントに応答するインターフェイスを追加し、ユーザー定義の監視に追加できる onClick イベントも開きます。

        Selectable の機能は、マウス イベントに基づいて 4 つの状態変化を提供することです。 Button や Dropdown などの派生クラスの基本ロジックを提供する一方で、Selectable に基づいて新しいカスタム コンポーネントを派生することもできます。

おすすめ

転載: blog.csdn.net/ttod/article/details/135010923