Unity移动端角色触摸判定不准确,无法正确设置move状态求助
解决方案
问题根源分析
- 第一种方案中,
hit.point == transform.position永远无法成立:射线击中的是碰撞体表面,而非角色Transform的原点,加上浮点数精度误差,完全匹配的概率为0。 - 第二种方案中,
0.1f的屏幕距离阈值过小:屏幕坐标单位是像素(比如1080P屏幕下像素范围是0~1080),0.1像素的检测范围几乎无法触发触摸检测。
可靠实现方案
方案1:利用Raycast命中的碰撞体判断(推荐)
直接通过射线击中的hit.collider判断是否触碰到角色,这是最精准的方式:
using Unity.VisualScripting; using UnityEngine; using UnityEngine.UI; public class MobileControls : MonoBehaviour { public Text text; private bool move = false; private RaycastHit hit; private void Update() { if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began) { text.text = ""; Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); if (Physics.Raycast(ray, out hit)) { // 判断是否击中当前脚本挂载的角色(也可通过Tag判断:hit.collider.CompareTag("Player")) if (hit.collider.gameObject == gameObject) { move = false; } else { move = true; // 生成标记点 GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = hit.point; sphere.GetComponent<Renderer>().material.color = Color.red; sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); Destroy(sphere.GetComponent<Collider>()); } } else { // 未击中任何碰撞体,设为移动状态 move = true; } } if(Input.touchCount == 2) { text.text = "Press Space !"; } if(move) { transform.position = Vector3.MoveTowards(transform.position, hit.point, Time.deltaTime * 2f); Vector3 direction = hit.point - transform.position; Quaternion rot = Quaternion.LookRotation(direction); transform.rotation = Quaternion.RotateTowards(transform.rotation, rot, 100 * Time.deltaTime); } } }
方案2:修正屏幕坐标检测的阈值
如果坚持用屏幕坐标判断,需要将阈值改为合理的像素范围(比如50~100,根据角色屏幕大小调整):
private void Update() { if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began) { text.text = ""; Vector3 touchPos = Input.GetTouch(0).position; Vector3 playerScreenPos = Camera.main.WorldToScreenPoint(transform.position); // 调整阈值为50像素(可根据角色实际屏幕大小修改) bool touchingPlayer = Vector3.Distance(touchPos, playerScreenPos) < 50f; if (touchingPlayer) { move = false; } else { move = true; Ray ray = Camera.main.ScreenPointToRay(touchPos); if (Physics.Raycast(ray, out hit)) { GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = hit.point; sphere.GetComponent<Renderer>().material.color = Color.red; sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); Destroy(sphere.GetComponent<Collider>()); } } } if (Input.touchCount == 2) { text.text = "Press Space !"; } if (move) { transform.position = Vector3.MoveTowards(transform.position, hit.point, Time.deltaTime * 2f); Vector3 direction = hit.point - transform.position; Quaternion rot = Quaternion.LookRotation(direction); transform.rotation = Quaternion.RotateTowards(transform.rotation, rot, 100 * Time.deltaTime); } }
关键注意点
- 方案1必须确保角色身上挂载了Collider组件,且Collider范围覆盖角色全部可触摸区域。
- 若使用Tag判断角色,需给角色设置对应Tag(比如"Player"),并修改代码中的判断条件。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

