Unity关于手游端摇杆移动、摇杆按钮冲突问题
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、摇杆移动问题
1.问题重现
①摇杆移动时,通过控制角色的刚体运动。
②当摇杆移动到游戏区域外松开时,后面对摇杆进行操作无响应。
③使用的是Drag事件来写的拖动逻辑。
2、解决
解决思路:摇杆控制角色移动时,不能通过控制角色的刚体移动,而要通过改变角色的位置来移动。
(有BUG)刚体移动代码如下(hor、ver为获取了摇杆移动的方向,判断设置了区间-1,1):
direction.x = hor;
direction.y = ver * 0.7f;
rig.velocity = direction * moveSpeed * 50 * Time.deltaTime;
if (rig.velocity.x >= 0.05)
{
transform.rotation = new Quaternion(0, 0, 0, 0);
}
else if (rig.velocity.x <= -0.05)
{
transform.rotation = new Quaternion(0, 180, 0, 0);
}
(可用)使用Translate的移动代码如下:
direction.x = hor;
direction.y = ver * 0.7f;
player.transform.Translate(direction*moveSpeed*Time.deltaTime);
(可用)最后附上完整代码:
private float moveSpeed;//移动速度
private Vector2 direction;//移动方向
private PlayerBehaviour behaviour;//角色行为
// public Transform Yingzi;//影子
public Transform big; //摇杆背景
public Transform small;//摇杆中心
private float radius = 250;//摇杆半径
private Vector2 moveCenter;//移动中心
private Vector2 mouseToCenterVect;//鼠标移动到中心的向量
private float mouseToCenterDistance;//鼠标到中心点的距离
private float hor;//获取水平方向
private float ver;//获取垂直方向
public Transform player;//主角
// Start is called before the first frame update
void Start()
{
behaviour = player.GetComponent<PlayerBehaviour>();
}
/// <summary>
/// 开始拖动时
/// </summary>
public void Begin(BaseEventData data)
{
//移动中心点赋值
moveCenter = big.position;
}
/// <summary>
/// 拖动中
/// </summary>
/// <param name="_">UI事件数据</param>
public void OnDrag(BaseEventData _)
{
//中心点到触摸点的向量赋值
mouseToCenterVect = (Vector2)Input.mousePosition - moveCenter;
//中心点到触摸点的距离计算
mouseToCenterDistance = Mathf.Clamp(mouseToCenterVect.magnitude, 0, 250);
//根据距离来判断摇杆中心的位置
if (mouseToCenterDistance < radius)
{
//若是距离小于最大半径,这里取向量的归一值,就是模为1的向量,乘上中心到触摸点的距离,这个就是摇杆中心应该移动的方向和距离,并且移动是在移动中心的基础上,所以加上移动中心的坐标
small.position = mouseToCenterVect.normalized * mouseToCenterDistance + moveCenter;
}
else
{
//同上,不过就是限定了移动的最大距离
small.position = mouseToCenterVect.normalized * radius + moveCenter;
}
//摇杆中心的X - 移动中心的x就是水平的变化值,这里 /100 控制_hor在(-1,,1)之间
hor = (small.position.x - moveCenter.x) / 250;
//摇杆中心的Y - 移动中心的Y就是垂直的变化值,这里 /100 控制_hor在(-1,,1)之间
ver = (small.position.y - moveCenter.y) / 250;
}
/// <summary>
/// 结束时
/// </summary>
public void End(BaseEventData data)
{
PointerEventData _ = data as PointerEventData;
if (_ == null)
return;
//水平移动值归零
hor = 0;
//垂直移动值归零
ver = 0;
small.localPosition = big.localPosition;
}
void Update()
{
moveSpeed = behaviour.Speed;
direction.x = hor;
direction.y = ver * 0.7f;
}
private void FixedUpdate()
{
player.transform.Translate(direction*moveSpeed*Time.deltaTime);
}
代码详细参考:https://blog.csdn.net/Mr_Sun88/article/details/84680361)
(tips:需要添加Event Trigger组件,并添加Begin Drag、Drag、End Drag)
二、摇杆按钮冲突问题
1.问题重现
导到手机上后:
①摇杆的拖动区域
②左手拖动摇杆时,右手按下按钮,摇杆会往右边移动。
2.解决
解决思路:使用Drag事件所使用到的Input.mousePosition(鼠标位置)不适用于手游的使用,而应该使用多点触控来控制摇杆。
多点触控代码如下:
void Start()
{
Input.multiTouchEnabled = true;//开启多点触控
}
void Update()
{
if (Input.touchCount <= 0) //触摸点数量为0
return;
if (Input.touchCount >= 1)//触摸点数量不为0
{
//当触控为左边区域,左边控制虚拟摇杆从而控制player移动
if (Input.GetTouch(0).position.x < Screen.width * 0.5f)
{
//只要有左边区域被触摸了,只获取第一次触摸的点
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
//移动中心点赋值
moveCenter = big.position;
}
//第一次手指触摸移动
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
//中心点到触摸点的向量赋值
mouseToCenterVect = (Vector2)Input.GetTouch(0).position - moveCenter;
//中心点到触摸点的距离计算
mouseToCenterDistance = Mathf.Clamp(mouseToCenterVect.magnitude, 0, 250);
//根据距离来判断摇杆中心的位置
if (mouseToCenterDistance < radius)
{
//若是距离小于最大半径,这里取向量的归一值,就是模为1的向量,乘上中心到触摸点的距离,这个就是摇杆中心应该移动的方向和距离,并且移动是在移动中心的基础上,所以加上移动中心的坐标
small.position = mouseToCenterVect.normalized * mouseToCenterDistance + moveCenter;
}
else
{
//同上,不过就是限定了移动的最大距离
small.position = mouseToCenterVect.normalized * radius + moveCenter;
}
//摇杆中心的X - 移动中心的x就是水平的变化值,这里 /100 控制_hor在(-1,,1)之间
hor = (small.position.x - moveCenter.x) / 250;
//摇杆中心的Y - 移动中心的Y就是垂直的变化值,这里 /100 控制_hor在(-1,,1)之间
ver = (small.position.y - moveCenter.y) / 250;
}
//第一次手指触摸离开
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
//水平移动值归零
hor = 0;
//垂直移动值归零
ver = 0;
small.localPosition = big.localPosition;
}
}
}
}
完整代码如下:
private float moveSpeed;//移动速度
private Vector2 direction;//移动方向
private PlayerBehaviour behaviour;//角色行为
// public Transform Yingzi;//影子
public Transform big; //摇杆背景
public Transform small;//摇杆中心
private float radius = 250;//摇杆半径
private Vector2 moveCenter;//移动中心
private Vector2 mouseToCenterVect;//鼠标移动到中心的向量
private float mouseToCenterDistance;//鼠标到中心点的距离
private float hor;//获取水平方向
private float ver;//获取垂直方向
public Transform player;//主角
void Start()
{
behaviour = player.GetComponent<PlayerBehaviour>();
Input.multiTouchEnabled = true;
}
void Update()
{
moveSpeed = behaviour.Speed;
if (Input.touchCount <= 0)
return;
if (Input.touchCount >= 1)
{
//当触控为左边区域,左边控制虚拟摇杆从而控制player移动
if (Input.GetTouch(0).position.x < Screen.width * 0.5f)
{
//只要有左边区域被触摸了,不管Input.touchCount等于多少,都会执行下面
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
//移动中心点赋值
moveCenter = big.position;
}
//手指触摸移动
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
//中心点到触摸点的向量赋值
mouseToCenterVect = (Vector2)Input.GetTouch(0).position - moveCenter;
//中心点到触摸点的距离计算
mouseToCenterDistance = Mathf.Clamp(mouseToCenterVect.magnitude, 0, 250);
//根据距离来判断摇杆中心的位置
if (mouseToCenterDistance < radius)
{
//若是距离小于最大半径,这里取向量的归一值,就是模为1的向量,乘上中心到触摸点的距离,这个就是摇杆中心应该移动的方向和距离,并且移动是在移动中心的基础上,所以加上移动中心的坐标
small.position = mouseToCenterVect.normalized * mouseToCenterDistance + moveCenter;
}
else
{
//同上,不过就是限定了移动的最大距离
small.position = mouseToCenterVect.normalized * radius + moveCenter;
}
//摇杆中心的X - 移动中心的x就是水平的变化值,这里 /100 控制_hor在(-1,,1)之间
hor = (small.position.x - moveCenter.x) / 250;
//摇杆中心的Y - 移动中心的Y就是垂直的变化值,这里 /100 控制_hor在(-1,,1)之间
ver = (small.position.y - moveCenter.y) / 250;
}
//手指触摸离开
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
//水平移动值归零
hor = 0;
//垂直移动值归零
ver = 0;
small.localPosition = big.localPosition;
}
}
}
direction.x = hor;
direction.y = ver * 0.7f;
}
private void FixedUpdate()
{
player.transform.Translate(direction*moveSpeed*Time.deltaTime);
}
代码详细参考:https://blog.csdn.net/qq_39745907/article/details/104010204
tips:这个不需要添加Event Trigger事件。