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

How to use Unity ARKit to activate objects in scene rather than prefabs

我在 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);
            }
        }
    }
}

因此,不用预制件,只需将场景中的所有现有对象引用到 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 完成所有操作。