🎨

UnityでButtonに複数のtargetGraphicを指定したい

2022/09/02に公開

はじめに

現状では1つのtargetGraphicしか指定出来ません。
しかしサムネイルの上に乗っているアイコンなど、Button押下時の処理に合わせてまとめてカラーを変えたかったのです。

内部を追ってみる

Buttonクラスの中身を見ていくと、継承元にあるSelectableクラスに以下が定義されています。

protected virtual void DoStateTransition(SelectionState state, bool instant)

これはButtonの状態が変わるときに呼ばれる関数のようで、この処理に合わせればぴったり同じタイミングで処理を入れ込めます。

実装

処理はカラー用にしてありますが、Spriteなどの場合も根底クラスに書かれているので適当に書き換えて下さい。
既存のButtonを以下のTransitionFollowingColorsButtonに置き換えて、TransitionFollowingColorsButtonTargetsに指定したいコンポーネントを入れてください。

Buttonクラスなどを継承するとフィールドに定義した値がインスペクターに出ないため、エディター拡張しないといけません。
それは少し面倒なのでAwake()で済ませています。

TransitionFollowingColorsButton
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// Buttonに登録されているTargetGraphic以外の画像のカラーも一緒に変えたいときに使う
/// 根底クラスのDoStateTransitionに従って同じタイミングで動作する
/// </summary>
[RequireComponent(typeof(TransitionFollowingColorsButtonTargets))]
public class TransitionFollowingColorsButton : Button
{
	private TransitionFollowingColorsButtonTargets data;

	protected override void Awake()
	{
		base.Awake();
		data = GetComponent<TransitionFollowingColorsButtonTargets>();
	}

	// 根底クラスにある実装をそのままカラー用に抜き出して、複数画像に同じタイミングで適用出来るようにした
	protected override void DoStateTransition(SelectionState state, bool instant)
	{
		base.DoStateTransition(state, instant);
		Color tintColor;
		switch (state)
		{
			case SelectionState.Normal:
				tintColor = colors.normalColor;
				break;
			case SelectionState.Highlighted:
				tintColor = colors.highlightedColor;
				break;
			case SelectionState.Pressed:
				tintColor = colors.pressedColor;
				break;
			case SelectionState.Selected:
				tintColor = colors.selectedColor;
				break;
			case SelectionState.Disabled:
				tintColor = colors.disabledColor;
				break;
			default:
				tintColor = Color.black;
				break;
		}

		foreach (var target in data.Targets)
		{
			target.CrossFadeColor(tintColor * colors.colorMultiplier, instant ? 0f : colors.fadeDuration, true, true);
		}
	}
}

TransitionFollowingColorsButtonTargets
using UnityEngine;
using UnityEngine.UI;

public class TransitionFollowingColorsButtonTargets : MonoBehaviour
{
	public Graphic[] Targets;
}

ちなみに

以下を参考にしてDoTweenを使わないでコルーチン形式で実装してみたのですが、何回か押しているとどうしてもタイミングが合わない場面があったので別で作った次第です。
https://qiita.com/kazuman519/items/38821884cb6a2fef9a2a

Discussion