Я работаю над проектом, который обнаруживает некоторые изображения. Я сделал довольно простой скрипт, который позволяет мне сканировать 5 изображений, а затем размещать 5 соответствующих 3D-префабов в соответствии с каждым изображением. Также есть текст, который показывает имя отсканированного изображения, если этот процесс прошел успешно, или ограниченное отслеживание, если мы не сканируем соответствующие изображения. В основном скрипт выглядит так:
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using System.Collections.Generic;
using TMPro;
public class MultipleImageTracker : MonoBehaviour
{
[System.Serializable]
public struct TrackableImage
{
public string imageName;
public GameObject prefabToInstantiate;
}
public List trackableImages;
public GameObject statusTextPrefab;
public float statusDisplayTime = 5f;
public Canvas arCanvas;
private ARTrackedImageManager trackedImageManager;
private Dictionary spawnedPrefabs = new Dictionary();
private Dictionary statusTexts = new Dictionary();
private Dictionary lastTrackingStates = new Dictionary();
private GameObject currentActiveStatusText;
private void Awake()
{
trackedImageManager = FindObjectOfType();
if (arCanvas == null)
{
Debug.LogError("AR Canvas is not assigned!");
}
}
private void OnEnable()
{
trackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
}
private void OnDisable()
{
trackedImageManager.trackedImagesChanged -= OnTrackedImagesChanged;
}
private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
foreach (var trackedImage in eventArgs.added)
{
UpdateImage(trackedImage);
}
foreach (var trackedImage in eventArgs.updated)
{
UpdateImage(trackedImage);
}
foreach (var trackedImage in eventArgs.removed)
{
string imageName = trackedImage.referenceImage.name;
if (spawnedPrefabs.ContainsKey(imageName))
{
Destroy(spawnedPrefabs[imageName]);
spawnedPrefabs.Remove(imageName);
}
if (statusTexts.ContainsKey(imageName))
{
Destroy(statusTexts[imageName]);
statusTexts.Remove(imageName);
}
lastTrackingStates.Remove(imageName);
}
}
private void UpdateImage(ARTrackedImage trackedImage)
{
string imageName = trackedImage.referenceImage.name;
Vector3 position = trackedImage.transform.position;
TrackableImage trackableImage = trackableImages.Find(x => x.imageName == imageName);
if (trackableImage.prefabToInstantiate != null)
{
UpdateSpawnedPrefab(trackableImage, imageName, position, trackedImage.trackingState);
UpdateStatusText(imageName, trackedImage.trackingState);
}
}
private void UpdateSpawnedPrefab(TrackableImage trackableImage, string imageName, Vector3 position, TrackingState trackingState)
{
if (spawnedPrefabs.ContainsKey(imageName))
{
spawnedPrefabs[imageName].transform.position = position;
spawnedPrefabs[imageName].SetActive(trackingState == TrackingState.Tracking);
}
else
{
GameObject prefabInstance = Instantiate(trackableImage.prefabToInstantiate, position, Quaternion.identity);
prefabInstance.AddComponent();
spawnedPrefabs[imageName] = prefabInstance;
}
}
private void UpdateStatusText(string imageName, TrackingState currentTrackingState)
{
if (!lastTrackingStates.ContainsKey(imageName) || lastTrackingStates[imageName] != currentTrackingState)
{
ShowStatusText(imageName, currentTrackingState);
lastTrackingStates[imageName] = currentTrackingState;
}
}
private void ShowStatusText(string imageName, TrackingState trackingState)
{
if (currentActiveStatusText != null)
{
StopAllCoroutines();
currentActiveStatusText.SetActive(false);
}
GameObject statusTextObject;
if (!statusTexts.ContainsKey(imageName))
{
statusTextObject = Instantiate(statusTextPrefab, arCanvas.transform);
statusTexts[imageName] = statusTextObject;
RectTransform rectTransform = statusTextObject.GetComponent();
rectTransform.anchorMin = new Vector2(1, 1);
rectTransform.anchorMax = new Vector2(1, 1);
rectTransform.anchoredPosition = new Vector2(-200, -200);
rectTransform.sizeDelta = new Vector2(200, 50);
}
else
{
statusTextObject = statusTexts[imageName];
}
TextMeshProUGUI tmp = statusTextObject.GetComponent();
if (tmp != null)
{
switch (trackingState)
{
case TrackingState.Tracking:
tmp.color = Color.green;
tmp.text = $"Recognized: {imageName}";
break;
case TrackingState.Limited:
tmp.color = Color.yellow;
tmp.text = "Tracking limited...";
break;
case TrackingState.None:
tmp.color = Color.red;
tmp.text = "Lost tracking";
break;
}
}
statusTextObject.SetActive(true);
currentActiveStatusText = statusTextObject;
StartCoroutine(HideStatusText(imageName));
}
private System.Collections.IEnumerator HideStatusText(string imageName)
{
yield return new WaitForSeconds(statusDisplayTime);
if (statusTexts.ContainsKey(imageName) && statusTexts[imageName] == currentActiveStatusText)
{
statusTexts[imageName].SetActive(false);
currentActiveStatusText = null;
}
}
}
Теперь я хочу добавить некоторые взаимодействия с моими префабами, которые отображаются в соответствии с изображениями. Если я коснусь префаба, он должен увеличиться в два раза и вернуться к нормальному размеру, как простая анимация. Если я снова коснусь этого префаба, он прекратит анимацию и вернется к исходному масштабу. Я пробовал что-то вроде этого:
Я работаю над проектом, который обнаруживает некоторые изображения. Я сделал довольно простой скрипт, который позволяет мне сканировать 5 изображений, а затем размещать 5 соответствующих 3D-префабов в соответствии с каждым изображением. Также есть текст, который показывает имя отсканированного изображения, если этот процесс прошел успешно, или ограниченное отслеживание, если мы не сканируем соответствующие изображения. В основном скрипт выглядит так: [code]using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; using System.Collections.Generic; using TMPro;
public class MultipleImageTracker : MonoBehaviour { [System.Serializable] public struct TrackableImage { public string imageName; public GameObject prefabToInstantiate; }
public List trackableImages; public GameObject statusTextPrefab; public float statusDisplayTime = 5f; public Canvas arCanvas;
private ARTrackedImageManager trackedImageManager; private Dictionary spawnedPrefabs = new Dictionary(); private Dictionary statusTexts = new Dictionary(); private Dictionary lastTrackingStates = new Dictionary(); private GameObject currentActiveStatusText;
private void Awake() { trackedImageManager = FindObjectOfType(); if (arCanvas == null) { Debug.LogError("AR Canvas is not assigned!"); } }
private System.Collections.IEnumerator HideStatusText(string imageName) { yield return new WaitForSeconds(statusDisplayTime); if (statusTexts.ContainsKey(imageName) && statusTexts[imageName] == currentActiveStatusText) { statusTexts[imageName].SetActive(false); currentActiveStatusText = null; } } } [/code] Теперь я хочу добавить некоторые взаимодействия с моими префабами, которые отображаются в соответствии с изображениями. Если я коснусь префаба, он должен увеличиться в два раза и вернуться к нормальному размеру, как простая анимация. Если я снова коснусь этого префаба, он прекратит анимацию и вернется к исходному масштабу. Я пробовал что-то вроде этого: [code]using UnityEngine;
public class TouchInputHandler : MonoBehaviour { private bool isScaled = false;
void Update() { if (Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began) { Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position); RaycastHit[] hits = Physics.RaycastAll(ray);
Debug.Log("Touch detected");
foreach (RaycastHit hit in hits) { Debug.Log($"Raycast hit: {hit.transform.name}");
if (hit.transform == transform) { Debug.Log($"Object {hit.transform.name} was touched");