Unity 2D转盘的实现
关键点
- FixIconRotation() 每帧进行子图标修正,保持竖直;
- 停止拖拽将会旋转到某个固定角度,这个角度由最后的释放鼠标时的角度决定;
- m_nIndex = (int)(Mathf.Round(transform.rotation.eulerAngles.z / m_fAngle));
这个值确定了最终将转向哪个角度; - 记得绑定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转盘的实现
- 转盘倾斜45度,子Icon不能成为转盘子物体,否则角度关系容易混乱;
- FixedChildRotation()每帧进行子物体旋转角度纠正;
- Start函数初始化最终可以转向的角度并存储;
- EndDrag()判断最终将要转向最近的角度;
- 旋转使用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的层级关系:
- 最终效果: