可以实现在水平面的2D物体被摇杆移动,移动方式有3种。
1、水平360度转向移动(移动前先转向摇杆的方向,然后再移动)
2、水平360度不转向移动
3、4方向(上,下,左,右)移动
在这里插入代码片
/*--------------------------------------------------------------------
- Author Name: DXL
- Creation Time: 2018.9.28
- File Describe: 摇杆,控制物体在平面上移动
- ------------------------------------------------------------------*/
using UnityEngine;
using UnityEngine.EventSystems;
//控制人物行走的方向
public enum RockerMoveType
{
[EnumNameAttribute(“上下左右四方向角度不旋转移动”)]
Horizontal4, //水平面(x,y)4方向
[EnumNameAttribute("360度不旋转移动")]
Horizontal360, //水平面(x,y)360度方向,不转向
[EnumNameAttribute("360度旋转朝向角度再旋转移动")]
TurnHead360, //水平面(x,y)360度,转移前,先旋转头部位置,朝向移动的方向后再移动位置
}
public class Rocker : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[InspectorShow(“拖动的摇杆”)]
public GameObject rockerIcon; //当前摇杆使用的图片
[InspectorShow("控制的物体")]
public GameObject role; //当前摇杆控制的人物
[EnumNameAttribute("物体的移动方向")]
public RockerMoveType moveType; //当前摇杆行走方向
[InspectorShow("摇杆移动半径")]
public float maxRadius = 200; //摇杆拖动的最大距离
[InspectorShow("移动速度")]
public float roleMoveSpeed = 0.5f; //控制人物的移动速度
[InspectorShow("减速倍率(Horizontal360)")]
public float slowSpeed = 100f; //只有 Horizontal360 方式才生效,此时实际速度是 roleMoveSpeed / slowSpeed
Vector2 firstTouchPoint; //首次触摸点(拖动摇杆起始点)
float hor; //摇杆 x坐标
float ver; //摇杆 y坐标
void Update()
{
if (rockerIcon == null || rockerIcon == null)
{
return;
}
hor = rockerIcon.transform.localPosition.x;
ver = rockerIcon.transform.localPosition.y;
Vector3 direction = new Vector3(hor, ver, 0);
//以12点方向为起始点进行计算角度,最大为180度,不区分方向
float angle = Vector3.Angle(direction, Vector3.up);
//区分方向,变成360度方向
angle = CalculateAngle(angle);
if (direction != Vector3.zero)
{
if (moveType == RockerMoveType.TurnHead360)
{
role.transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
role.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
}
else if (moveType == RockerMoveType.Horizontal4)
{
if (angle <= 45 || angle >= 315)
{
//上
role.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
}
else if (angle > 45 && angle < 135)
{
//左
role.transform.Translate(Vector3.left * Time.deltaTime * roleMoveSpeed);
}
else if (angle >= 135 && angle < 225)
{
//下
role.transform.Translate(Vector3.down * Time.deltaTime * roleMoveSpeed);
}
else if (angle >= 225 && angle < 315)
{
//右
role.transform.Translate(Vector3.right * Time.deltaTime * roleMoveSpeed);
}
}
else if (moveType == RockerMoveType.Horizontal360)
{
role.transform.Translate(new Vector3(hor, ver, 0) * Time.deltaTime * roleMoveSpeed / slowSpeed);
}
}
}
//转换角度 ang 从 0 - 180,要变成 0 - 360
float CalculateAngle(float ang)
{
if (hor >= 0 && ver > 0)
{
//第一象限
ang = 360 - ang;
}
else if (hor <= 0 && ver > 0)
{
//第二象限
}
else if (hor < 0 && ver <= 0)
{
//第三象限
}
else if (hor > 0 && ver <= 0)
{
//第四象限
ang = 360 - ang;
}
return ang;
}
//开始移动
public void OnBeginDrag(PointerEventData eventData)
{
firstTouchPoint = eventData.position;
}
//移动中
void IDragHandler.OnDrag(PointerEventData eventData)
{
//得到触摸点与原始点角度
Vector2 vec = eventData.position - firstTouchPoint;
//获取向量长度
float distance = Vector3.Magnitude(vec);
float radius = Mathf.Clamp(distance, 0, maxRadius);
rockerIcon.transform.localPosition = vec.normalized * radius;
}
//移动结束
void IEndDragHandler.OnEndDrag(PointerEventData eventData)
{
//移动结束后,让摇杆归位
rockerIcon.transform.localPosition = Vector3.zero;
}
}
上面会有一些Inspector面板显示中文的方法,可以忽略。
这里是个脚本,需要将摇杆icon和受控制的物体拖到Inspector上即可生效。