Unity 花活小剧场 - 通过ScrollRect可以做摇杆?

文章介绍了如何在Unity中使用ScrollRect组件的ElasticMovementType特性来创建摇杆Handle的回弹居中效果。通过限制Handle的拖动范围,记录拖动方向,并添加回调函数,可以实现摇杆驱动,从而控制游戏对象的移动和旋转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现思路:

  • 利用Scroll Rect组件的Elastic MovementType实现Handle的回弹居中;
  • 重写SetContentAnchoredPosition函数,限制Handle的拖动范围;
  • 重写OnDragOnEndDrag函数,记录拖动形成的Direction方向;
  • 添加回调函数,实现摇杆驱动。

Elastic MovementType

添加两个圆形Image,中间的小圆就是摇杆Handle,将其拖拽到Scroll Rect组件中的Content属性中,如图所示:
Scroll Rect
Movement Type使用默认Elastic类型,该属性帮忙我们可以实现Handle的回弹居中,如图所示:

回弹居中

限制Handle的拖动范围

创建脚本SimpleJoystick,继承ScrollRect类,通过Override虚函数SetContentAnchoredPosition来限制Handle的可拖拽范围:

using UnityEngine;
using UnityEngine.UI;

public class SimpleJoystick : ScrollRect
{
    protected override void SetContentAnchoredPosition(Vector2 position)
    {
        //base.SetContentAnchoredPosition(position);

        if (position != content.anchoredPosition)
        {
        	//大圆的半径
            float radius = (transform as RectTransform).rect.height * .5f;
            //限制拖拽范围在半径内
            content.anchoredPosition = position.magnitude <= radius ? position : position.normalized * radius;
            UpdateBounds();
        }
    }
}

拖拽限制

记录拖拽形成的方向

声明Vecotor3类型变量,记录拖拽形成的方向,在拖拽过程中记录,在结束拖拽时重置为Vector3.Zero:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class SimpleJoystick : ScrollRect
{
    private Vector3 direction;

    protected override void SetContentAnchoredPosition(Vector2 position)
    {
        //base.SetContentAnchoredPosition(position);

        if (position != content.anchoredPosition)
        {
            float radius = (transform as RectTransform).rect.height * .5f;
            content.anchoredPosition = position.magnitude <= radius ? position : position.normalized * radius;
            UpdateBounds();
        }
    }

    public override void OnDrag(PointerEventData eventData)
    {
        base.OnDrag(eventData);
        
        direction = new Vector3(content.anchoredPosition.x, 0f, content.anchoredPosition.y);
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);

        direction = Vector3.zero;
    }
}

添加回调函数

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class SimpleJoystick : ScrollRect
{
    public UnityAction<Vector3> onDrag;

    private Vector3 direction;

    protected override void SetContentAnchoredPosition(Vector2 position)
    {
        //base.SetContentAnchoredPosition(position);

        if (position != content.anchoredPosition)
        {
            float radius = (transform as RectTransform).rect.height * .5f;
            content.anchoredPosition = position.magnitude <= radius ? position : position.normalized * radius;
            UpdateBounds();
        }
    }


    public override void OnDrag(PointerEventData eventData)
    {
        base.OnDrag(eventData);
        
        direction = new Vector3(content.anchoredPosition.x, 0f, content.anchoredPosition.y);
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);

        direction = Vector3.zero;
    }

    private void Update()
    {
        if (content.anchoredPosition != Vector2.zero)
        {
            onDrag?.Invoke(direction);
        }
    }
}

Example示例:

using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private Rigidbody rb;
    [SerializeField] private SimpleJoystick joystick;

    private void Start()
    {
        joystick.onDrag += OnJoystickDrag;
    }

    private void OnJoystickDrag(Vector3 direction)
    {
        rb.velocity += direction.normalized * Time.deltaTime * 15f;
        if (direction != Vector3.zero)
        {
            rb.transform.rotation = Quaternion.LookRotation(direction);
        }
    }
}

摇杆驱动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CoderZ1010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值