99 lines
2.9 KiB
C#
99 lines
2.9 KiB
C#
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.XR.ARFoundation;
|
||
|
|
using UnityEngine.XR.ARSubsystems;
|
||
|
|
using ZXing;
|
||
|
|
|
||
|
|
public class ImageTracker : MonoBehaviour
|
||
|
|
{
|
||
|
|
ARCameraManager cameraManager;
|
||
|
|
|
||
|
|
[SerializeField] List<string> listName;
|
||
|
|
[SerializeField] List<GameObject> listAnimal;
|
||
|
|
[SerializeField] float spawnScale = 0.3f;
|
||
|
|
[SerializeField] float spawnDistance = 1.5f;
|
||
|
|
|
||
|
|
Dictionary<string, GameObject> dictPrefab = new();
|
||
|
|
Dictionary<string, GameObject> dictSpawn = new();
|
||
|
|
|
||
|
|
// 현재 소환된 QR 이름 추적
|
||
|
|
string currentName = "";
|
||
|
|
|
||
|
|
IBarcodeReader reader = new BarcodeReader();
|
||
|
|
|
||
|
|
void Awake()
|
||
|
|
{
|
||
|
|
cameraManager = FindFirstObjectByType<ARCameraManager>();
|
||
|
|
|
||
|
|
for (int i = 0; i < listName.Count; i++)
|
||
|
|
dictPrefab[listName[i]] = listAnimal[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
void OnEnable() => StartCoroutine(ScanQR());
|
||
|
|
void OnDisable() => StopAllCoroutines();
|
||
|
|
|
||
|
|
IEnumerator ScanQR()
|
||
|
|
{
|
||
|
|
while (true)
|
||
|
|
{
|
||
|
|
yield return new WaitForSeconds(0.5f);
|
||
|
|
|
||
|
|
if (!cameraManager.TryAcquireLatestCpuImage(out var cpuImage)) continue;
|
||
|
|
|
||
|
|
using (cpuImage)
|
||
|
|
{
|
||
|
|
var tex = new Texture2D(cpuImage.width, cpuImage.height, TextureFormat.RGBA32, false);
|
||
|
|
var conversionParams = new XRCpuImage.ConversionParams(cpuImage, TextureFormat.RGBA32);
|
||
|
|
var buffer = tex.GetRawTextureData<byte>();
|
||
|
|
cpuImage.Convert(conversionParams, buffer);
|
||
|
|
tex.Apply();
|
||
|
|
|
||
|
|
var result = reader.Decode(tex.GetPixels32(), tex.width, tex.height);
|
||
|
|
Destroy(tex);
|
||
|
|
|
||
|
|
if (result == null) continue;
|
||
|
|
if (!dictPrefab.ContainsKey(result.Text)) continue;
|
||
|
|
|
||
|
|
string detected = result.Text;
|
||
|
|
|
||
|
|
// 같은 QR이면 무시
|
||
|
|
if (detected == currentName) continue;
|
||
|
|
|
||
|
|
SpawnCharacter(detected);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void SpawnCharacter(string name)
|
||
|
|
{
|
||
|
|
// 이전 동물 전부 Destroy
|
||
|
|
foreach (var key in new List<string>(dictSpawn.Keys))
|
||
|
|
DestroyCharacter(key);
|
||
|
|
|
||
|
|
Vector3 spawnPos = GetSpawnPosition();
|
||
|
|
var go = Instantiate(dictPrefab[name], spawnPos, Quaternion.identity);
|
||
|
|
go.transform.localScale = Vector3.one * spawnScale;
|
||
|
|
|
||
|
|
// 카메라를 바라보도록 회전
|
||
|
|
Vector3 lookDir = Camera.main.transform.position - spawnPos;
|
||
|
|
lookDir.y = 0;
|
||
|
|
go.transform.rotation = Quaternion.LookRotation(lookDir);
|
||
|
|
|
||
|
|
dictSpawn[name] = go;
|
||
|
|
currentName = name;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DestroyCharacter(string name)
|
||
|
|
{
|
||
|
|
if (!dictSpawn.ContainsKey(name)) return;
|
||
|
|
Destroy(dictSpawn[name]);
|
||
|
|
dictSpawn.Remove(name);
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector3 GetSpawnPosition()
|
||
|
|
{
|
||
|
|
Transform cam = Camera.main.transform;
|
||
|
|
return cam.position + cam.forward * spawnDistance;
|
||
|
|
}
|
||
|
|
}
|