追記(2020/1/20)
Buttonが反応しない不具合を解消するため、Canvasに加えてGraphicRaycasterを追加するようにしました。
追記(2020/1/21)
Focus()にて1F待機を追加しました。UniTaskを使用してますが1F待機できればCoroutineなどでも問題ないはずです。
背景
デジゲー博に展示して試遊してる様子を見て気づいたんですが、押させたい場所にポップを表示させるだけでは人は押してくれませんでした(見ててまじかよと思った)。
そこで、押させたい場所しか押せない仕組みが必須と分かり実装してみました。
概要
UIで押させたいボタンだけフォーカスさせる実装方法
— アズマゴロー@デジゲー博B-03a (@azumagoro) November 24, 2019
①Stopper用Canvas(+Image)を通常のUIのCanvasより前に表示させる
②押させたいボタンにAddComponentで動的にCanvasを追加し、SortOrderをStopperCanvasより前に表示させる。
③するとUIのレイヤー関係を壊さずに最前面に表示できる。 pic.twitter.com/TRnADbzk1L
コードとか
using UniRx.Async;
using UnityEngine;
using UnityEngine.UI;
public class StopperController : MonoBehaviour
{
[SerializeField] private Canvas _stopperCanvas;
public static FocusController Instance;
private Canvas _addedCanvas;
private GraphicRaycaster _addedRaycaster;
private void Awake()
{
Instance = this;
}
public async void Focus(GameObject go)
{
_stopperCanvas.gameObject.SetActive(true);
_addedCanvas = go.AddComponent<Canvas>();
_addedRaycaster = go.AddComponent<GraphicRaycaster>();
// たまに動作しない時があるため1F待機する
await UniTask.DelayFrame(1);
_addedCanvas.overrideSorting = true;
_addedCanvas.sortingOrder = _stopperCanvas.sortingOrder + 1;
}
public void RemoveFocus()
{
// 依存関係のため_addedRaycasterから先に削除する
Object.Destroy(_addedRaycaster);
_addedRaycaster = null;
Object.Destroy(_addedCanvas);
_addedCanvas = null;
_stopperCanvas.gameObject.SetActive(false);
}
# if UNITY_EDITOR
[SerializeField] private GameObject testGameObject;
[ContextMenu("TestFocus")]
void TestFocus()
{
Focus(testGameObject);
}
[ContextMenu("TestRemoveFocus")]
void TestRemoveFocus()
{
RemoveFocus();
}
# endif
}
StopperCanvas
StopperController
参考になった場合はよろしければいいねお願いします😊
おわり