You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity移动端角色触摸判定不准确,无法正确设置move状态求助

解决方案

问题根源分析

  1. 第一种方案中,hit.point == transform.position永远无法成立:射线击中的是碰撞体表面,而非角色Transform的原点,加上浮点数精度误差,完全匹配的概率为0。
  2. 第二种方案中,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:10:18