Home > front end >  How to use Unity ARKit to activate objects in scene rather than prefabs
How to use Unity ARKit to activate objects in scene rather than prefabs

Time:12-11

I have a selection of game objects that I associate with different markers using ARKit in Unity. These game objects are currently prefabs, but they are limited in number and each is unique. It would make more sense if the prefabs were inactive game objects in the scene that became active when the device camera identifies a marker. Is there a way to change the code below to make game objects set to active instead of instantiating a prefab?

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

CodePudding user response:

So instead of prefabs simply reference all the existing objects in your scene into placeablePrefabs (of course change that name later!) and then do

[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);
    }
}

You could even consider use some free asset like e.g. SerializableDictionary and do it all via the Inspector directly.

  • Related