EDIT 由于我发现finger ID得到的数字与触控的原始索引值相同,所以我做了一个方法,将废弃触控中保存的finger ID重置为-1。发了一个完整的答案。
我正在尝试为我的简单射击游戏实现2个手指的多点触控,其中一个手指射击如果先在屏幕下方的定义区域按住,会持续影响玩家的旋转,另一个手指控制射击按钮,也可以装上更多的子弹。
一开始我试着把TouchPhase=Began时的触摸位置存储在一个Vector3数组中,有两个地方,其他类检查数组中的数值是否以及哪一个符合规则开始它们的活动。问题是,如果早先的手指被抬起,手指索引似乎会下降,所以如果我按下例如瞄准->射击按钮,然后抬起瞄准,瞄准按钮就会卡在加载中,因为它试图跟踪触摸(1),而实际上变成了(0)。
解决方法似乎应该是使用fingerId,它可以为触摸产生一个一致的数字,而不管它的索引是什么。问题是--我写的东西比以前更糟糕。即使我按错了地方,它也会激活函数,所以即使不该按的地方,if 语句似乎也符合要求。代码有什么问题?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchControls : MonoBehaviour
{
public static int aimID;
public static int shootID;
// Start is called before the first frame update
void Start()
{
aimID = 0;
shootID = 0;
}
// Update is called once per frame
void Update()
{
for (int i = 0; i < Input.touchCount && i < 2; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
Vector2 pos = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
if (pos.x == Mathf.Clamp(pos.x, -2.5f * SceneScale.ratio, 2.5f * SceneScale.ratio) &&
pos.y <= Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 0)).y + (2 * SceneScale.ratio))
{
aimID = Input.GetTouch(i).fingerId;
}
else if (Vector2.Distance(pos, ShotButton.position) <= ShotButton.scale.x)
{
shootID = Input.GetTouch(i).fingerId;
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Android;
public class ShotButton : MonoBehaviour
{
public static bool[] time;
static public Vector3 scale;
static public Vector2 position;
// Start is called before the first frame update
void Start()
{
scale = gameObject.transform.localScale;
position = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
time = new bool[2];
time[0] = false;
time[1] = false;
}
// Update is called once per frame
public void FixedUpdate()
{
for (int i = 0; i < Input.touchCount && i < 2; i++)
{
time[i] = false;
if (Input.GetTouch(i).fingerId == TouchControls.shootID)
{
time[i] = true;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public GameObject player;
public static bool isDead = false;
public float rot;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
public void FixedUpdate()
{
for (int i = 0; i < Input.touchCount && i < 2; i++)
{
if (Input.GetTouch(i).fingerId == TouchControls.aimID)
{
rot = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position).x * 80 / (2.5f * SceneScale.ratio);
}
}
rot = Mathf.Clamp(rot, -80, 80);
player.transform.rotation = Quaternion.Euler(0, 0, rot);
}
}
由于这个问题没有得到答案,我也没有找到不同的方法,所以我把我发现的工作方法贴出来--尽管可能还有其他更有效的解决方案。
手指ID与触摸的原始索引相匹配,可以是0或以上。所以我为每个控制方法保存了一个唯一的整数类型,并将其初始化为值-1,当TouchPhase.Began的触控落在为其中一个按钮或控制区域定义的边界内时,我给这个唯一的整数类型记录的手指ID值,然后由相应的方法来寻找每一帧中触控所在的索引,当带有这个手指ID的触控返回TouchPhase.Ended时,它再次给保存的整数值-1,在任何触控中都找不到这个值,因此它停止了控制方法。