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 に基づいて新しいカスタム コンポーネントを派生することもできます。