Unity 转盘的实现

Unity 2D转盘的实现

关键点

  1. FixIconRotation() 每帧进行子图标修正,保持竖直;
  2. 停止拖拽将会旋转到某个固定角度,这个角度由最后的释放鼠标时的角度决定;
  3. m_nIndex = (int)(Mathf.Round(transform.rotation.eulerAngles.z / m_fAngle));
    这个值确定了最终将转向哪个角度;
  4. 记得绑定EventTrigger触发StartDrag()和StopDrag();
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurnPanel2D : MonoBehaviour
{
    public RectTransform[] icons;
    private bool m_bIsDrag = false;
    private int m_nIndex = 0;
    public int m_nIconCount = 5;
    private float m_fAngle = 72.0f;

    void Start()
    {
        m_fAngle = 360.0f / m_nIconCount;
    }

    void Update()
    {
        FixIconRotation();
        Dragging();
    }

    void FixIconRotation()
    {
        foreach (RectTransform icon in icons)
        {
            icon.rotation = Quaternion.Slerp(icon.rotation, Quaternion.Euler(0, 0, 0), 0.3f);
        }
    }

    public void StartDrag()
    {
        m_bIsDrag = true;
    }

    void Dragging()
    {
        /*
        //触摸操作
        if (m_bIsDrag && Input.touchCount > 0)
        {
            Debug.Log("TOUCH!");
            transform.Rotate(0, 0, -Input.GetTouch(0).deltaPosition.x);
        }
        */

        //鼠标操作
        if (m_bIsDrag && Input.GetMouseButton(0))
        {
            Debug.Log("MOUSE!");
            transform.Rotate(0, 0, Input.GetAxis("Mouse X") * 5);
        }
        else
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0, 0, m_nIndex * m_fAngle), 0.25f);
        }
    }

    public void StopDrag()
    {
        m_nIndex = (int)(Mathf.Round(transform.rotation.eulerAngles.z / m_fAngle));
        m_bIsDrag = false;
    }
}
  • 效果图

这里写图片描述


Unity 3D转盘的实现

  1. 转盘倾斜45度,子Icon不能成为转盘子物体,否则角度关系容易混乱;
  2. FixedChildRotation()每帧进行子物体旋转角度纠正;
  3. Start函数初始化最终可以转向的角度并存储;
  4. EndDrag()判断最终将要转向最近的角度;
  5. 旋转使用Slerp比Lerp更好平滑一些;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurnPanel3D : MonoBehaviour {

    //职业转盘
    public Transform m_turnObj;
    //有几种职业
    public int m_nJobCount = 4;
    //单个职业
    public Transform[] m_transforms;
    //每个职业间隔的角度
    private float m_fGapAngle = 90.0f;
    //最终要转向的角度
    private Vector3 m_vec3TargetAngle = new Vector3(45, 180, 180);
    //存在的可以旋转到的角度
    public List<Vector3> m_listAngle = new List<Vector3>();
    //是否触摸滑动
    private bool m_bIsDrag = false;

    /// <summary>
    /// 职业
    /// 0 战士
    /// 1 刺客 
    /// 2 射手
    /// 3 法师
    /// </summary>
    public int m_nJobType = 0;

    void Start () {
        m_fGapAngle = 360.0f / m_nJobCount;

        //把可以旋转到的角度存储起来
        for (int i = 0; i < m_nJobCount; i++)
        {
            m_turnObj.Rotate(new Vector3(0, -m_fGapAngle, 0));
            m_listAngle.Add(m_turnObj.rotation.eulerAngles);
            //Debug.Log("m_turnObj.rotation:" + m_turnObj.rotation.eulerAngles);
        }

    }

    void Update () {
        FixedChildRotation();
        Dragging();
    }

    private void FixedChildRotation()
    {
        foreach (Transform trans in m_transforms)
        {
            trans.rotation = Quaternion.Slerp(trans.rotation, Quaternion.Euler(90,0,0), 0.35f);
        }
    }

    public void StartDrag()
    {
        m_bIsDrag = true;
    }

    public void Dragging()
    {
#if UNITY_ANDROID || UNITY_IPHONE
        //触摸操作
        if (m_bIsDrag && Input.touchCount > 0)
        {
            m_turnObj.Rotate(0, -Input.GetTouch(0).deltaPosition.x, 0);
        }
        else
        {
            m_turnObj.rotation = Quaternion.Slerp(m_turnObj.rotation, Quaternion.Euler(m_vec3TargetAngle.x, m_vec3TargetAngle.y, m_vec3TargetAngle.z), 0.25f);
        }
#endif

        //旋转时
        if (m_bIsDrag && Input.GetMouseButton(0))
        {
            m_turnObj.Rotate(new Vector3(0, Input.GetAxis("Mouse X") * 10.0f, 0));
        }
        //停止触摸,则转向最近的职业
        else
        {
            m_turnObj.rotation = Quaternion.Slerp(m_turnObj.rotation,Quaternion.Euler(m_vec3TargetAngle.x, m_vec3TargetAngle.y, m_vec3TargetAngle.z),0.25f);
        }
    }

    public void EndDrag()
    {

        float tempAngleY = m_turnObj.rotation.eulerAngles.y;
        float tempDelta = m_fGapAngle / 2; 

        //计算最终要旋转到的角度
        for (int i = 0; i < m_nJobCount; i++)
        {
            if (tempDelta > Mathf.Abs(tempAngleY - m_listAngle[i].y) || tempDelta > Mathf.Abs(tempAngleY - (m_listAngle[i].y+360)))
            {
                tempDelta = Mathf.Abs(tempAngleY - m_listAngle[i].y);
                if (tempDelta > m_fGapAngle / 2)
                {
                    tempDelta = Mathf.Abs(tempAngleY - (m_listAngle[i].y+360));
                }

                m_vec3TargetAngle = m_listAngle[i];

                if (Mathf.Abs(m_vec3TargetAngle.y - 180) < 1.0f)
                {
                    m_nJobType = 0;
                }
                else if (Mathf.Abs(m_vec3TargetAngle.y - 270) < 1.0f)
                {
                    m_nJobType = 1;
                }
                else if (Mathf.Abs(m_vec3TargetAngle.y - 0) < 1.0f)
                {
                    m_nJobType = 2;
                }
                else if (Mathf.Abs(m_vec3TargetAngle.y - 90) < 1.0f)
                {
                    m_nJobType = 3;
                }
                else
                {
                    m_nJobType = 0;
                }
            }
        }

        m_bIsDrag = false;

        SetJobType();
        //Debug.Log("m_turnObj.rotation:" + m_turnObj.rotation.eulerAngles);
    }

    public void SetJobType()
    {
        switch (m_nJobType)
        {
            case 0:
                Debug.Log("战士");
                break;
            case 1:
                Debug.Log("刺客");
                break;
            case 2:
                Debug.Log("射手");
                break;
            case 3:
                Debug.Log("法师");
                break;
            default:
                Debug.Log("战士");
                break;
        }
    }
}
  • 转盘与Icon的层级关系:

转盘与图表的层级关系

  • 最终效果:

最终效果


参考:https://www.youtube.com/watch?v=5k4KdhgnvGI

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值