UnityのuGuiのsliderは非常に便利なのですがFillAreaに画像をアタッチしても伸縮で表示されて絵的にイマイチです。なので自作のスライダーを設置しようとしましたが、uGuiのSliderの使い方の解説の情報ばかりで自作のスライダーの設置方法がみつからなかったので自分用につくりました。
を分解すると
土台部分はImage、バー部分はSpriteRendererとSpriteMaskで作成します
ヒエラルキー上ではこんな感じです
土台部分にEventTriggerをアタッチして、DragEventを追加します。
(EventTriggerはRaycastTargetが有効化されたImageが同じオブジェクトにある場合のみイベントを起こすので土台はImageでなくてはなりません)
受け取り側のスクリプト
using UnityEngine.EventSystems;
public float PixelPerUnit= 100f;
public void OnSliderDrag(BaseEventData e)
{
PointerEventData pointer = e as PointerEventData;
if (pointer.dragging)
{
Canvas canvas = GetComponentInParent<Canvas>();
RectTransform rect = GetComponent<RectTransform>();
Vector3 wpos = Vector3.zero;
RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, pointer.position, canvas.worldCamera, out wpos);
Vector2 LeftTop = new Vector2(-rect.sizeDelta.x * rect.pivot.x, -rect.sizeDelta.y * rect.pivot.y) / PixelPerUnit;
value = (wpos.x - transform.position.x - LeftTop.x) / rect.sizeDelta.x * PixelPerUnit;
}
}
PointerEventDataで受け取る座標pointer.positionはスクリーン上の座標なので土台のImageを描画しているキャンバスを
Canvas canvas = GetComponentInParent<Canvas>();
で取得し、そのキャンバスの対象のカメラを
canvas.worldCamera
から取得し、
RectTransform rect = GetComponent<RectTransform>();
Vector3 wpos = Vector3.zero;
RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, pointer.position, canvas.worldCamera, out wpos);
でワールド座標wposに変換します。
あくまでワールド座標なので、スライダーの表示位置からどのくらいの位置にあるかということも計算しないといけません。
そこでRectTransform のサイズとピボットから左上の座標を取得しているのが
Vector2 LeftTop = new Vector2(-rect.sizeDelta.x * rect.pivot.x, -rect.sizeDelta.y * rect.pivot.y) / PixelPerUnit;
です。
今回は横方向のスライダーなので
value = (wpos.x - transform.position.x - LeftTop.x) / rect.sizeDelta.x * PixelPerUnit;
で正規化されたスライダーのドラッグ位置が取得できます。
ちなみにPixelPerUnitは、TextureのPixelPerUnitの値です。
ここまでやっておいてなんですが透明なuGuiのスライダーを手前に置いて、そのvalue値を表示用のスライダーに反映させるほうが簡単だと思います。
ですが何かに応用できそうなのでメモとして残しておきます。