如何使用 Unity ARKit 激活场景中的对象而不是预制件

Posted

技术标签:

【中文标题】如何使用 Unity ARKit 激活场景中的对象而不是预制件【英文标题】:How to use Unity ARKit to activate objects in scene rather than prefabs 【发布时间】:2021-12-10 14:31:13 【问题描述】:

我有一些游戏对象,我使用 Unity 中的 ARKit 将它们与不同的标记相关联。这些游戏对象目前是预制件,但数量有限,而且每一个都是独一无二的。如果预制件是场景中的非活动游戏对象,当设备摄像头识别标记时变为活动状态,这将更有意义。有没有办法更改下面的代码以使游戏对象设置为活动而不是实例化预制件?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.ARFoundation;

[RequireComponent(typeof(ARTrackedImageManager))]

public class ImageTracking : MonoBehaviour


    [SerializeField]
    private GameObject[] placeablePrefabs;

    private Dictionary<string, GameObject> spawnedPrefabs = new Dictionary<string, GameObject>();
    private ARTrackedImageManager trackedImageManager;

    private void Awake()
    
        trackedImageManager = FindObjectOfType<ARTrackedImageManager>();

        foreach(GameObject prefab in placeablePrefabs)
        
            GameObject newPrefab = Instantiate(prefab, Vector3.zero, Quaternion.identity);
            newPrefab.name = prefab.name;
            spawnedPrefabs.Add(prefab.name, newPrefab);
        
    

    private void OnEnable()
    
        trackedImageManager.trackedImagesChanged += ImageChanged;
    

    private void OnDisable()
    
        trackedImageManager.trackedImagesChanged -= ImageChanged;
    

    private void ImageChanged(ARTrackedImagesChangedEventArgs eventArgs)
    
        foreach(ARTrackedImage trackedImage in eventArgs.added)
        
            UpdateImage(trackedImage);
        
        foreach (ARTrackedImage trackedImage in eventArgs.updated)
        
            UpdateImage(trackedImage);
        
        foreach (ARTrackedImage trackedImage in eventArgs.removed)
        
            spawnedPrefabs[trackedImage.name].SetActive(false);
        
    

    private void UpdateImage(ARTrackedImage trackedImage)
    
        string name = trackedImage.referenceImage.name;
        Vector3 position = trackedImage.transform.position;

        GameObject prefab = spawnedPrefabs[name];
        prefab.transform.position = position;
        prefab.SetActive(true);

        foreach(GameObject go in spawnedPrefabs.Values)
        
            if(go.name != name)
            
                go.SetActive(false);
            
        
    

【问题讨论】:

【参考方案1】:

因此,无需预制件,只需将场景中的所有现有对象都引用到 placeablePrefabs(当然以后再更改该名称!)然后做

[SerializeField]
private GameObject[] showAbleObjects;

private Dictionary<string, GameObject> nameToGameObject = new Dictionary<string, GameObject>();

private void Awake()

    trackedImageManager = FindObjectOfType<ARTrackedImageManager>();

    foreach(var obj in showAbleObjects)
    
        nameToGameObject.Add(obj.name, obj);
    


您甚至可以考虑使用一些免费资产,例如SerializableDictionary 并直接通过 Inspector 完成所有操作。

【讨论】:

效果很好!我更改了一些不再需要的其他行,当然还有命名约定。谢谢你,derHugo。

以上是关于如何使用 Unity ARKit 激活场景中的对象而不是预制件的主要内容,如果未能解决你的问题,请参考以下文章

在 ARKit 中同时显示相机捕获图像和场景背景

ARKit - 如何沿识别的表面移动物体?

为啥 iPhone XR、XS 和 XS Max 没有将环境图像应用到 ARKit 中的场景?

如何改善 ARKit 3.0 中的人物遮挡

使用 ARKit 显示 DAE 文件并跟踪场景中的锚点

ARKit - 在场景编辑器中向对象添加纹理