CardBoard SDKで 凝視で押すことの出来るボタン「GazeableButton」を作る
ボタンに視線を合わせるとゲージが溜まっていくボタンを作成したい.
Hierarchy
Canvas
+ GvrPointerGraphcRaycaster
+ Canvas(Render Mode World Space)
Button
+ Event Trigger(OnReticlePointerEnter + OnReticlePointerLeave)
Slider
-
[UI] > [Canvas] を追加
GraphicRaycasterの代わりにGvrPointerGraphicRaycasterを設定. Canvas のRender Modeを World Space にし、ワールド内の適当な場所に設置. そのままだと大きすぎるのでRect Transform をx,y,z 0.001程度に. -
ボタン: [UI] > [Button] を追加しCanvas以下に移動
-
ゲージ: [UI] > [Slider] をボタン以下に追加
-
ボタンに
Event Triggerをアタッチ -
ボタンにスクリプト
GazeableButton.csをアタッチ
GazeableButton.cs
using DG.Tweening;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 視線で押せるボタン
/// </summary>
[RequireComponent(typeof(Button))]
public class GazeableButton : MonoBehaviour {
/// <summary>
/// スライダー
/// </summary>
[SerializeField]
private Slider slider;
/// <summary>
/// 注視する秒数
/// </summary>
[SerializeField]
private float duration;
private bool hover = false;
private bool pressed = false;
private float TimeCount { get; set; } = 0.0f;
private float Value => TimeCount / duration;
void Start() {
var button = GetComponent<Button>();
var rect = GetComponent<RectTransform>();
this.UpdateAsObservable()
.Subscribe(_ => {
slider.value = Value;
if (pressed) return;
if (hover) {
TimeCount += Time.deltaTime;
rect.localScale = Vector3.one * (1.1f + Value * 0.2f);
}
if (!hover) {
TimeCount = 0;
rect.localScale = Vector3.one;
}
if (duration < TimeCount) {
// emulate click
var e = new PointerEventData(EventSystem.current);
ExecuteEvents.Execute(button.gameObject, e,
ExecuteEvents.pointerClickHandler);
pressed = true;
}
});
}
public void OnReticlePointerEnter(BaseEventData e) {
var rect = GetComponent<RectTransform>();
rect.DOScale(Vector3.one * 1.1f, 0.1f);
hover = true;
pressed = false;
TimeCount = 0;
}
public void OnReticlePointerLeave(BaseEventData e) {
var rect = GetComponent<RectTransform>();
rect.DOScale(Vector3.one, 0.1f);
hover = false;
pressed = false;
TimeCount = 0;
}
}スライダーの値は 0f ~ 1f で設定できるので注視している間、時間をカウントしていき、それをボタン押下に必要な秒数 duration で割った値をスライダーの値に設定.
duration 秒以上注視するとボタンのクリックをエミュレートする. ボタンクリックのエミュレートは以下で可能.
var e = new PointerEventData(EventSystem.current);
ExecuteEvents.Execute(button.gameObject, e, ExecuteEvents.pointerClickHandler);適宜ボタンのアニメーション等を設定.
- Event Trigger 設定
- 視線のポインタがボタンに乗ったとき、出たときに
PointerEnter(BaseEventData)/PointerExit(BaseEventData)が発火するのでEventTriggerにGazeableButton.OnReticlePointerEnter(BaseEventData),GazeableButton.OnReticlePointerLeave(BaseEventData)を設定