개발/Unity

유니티 AR - 이미지 타겟팅 : 원소를 합쳐서 물 만들기 (AR Chemical Formula For Water in Vuforia)

피로물든딸기 2023. 6. 21. 21:37
반응형

Unity 전체 링크

 

참고

- 유니티 AR 뷰포리아 튜토리얼

- 유니티 프로젝트에 뷰포리아 라이센스 키 적용하기

- 이미지 타겟팅으로 오브젝트 띄우기 From Image

- 이미지 타겟팅으로 오브젝트 띄우기 From DataBase

 

AR 원소 카드를 만들어서 화학식을 만족하면 변환하도록 해보자.


유니티에서 먼저 구현하기

 

위의 결과가 나오도록 먼저 유니티에서 구현해보자.

 

먼저 다음 이미지를 이용하여 쿼드를 아래와 같이 만들자.

 

 

H2O 카드는 O2 보다 살짝 위로 올리고 자식 오브젝트로 설정하고, 숨김 처리한다.

 

유니티에서 제공하는 Sphere를 이용하여 아래와 같이 카드 아래에 원소를 만든다.

 

각 카드에 있는 Mesh Collider를 제거하고, Box Collider를 추가한다.

그리고 Size를 변경하고, 충돌을 하더라도 변화가 없도록 Constrints에 모두 체크한다.

 

자세한 하이어라키나 설정은 아래 패키지를 참고하자.

WaterTest.unitypackage
0.10MB

 

이제 빈 오브젝트를 만들고 TargetManager.cs를 추가한다.

산소 OH가 두 번 부딪히면 물로 변환하도록 하였다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TargetManager : MonoBehaviour
{
    public GameObject H1, H2, Oxygen, H2OCard;
    public int H2OFlag = 0;

    void Update()
    {
        if (H2OFlag == 2)
        {
            H1.SetActive(false);
            H2.SetActive(false);
            Oxygen.SetActive(false);
            H2OCard.SetActive(true);
        }
        else
        {
            H1.SetActive(true);
            H2.SetActive(true);
            Oxygen.SetActive(true);
            H2OCard.SetActive(false);
        }
    }
}

 

TargetManager의 H2OFlag를 변화하는 주체는 수소 원소다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HCollider : MonoBehaviour
{
    TargetManager targetManager;

    void Start()
    {
        targetManager = GameObject.Find("TargetManager").GetComponent<TargetManager>();
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.tag == "Oxygen")
        {
            targetManager.H2OFlag++;
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.collider.tag == "Oxygen")
        {
            targetManager.H2OFlag--;
        }
    }
}

 

따라서 위의 스크립트를 HCard1, 2에 추가한다.

 

산소 카드에는 Tag를 Oxygen으로 변경하였다.

 

이제 게임을 실행시켜서 카드를 움직여보자.

카드가 모이게 되면 물 원소로 변하게 된다.

 

좀 더 자연스럽게 변하게 하기 위해 이동 효과를 추가하자.

먼저 H 오브젝트의 localPosition을 기억해둔다.

    void Start()
    {
        H1Pos = H1.transform.localPosition;
        H2Pos = H2.transform.localPosition;
    }

 

그리고 조건을 만족하면 O 원소로 이동하게끔 만들고, 거리가 좁아지면 H2O 카드로 변경한다.

    if (H2OFlag == 2)
    {
        H1.transform.position
            = Vector3.Lerp(H1.transform.position, Oxygen.transform.position, Time.deltaTime * speed);

        H2.transform.position
            = Vector3.Lerp(H2.transform.position, Oxygen.transform.position, Time.deltaTime * speed);

        if (Vector3.Distance(H1.transform.position, H2.transform.position) < .5f)
        {
            H1.SetActive(false);
            H2.SetActive(false);
            Oxygen.SetActive(false);
            H2OCard.SetActive(true);
        }     
    }

 

조건이 해제되면 원래대로 돌아가도록 저장한 position으로 갱신한다.

    else
    {
        H1.SetActive(true);
        H2.SetActive(true);

        H1.transform.localPosition = H1Pos;
        H2.transform.localPosition = H2Pos;

        Oxygen.SetActive(true);
        H2OCard.SetActive(false);
    }

 

이제 카드가 모이면 원소가 자석처럼 모이고 로 변한다.

 

전체 코드는 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TargetManager : MonoBehaviour
{
    public GameObject H1, H2, Oxygen, H2OCard;
    public int H2OFlag = 0;
    float speed = 1.0f;

    Vector3 H1Pos, H2Pos;

    void Start()
    {
        H1Pos = H1.transform.localPosition;
        H2Pos = H2.transform.localPosition;
    }

    void Update()
    {
        if (H2OFlag == 2)
        {
            H1.transform.position
               = Vector3.Lerp(
                   H1.transform.position, Oxygen.transform.position, Time.deltaTime * speed);

            H2.transform.position
                = Vector3.Lerp(
                    H2.transform.position, Oxygen.transform.position, Time.deltaTime * speed);

            if (Vector3.Distance(H1.transform.position, H2.transform.position) < .5f)
            {
                H1.SetActive(false);
                H2.SetActive(false);
                Oxygen.SetActive(false);
                H2OCard.SetActive(true);
            }     
        }
        else
        {
            H1.SetActive(true);
            H2.SetActive(true);

            H1.transform.localPosition = H1Pos;
            H2.transform.localPosition = H2Pos;

            Oxygen.SetActive(true);
            H2OCard.SetActive(false);
        }
    }
}

 

위의 실행결과는 아래의 unitypackage에서 확인 가능하다.

WaterTest.unitypackage
0.10MB


이미지 타겟팅 만들기

 

아래의 카드를 H1, O, H2로 설정해서 이미지 타겟팅으로 사용한다.

H --- O --- H

 

먼저 ImageTarget 오브젝트를 만들어 위의 이미지를 모두 설정한다.

 

이미지 인식이 잘 되는지 확인하기 위해 아무 오브젝트나 추가해보자.

 

Vuforia Configuration에서 3개의 오브젝트가 인식되도록 Max Simultaneous Track3으로 변경한다.

 

아래와 같이 3개의 이미지에 모두 오브젝트가 나타나면 된다.


이미지 타겟팅 적용하기

 

이제 각각의 카드를 이전에 만든 오브젝트로 등록하면 된다.

TargetManager와 같은 오브젝트도 씬 내에 있으면 AR 카메라와 함께 사용할 수 있다.

즉, 콜라이더 부딪히는 상황을 직접 현실 세계에서 만들어주면 된다.

 

참고로, 설정한 카드의 크기에 따라 코드에서 거리 스피드를 수정해야할 수도 있다. 

if (Vector3.Distance(H1.transform.position, H2.transform.position) < .5f)

 

또한, 게임을 실행하면 그림자가 남아있을 수 있다.

 

Sphere 오브젝트를 찾아서 Mesh Renderer [Lighting]에서 Cast Shadows를 모두 Off로 변경하자.

 

이제 게임을 실행해서 AR로 잘 되는지 확인해보자.

 

반응형