你知道为什么吗(1)之unity制作触屏移动摇杆

手游常见一种用来移动玩家人物的触碰摇杆,它的组成一般是由一个大圆和一个小圆,玩家的直觉是在大圆范围内操作这个小圆来进行移动操作。但作为开发者,请问实际上接收玩家操作的是大圆还是小圆?

好,如果你没答出,带着这个疑问来看这个摇杆的具体实现。

具体实现

目录

首先我们要写一个脚本。

第二步我们要再写一个脚本

第三步unity里的设置和界面实现


首先我们要写一个脚本

PEListener

public class PEListener : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
    public Action<PointerEventData> onClickDown;
    public Action<PointerEventData> onClickUp;
    public Action<PointerEventData> onDrag;
    public Action<PointerEventData> onClick;

    public void OnPointerDown(PointerEventData eventData)
    {
        onClickDown?.Invoke(eventData);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        onClickUp?.Invoke(eventData);
    }
    public void OnDrag(PointerEventData eventData)
    {
        onDrag?.Invoke(eventData);
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        onClick?.Invoke(eventData);
    }
}

 从类名及方法名来看不难看出是一个监听玩家各种触屏操作的脚本,这里面的c#知识点是委托Action,Action可以简单地看作是方法的集合,图中调用委托的写法是一种简化的写法。

 等同于图中红色的写法,若委托不空则调用里面的方法。

第二步我们要再写一个脚本

UIWnd这个

public class UIWnd : MonoBehaviour
{
    public Image imgTouch;//玩家实际触碰的范围
    public Image imgDirBg;//大圆
    public Image imgDirPoint;//小圆
    private float pointDis;//当前屏幕下小球可以移动的最大距离
    private Vector2 startPos = Vector2.zero;//在按下时大圆的位置,即玩家触碰处
    private Vector2 defaultPos = Vector2.zero;//大圆的初始位置,用于归正
   
     private void Start()
    {
        pointDis = Screen.height * 1.0f / 750 * 90;//750是我canvas分辨率的高度,90是小圆可以移动的最大距离
        defaultPos = imgDirBg.transform.position;
        RegisterTouchEvts();
    }



}

答对了吗,接收玩家操作的既不是大圆也不是小圆,而是本脚本里的imgTouch,那它到底是什么呢,我们放到最后界面实现再来揭晓

Start里RegisterTouchEvts()就是玩家对摇杆操作的具体实现了。我们来看怎么写。

private void RegisterTouchEvts()
{
     PEListener listener = GetOrAddComponect<PEListener>(imgTouch.gameObject);
     istener.onClickDown = (PointerEventData evt) =>
     {
           
            startPos = evt.position;//此处evt.position是玩家按下的位置的屏幕坐标
            imgDirPoint.gameObject.SetActive(true);//显示小圆
            imgDirBg.transform.position = evt.position;//大圆位置即按下位置



     };
     listener.onClickUp = (PointerEventData evt) =>
     {
            imgDirBg.transform.position = defaultPos; //大圆位置归正     
            imgDirPoint.transform.localPosition = Vector2.zero;//小圆回到中心
            imgDirPoint.gameObject.SetActive(false);//隐藏小圆
            //player.SetMoveDir(Vector2.zero);//此时无移动方向


      };

      listener.onDrag = (PointerEventData evt) =>
      {
            Vector2 dir = evt.position - startPos;
            float len = dir.magnitude;//小圆此时移动的距离,向量相减求模长
            //float dis = Vector2.Distance(evt.position, startPos); len等同于dis          
            if (len > pointDis)
            {
                Vector2 clampDir = Vector2.ClampMagnitude(dir, 90);//返回dir,最大值为90
                imgDirPoint.transform.position = startPos + clampDir;//小圆无法超出其最大距离


            }
            else
            {

                imgDirPoint.transform.position = evt.position;//小圆在玩家按下的位置

            }

           //player.SetMoveDir(dir.normalized);传入角色移动方向


        };

      
    }

先获取imgTouch上的监听脚本PEListener,然后设置PElistener的委托方法,我们这里要用到的是按下,松开和拖拽三种操作,用(委托参数)=>匿名函数可以更方便地设置委托方法。

evt.position,将屏幕看成左下角为原点(0,0),右上角为(屏宽,屏高)一个矩形,该坐标就是玩家触碰的位置在该矩形中的坐标。为什么要着重讲这个屏幕坐标,请往下看。

第三步unity里的设置和界面实现

canvas先做如此设置

 这一步就回答了刚刚的那个问题,有时候屏幕坐标不等于世界坐标,例如屏幕空间是由摄像机控制时,而这个屏幕空间覆盖的设置会让屏幕坐标一定等于世界坐标,也就是为什么imgDirBg.transform.position 可以直接等于 evt.position的原因。

接着我们在canvas下新建三个img

 imgTouch不需要设置图片且要比大圆还要大,它们的关系类似于这样

 接着改变imgTouch透明度使其看不见。现在揭晓为什么要用这个东西来接受玩家的操作,可能有的小伙伴在阅读RegisterTouchEvts()方法就猜出来了(提示:大圆位置改变)。

3

2

1

-

 玩家在触屏时并不是只能手指在摇杆上时才接收操作信息,而是手落在哪里摇杆就在哪里,此时我们增加一个可控制摇杆的具体范围,并且使大圆在玩家按下时改变位置。

现在我们只需给imgTouch挂载上PEListener,给任意一个游戏物体挂上UIWnd就可以使用这个摇杆了

我们要知道为什么,你知道为什么吗,如果你知道,那么你就知道了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值