如何使用 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 完成所有操作。
我在 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 完成所有操作。