AR동물사전
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class Animal : MonoBehaviour
|
||||
{
|
||||
public LayerMask animalLayer;
|
||||
public AudioSource audioSource;
|
||||
public AudioClip crySound;
|
||||
|
||||
[SerializeField] float rotateSpeed = 0.3f;
|
||||
[SerializeField] float followSpeed = 5f;
|
||||
[SerializeField] float followDistance = 1.5f;
|
||||
|
||||
bool isDragging = false;
|
||||
Vector2 lastTouchPos;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Touchscreen.current == null) return;
|
||||
|
||||
var touch = Touchscreen.current.primaryTouch;
|
||||
|
||||
// 터치 시작
|
||||
if (touch.press.wasPressedThisFrame)
|
||||
{
|
||||
Vector2 touchPos = touch.position.ReadValue();
|
||||
Ray ray = Camera.main.ScreenPointToRay(touchPos);
|
||||
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, animalLayer))
|
||||
{
|
||||
if (hit.transform.IsChildOf(transform))
|
||||
{
|
||||
isDragging = true;
|
||||
lastTouchPos = touchPos;
|
||||
|
||||
if (crySound != null && !audioSource.isPlaying)
|
||||
audioSource.PlayOneShot(crySound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 드래그 중 좌우 회전
|
||||
if (touch.press.isPressed && isDragging)
|
||||
{
|
||||
Vector2 currentPos = touch.position.ReadValue();
|
||||
float deltaX = currentPos.x - lastTouchPos.x;
|
||||
transform.Rotate(Vector3.up, -deltaX * rotateSpeed, Space.World);
|
||||
lastTouchPos = currentPos;
|
||||
}
|
||||
|
||||
// 터치 종료
|
||||
if (touch.press.wasReleasedThisFrame)
|
||||
isDragging = false;
|
||||
|
||||
// 항상 카메라 앞 중앙에 부드럽게 위치
|
||||
Vector3 targetPos = Camera.main.transform.position + Camera.main.transform.forward * followDistance;
|
||||
transform.position = Vector3.Lerp(transform.position, targetPos, followSpeed * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8528256fbd7ee6c419716585ac802388
|
||||
@@ -0,0 +1,99 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16a3e73572be3324d87ca8cba9d7f0db
|
||||
Reference in New Issue
Block a user