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

Unity AR Core中按钮无法触发预制体生成问题求助

问题描述

需要实现两个按钮,点击按钮切换要生成的预制体类型,点击屏幕时在AR平面上生成对应预制体。目前启动后placeablePrefab字段可以通过按钮更新,但按钮点击无响应(已添加控制台日志但无输出),无论是AR Core模板还是3D模板创建的项目都无法正常工作。

问题代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

[RequireComponent(typeof(ARRaycastManager))]
public class NewBehaviourScript : MonoBehaviour
{
    private ARRaycastManager raycastManager;
    private GameObject spawnedObject;
    private List<GameObject> placedPrefabsList = new List<GameObject>();
    [SerializeField]
    private int maxPrefabSpawnCount;
    private int placedPrefabCount;
    public GameObject placeablePrefab;
    static List<ARRaycastHit> s_Hits = new List<ARRaycastHit>();

    private void Awake()
    {
        raycastManager = GetComponent<ARRaycastManager>();
    }

    bool TryGetTouchPosition(out Vector2 touchPosition)
    {
        if (Input.touchCount > 0)
        {
            Debug.Log("Input.touchCount: " + Input.touchCount);

            if (Input.GetTouch(0).phase == TouchPhase.Began)
            {
                Debug.Log("Touch detected at position: " + Input.GetTouch(0).position);
                touchPosition = Input.GetTouch(0).position;
                return true;
            }
            else
            {
                Debug.Log("Touch phase is not Began: " + Input.GetTouch(0).phase);
            }
        }

        touchPosition = default;
        return false;
    }

    private void Update()
    {
        if (!TryGetTouchPosition(out Vector2 touchPosition))
        {
            return;
        }
        if (raycastManager.Raycast(touchPosition, s_Hits, TrackableType.PlaneWithinPolygon))
        {
            var hitPose = s_Hits[0].pose;
            if (placedPrefabCount < maxPrefabSpawnCount)
            {
                Debug.Log("1");
                SpawnPrefab(hitPose);
            }
        }
    }

    private void SpawnPrefab(Pose hitPose)
    {
        spawnedObject = Instantiate(placeablePrefab, hitPose.position, hitPose.rotation);
        placedPrefabsList.Add(spawnedObject);
        placedPrefabCount++;
    }

    public void SetPrefabType(GameObject prefabType)
    {
        placeablePrefab = prefabType;
        Debug.Log("Prefab updated to: " + prefabType.name);
    }
}
相关截图
  • 按钮与脚本绑定设置
  • AR场景组件配置
  • 预制体与参数设置
  • 控制台日志输出
排查与解决方案

1. 优先检查按钮事件绑定

  • 打开Unity编辑器,选中按钮对象,在Inspector面板的OnClick()事件列表中:
    • 确认已拖拽挂载了NewBehaviourScript的GameObject到对象选择框
    • 确认选择了NewBehaviourScript -> SetPrefabType(GameObject)方法
    • 确认已将对应预制体拖拽到方法的参数输入框中
  • 给SetPrefabType方法添加日志(如代码中新增的Debug.Log),测试按钮点击是否触发日志输出

2. 修复触摸输入与UI冲突问题

当前代码未区分UI触摸和AR屏幕触摸,导致按钮点击可能被AR触摸逻辑拦截。修改TryGetTouchPosition方法,添加UI判断:

bool TryGetTouchPosition(out Vector2 touchPosition)
{
    if (Input.touchCount > 0)
    {
        var touch = Input.GetTouch(0);
        // 判断触摸是否在UI上,若是则直接返回
        if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
        {
            Debug.Log("Touch is over UI element");
            touchPosition = default;
            return false;
        }

        Debug.Log("Input.touchCount: " + Input.touchCount);

        if (touch.phase == TouchPhase.Began)
        {
            Debug.Log("Touch detected at position: " + touch.position);
            touchPosition = touch.position;
            return true;
        }
        else
        {
            Debug.Log("Touch phase is not Began: " + touch.phase);
        }
    }

    touchPosition = default;
    return false;
}

注意:确保场景中存在EventSystem对象(UI模板默认包含,若没有可右键UI -> Event System创建)

3. 检查AR相关配置(AR Core项目)

  • 确认场景中已添加ARSession和ARSessionOrigin组件
  • 确认ARRaycastManager已正确挂载到ARSessionOrigin对象上
  • 确认maxPrefabSpawnCount在Inspector中设置了大于0的值,否则无法生成预制体
  • 测试时确保AR平面已被检测到(屏幕上显示平面网格),否则raycastManager.Raycast不会返回true

4. 3D模板项目适配

若使用3D模板而非AR Core模板,当前代码依赖AR组件会报错。需移除AR相关代码,修改生成逻辑为基于鼠标/触摸点击3D平面:

// 替换Update方法中的AR射线检测为普通射线检测
private void Update()
{
    if (!TryGetTouchPosition(out Vector2 touchPosition))
    {
        return;
    }

    Ray ray = Camera.main.ScreenPointToRay(touchPosition);
    if (Physics.Raycast(ray, out RaycastHit hit))
    {
        if (placedPrefabCount < maxPrefabSpawnCount)
        {
            Debug.Log("Spawning prefab at 3D hit point");
            SpawnPrefab(new Pose(hit.point, Quaternion.LookRotation(hit.normal)));
        }
    }
}

同时确保场景中有可被射线检测的平面(添加Collider组件)

内容的提问来源于stack exchange,提问作者acr1d _

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:12:11