Unity摇杆制作及代码编写

 

今天学习案例项目时,需要制作摇杆,我 就把这个摇杆制作过程记录一下,以便以后忘记了可以查看。

摇杆分为三个部分,
1.摇杆可以出现的区域
2.摇杆背景图
3.摇杆中心可以拖动的圆点

----------------------代码部分-----------------
创建PEListener(UI事件监听插件类):用于监听摇杆的点击、拖拽等事件,通过代码挂载在摇杆获取区域(imgTouch)物体上

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

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

    public void OnPointerDown(PointerEventData eventData)
    {
       if(onClickDown !=null )
        {
            onClickDown(eventData);
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (onClickUp  != null)
        {
            onClickUp(eventData);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (onDrag  != null)
        {
            onDrag(eventData);
        }
    }
   
}

在WindowRoot(UI窗口基类)中定义需要监听的事件

//判断物体是否有某个组件 如果没有给这物体添加这个组件 
protected T GetOrAddComponect<T>(GameObject  go) where T:Component 
    {
        T t = go.GetComponent<T>();
        if(t==null )
        {
           t= go.AddComponent<T>();
        }
        return t;
    }
    

    #region ClickEvts
    protected void OnClickDown(GameObject go,Action<PointerEventData>cb)
    {
        PEListener listener = GetOrAddComponect<PEListener>(go);
        listener.onClickDown = cb;
    }

    protected void OnClickUp(GameObject go, Action<PointerEventData> cb)
    {
        PEListener listener = GetOrAddComponect<PEListener>(go);
        listener.onClickUp  = cb;
    }

    protected void OnDrag(GameObject go, Action<PointerEventData> cb)
    {
        PEListener listener = GetOrAddComponect<PEListener>(go);
        listener.onDrag  = cb;
    }
    #endregion

在MainCityWnd(主城UI界面)类中获取摇杆,继承WindowRoot类,脚本挂载在主城UI界面的根物体并编写监听的具体事件,然后把位置信息传递给主角就OK了,

public void RegisterTouchEvts()
    {
        OnClickDown(imgTouch.gameObject, (PointerEventData evt) =>
        {
            startPos = evt.position;
            SetActive(imgDirPoint, true);
            imgDirBg.transform.position = evt.position;

        });
        OnClickUp(imgTouch.gameObject, (PointerEventData evt) =>
        {
            SetActive(imgDirPoint, false);
            imgDirBg.transform.position = defaultPos;
            imgDirPoint.transform.localPosition = Vector2.zero;

            //方向信息传递给主角
            MainCitySys.Instance.SetMoveDir(Vector2.zero );


        });
        OnDrag(imgTouch.gameObject, (PointerEventData evt) =>
        {
          Vector2 dir=  evt.position - startPos;
            float len = dir.magnitude;
            if(len>pointDis )
            {
                Vector2 clampDir = Vector2.ClampMagnitude(dir, pointDis );
                imgDirPoint.transform.position = startPos + clampDir;
            }
            else
            {
                imgDirPoint.transform.position = evt.position;
            }
            //方向信息传递给主角
            MainCitySys.Instance.SetMoveDir(dir.normalized);
        });
       
    }

MainCitySys(主城系统),加载主角模型,打开主城UI界面,播放背景音乐

//获取坐标位置 
public void SetMoveDir(Vector2 dir)
    {
        if(dir ==Vector2.zero )
        {
            playerCtrl.SetBlend(Constants.BlendIdle);
        }
        else
        {
            playerCtrl.SetBlend(Constants.BlendWald );

        }
        //把坐标位置传递给主角(这个坐标使用Vector2.SignedAngle(),可以得出自身坐标与世界坐标的之间的角度,继而主角进行方向旋转)
        playerCtrl.Dir = dir;
    }

 

第二种写法:



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class UIJointed : MonoBehaviour, IPointerDownHandler,IPointerUpHandler ,IDragHandler 
{
    public Image IconImage;//摇杆内的小圆
    private Vector3 startPos;//小圆的初始化位置
    public int radius=5;//半径
    [HideInInspector]
    public bool isMove = false;//是否移动
    [HideInInspector]
   public  Vector3 mdaltc;//摇杆控制的方向信息,
   //方向
    [HideInInspector]
    public float angle=0;//摇杆控制的旋转角度信息

    public RectTransform Jointed;//摇杆
     RectTransform rect;//摇杆的矩形背景,显示的区域
    private Vector2 thisPos;//摇杆初始位置
    void Start()
    {
        Jointed.gameObject.SetActive(false);//隐藏摇杆
        rect = GetComponent<RectTransform>();
        //获取初始化位置
        startPos = IconImage.transform.localPosition;
        thisPos = Jointed. transform.localPosition;
    }

    /// <summary>
    /// 拖拽中
    /// </summary>
    /// <param name="eventData"></param>
    public void OnDrag(PointerEventData eventData)
    {
      //  Debug.Log("This is Drag");
        Vector2 uiPoint;//获取鼠标在摇杆背景上的位置
        //将一个屏幕空间坐标转换到RectTransform本地空间位于矩形上的一个位置
        RectTransformUtility.ScreenPointToLocalPointInRectangle(Jointed  as RectTransform, Input.mousePosition, eventData.pressEventCamera, out uiPoint);
        Range(uiPoint);
        
    }
    //小圆是否超出范围
    void Range(Vector3 uiPoint)
    {
        isMove = true;
       Vector2  delta = uiPoint - startPos;//方向
        if ((uiPoint - startPos).magnitude < radius)//移动时向量的长度小于半径,即在范围内
        {
            //拖拽时 小圆在摇杆上的位置
            IconImage.transform.localPosition = uiPoint;
        }
        else//超出范围
        {
           Vector3 v= Vector3.ClampMagnitude(delta, radius);//现在一个方向的最大长度
            //delta.Normalize();//向量归一化
            //delta *= radius;//最大
            IconImage.transform.localPosition = v + startPos;
        }
        mdaltc =  IconImage.transform.localPosition - startPos;
        #region 摇杆控制的角度信息
        float dotValue = Vector2.Dot(Vector2.up.normalized, mdaltc.normalized);//两个向量夹角的余弦值
        angle= Mathf.Acos(dotValue)*Mathf.Rad2Deg;//通过余弦值获得弧度角,转换为角度
        if(delta .x>0)
        {
            angle = -angle;
        }
        #endregion
    }

    /// <summary>
    /// 按下
    /// </summary>
    /// <param name="eventData"></param>
    public void OnPointerDown(PointerEventData eventData)
    {

        Jointed.gameObject.SetActive(true);//显示摇杆
        Vector2 uiPoint;
        //将一个屏幕上的位置转换到一个矩形上的位置
        RectTransformUtility.ScreenPointToLocalPointInRectangle(transform  as RectTransform, Input.mousePosition, eventData.pressEventCamera, out uiPoint);
        Jointed.localPosition = uiPoint;//设置摇杆出现的位置

    }


    /// <summary>
    /// 抬起
    /// </summary>
    /// <param name="eventData"></param>
    public void OnPointerUp(PointerEventData eventData)
    {

        Jointed.gameObject.SetActive(false);
        Jointed.localPosition = thisPos ;//摇杆恢复初始位置
        IconImage.transform.localPosition = startPos;//小球恢复到原来位置
        isMove = false;//不能移动
        mdaltc = Vector3.zero;//方向置空
        angle = 0;//角度置零
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//挂载需要用摇杆控制的物体上,
public class JointedMove : MonoBehaviour
{
    UIJointed ui;
    public float  Speed = 10;//移动 速度
    void Awake()
    {
        ui = GameObject.FindObjectOfType<UIJointed>();
    }

    void Update()
    {
        Debug.Log(ui.name);
        if (ui.isMove )
        {
           
           //移动
            transform.localPosition += ui.mdaltc * Speed * Time.deltaTime;
            //旋转
            transform.localEulerAngles =new Vector3 (0,0,ui.angle );
           

        }
 
       
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值