타이머를 설정하는것은 정말 빈번하게 사용하게됩니다. 그렇기 때문에 좀더 좋은 형태를 가지도록 구현하고자 정리하려고 합니다.

 

Update를 이용한 방법

Private float time = 0f; 
Void Update() 
{ 
    this.time += Time.deltaTime; 
    if(this.time > 5f) 
    { 
        Debug.Log(“Do something!”); 
        this.time = 0; 
    } 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

Time.deltaTime은 지난 프레임이 완료되는게까지 걸린 시간을 말합니다.

저희가 만든 time프로퍼티에 매 프레임마다 더해줌으로써 현재까지 걸린시간을 측정할 수 있습니다.

그 time프로퍼티가 5초를 넘는순간 어떠한 작업을 하고 다시 0초로 초기화해줘서 5초마다 일정한 시간을 가지고 어떠한 반복작업을 하는것이 가능해집니다.

 

이런 식으로 update를 이용하는 방법으로 간단하고 직관적으로 코드를 작성할수있지만 저는 이보다 좀더 복잡한 상황에서 사용하기 좋을수있는 coroutine을 사용해서 구현하고자합니다.

 

타이머 만드는 3개지 방법

검색을 하던 도중 코루틴과 Invoke의 차이점에 대해 묻는 질문을 발견했고, 나는 명확하게 대답하지 못해 해당 지식에 대한 정리를 해두고자 글을 작성한다.

🌐 코루틴

Cooperate(협력하다) 할때 Co와 routine이 합쳐진 Co-routine은 여러개의 루틴이 동시에 실행되게 해주며 멀티쓰레드가 아닌 유니티에서 마치 멀티쓰레드 처럼 보여 병렬적인 구조를 만드는 기능이다.

코루틴을 사용할 때는 Yield return을 해주어야 하는데, 이를 통해서 현재 위치를 기억하고 다른 루틴에게 수행권한을 넘겨주고 다시와서 처리하는 방식이다.

멀티 쓰레드 같지만 단일 쓰레드이기에 Race Condition과 같은 멀티 쓰레드에 문제점을 고민하지 않아도 된다.

💽 코루틴 특징

  • 코루틴은 해당 GameObject가 inactive일때 동작하지 않는다.
  • 정지 된 코루틴은 다시 GameObject가 Active 되더라도 다시 동작하지 않는다.(다시 실행을 시켜주어야한다.)
  • yield return new WaitForSeconds(시간) 이게 너무 편하다.. 함수 중간 중간 쉬었다가 동작 시킬 수 있는데 매우 간편하고, Update를 통해 Timer를 만들어 시간을 재는것 보다 효율적이다.왜 효율적인가?
    5초 뒤 동작을 위해 코드를 구현할 떄 Update에서는 초당 50프레임 정도를 동작하면서 250번을 호출하면서 동작을 하는데, 코루틴은 엔진에게 5초 뒤에 깨우라고 맡기고 쉬다가 동작하니 더 효율적일 수 밖에 없다.

🎇 Invoke

인보크는 코루틴에 비해 비교적 간단하다. 함수를 대신 실행시켜준다. 또한 간단한 방법으로 지연시간 뒤에 함수를 동작하게도 할 수 있다.

Invoke( "함수명"(string) , 지연시간(float));

다만 Invoke는 Reflection을 통해 값을 가져오는데 이 방식이 코루틴 보다는 느리다. 코루틴이 메서드 자체를 인자로 받아가는 것과는 다르게 메서드의 이름을 받아간다.

Reflection
프로그램 실행 도중에 객체의 정보 조사, 다른 모듈에 선언된 인스턴스를 생성, 기존 개체에서 형식을 가져오고 해당하는 메서드를 호출, 접근할 수 있는 강력한 기능
-> 코루틴도 string으로 부를 수 있는데 이때도 리플렉션이 동작되는건가 궁금한데 찾아도 잘 나오지 않는다. 더 공부해보고 추가 글을 남겨야겠다.

👓 인보크 특징

  • Invoke는 GameObject가 비활성화 되더라도 동작을 한다.
  • InvokeRepeating을 통해 지속 반복 동작을 시킬 수 있다.
    -> CancelInvoke, 오브젝트를 파괴하여 종료해주어야 한다.

✅ 차이점

결국은 글에서 언급하면서 나오긴 했지만 다시 정리하자면

  • 코루틴은 GameObject가 활성화 일때만 동작, 인보크는 파괴 전 까지 동작
  • 코루틴은 매개변수 전달 가능, Invoke는 불가능
  • 코루틴은 TimeScale이 0인 경우에도 동작 시킬 수 있다.
    -> yield return new WaitForSecondsRealtime()를 사용
  • 리플렉션의 차이로 코루틴의 속도가 조금 더 빠르다.

공부중인 내용이라 틀릴 수도 있습니다. 추가로 부족한 부분이 있으면 조언 부탁드립니다.

Couroutine을 이용하는 방법

Void Start()
{ 
    StartCoroutine(“timerCoroutine”);
} 

IEnumerator testCoroutine() 
{ 
    While(true) 
    { 
        Debug.Log(“Do something!”); 
        yield return new WaitForSeconts(5f); 
    } 
    yield return null; 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

StartCoroutine()는 파라미터로 주어진 IEnumerator타입의 메소드를 실행시켜주는 역할을합니다.

IEnumerator타입 함수는 yield의 사용을 할수있어서 함수가 호출되고 나서 저희가 함수로 다시 돌아오고 어떻게 동작하는지 확인 할수있게 해줍니다.

 

Yield return new WaitForSecond()은 IEnumerator타입 함수가 재시작 할때까지 얼마나 오랫동안 기다려야하는지를 결정하는 유연성을 제공해줍니다. 파라미터로 원하는 시간을 넘겨주면 그시간동안 다음 동작을 기다립니다. 그후에 더이상의 이함수의 반복이 필요하지않은 부분에서 yield return null로 탈출해주면됩니다.

 

이 코루틴을 이용한 타이머는 타이머가 필요한 동작을 각각 분리하여 구현을 할수있다는것이 장점이 될수있습니다.

 

update로 하기에는 다양한 조건을 검사하거나 동시에 여러개의 타이머가 필요할때는 코루틴을 사용해 구현하는것이 편리할것같다고 생각합니다.

'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글

Unity 타이머  (0) 2024.07.06
7/5 수업  (0) 2024.07.05
7/3 강의 마커기반 AR  (0) 2024.07.03
7/1 FaceTracking2  (1) 2024.07.03
4일차 FaceTracking (6.30 강의)  (0) 2024.06.30

타이머를 설정하는것은 정말 빈번하게 사용하게됩니다. 그렇기 때문에 좀더 좋은 형태를 가지도록 구현하고자 정리하려고 합니다.

 

Update를 이용한 방법

Private float time = 0f; 
Void Update() 
{ 
    this.time += Time.deltaTime; 
    if(this.time > 5f) 
    { 
        Debug.Log(“Do something!”); 
        this.time = 0; 
    } 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

Time.deltaTime은 지난 프레임이 완료되는게까지 걸린 시간을 말합니다.

저희가 만든 time프로퍼티에 매 프레임마다 더해줌으로써 현재까지 걸린시간을 측정할 수 있습니다.

그 time프로퍼티가 5초를 넘는순간 어떠한 작업을 하고 다시 0초로 초기화해줘서 5초마다 일정한 시간을 가지고 어떠한 반복작업을 하는것이 가능해집니다.

 

이런 식으로 update를 이용하는 방법으로 간단하고 직관적으로 코드를 작성할수있지만 저는 이보다 좀더 복잡한 상황에서 사용하기 좋을수있는 coroutine을 사용해서 구현하고자합니다.

 

타이머 만드는 3개지 방법

검색을 하던 도중 코루틴과 Invoke의 차이점에 대해 묻는 질문을 발견했고, 나는 명확하게 대답하지 못해 해당 지식에 대한 정리를 해두고자 글을 작성한다.

🌐 코루틴

Cooperate(협력하다) 할때 Co와 routine이 합쳐진 Co-routine은 여러개의 루틴이 동시에 실행되게 해주며 멀티쓰레드가 아닌 유니티에서 마치 멀티쓰레드 처럼 보여 병렬적인 구조를 만드는 기능이다.

코루틴을 사용할 때는 Yield return을 해주어야 하는데, 이를 통해서 현재 위치를 기억하고 다른 루틴에게 수행권한을 넘겨주고 다시와서 처리하는 방식이다.

멀티 쓰레드 같지만 단일 쓰레드이기에 Race Condition과 같은 멀티 쓰레드에 문제점을 고민하지 않아도 된다.

💽 코루틴 특징

  • 코루틴은 해당 GameObject가 inactive일때 동작하지 않는다.
  • 정지 된 코루틴은 다시 GameObject가 Active 되더라도 다시 동작하지 않는다.(다시 실행을 시켜주어야한다.)
  • yield return new WaitForSeconds(시간) 이게 너무 편하다.. 함수 중간 중간 쉬었다가 동작 시킬 수 있는데 매우 간편하고, Update를 통해 Timer를 만들어 시간을 재는것 보다 효율적이다.왜 효율적인가?
    5초 뒤 동작을 위해 코드를 구현할 떄 Update에서는 초당 50프레임 정도를 동작하면서 250번을 호출하면서 동작을 하는데, 코루틴은 엔진에게 5초 뒤에 깨우라고 맡기고 쉬다가 동작하니 더 효율적일 수 밖에 없다.

🎇 Invoke

인보크는 코루틴에 비해 비교적 간단하다. 함수를 대신 실행시켜준다. 또한 간단한 방법으로 지연시간 뒤에 함수를 동작하게도 할 수 있다.

Invoke( "함수명"(string) , 지연시간(float));

다만 Invoke는 Reflection을 통해 값을 가져오는데 이 방식이 코루틴 보다는 느리다. 코루틴이 메서드 자체를 인자로 받아가는 것과는 다르게 메서드의 이름을 받아간다.

Reflection
프로그램 실행 도중에 객체의 정보 조사, 다른 모듈에 선언된 인스턴스를 생성, 기존 개체에서 형식을 가져오고 해당하는 메서드를 호출, 접근할 수 있는 강력한 기능
-> 코루틴도 string으로 부를 수 있는데 이때도 리플렉션이 동작되는건가 궁금한데 찾아도 잘 나오지 않는다. 더 공부해보고 추가 글을 남겨야겠다.

👓 인보크 특징

  • Invoke는 GameObject가 비활성화 되더라도 동작을 한다.
  • InvokeRepeating을 통해 지속 반복 동작을 시킬 수 있다.
    -> CancelInvoke, 오브젝트를 파괴하여 종료해주어야 한다.

✅ 차이점

결국은 글에서 언급하면서 나오긴 했지만 다시 정리하자면

  • 코루틴은 GameObject가 활성화 일때만 동작, 인보크는 파괴 전 까지 동작
  • 코루틴은 매개변수 전달 가능, Invoke는 불가능
  • 코루틴은 TimeScale이 0인 경우에도 동작 시킬 수 있다.
    -> yield return new WaitForSecondsRealtime()를 사용
  • 리플렉션의 차이로 코루틴의 속도가 조금 더 빠르다.

공부중인 내용이라 틀릴 수도 있습니다. 추가로 부족한 부분이 있으면 조언 부탁드립니다.

Couroutine을 이용하는 방법

Void Start()
{ 
    StartCoroutine(“timerCoroutine”);
} 

IEnumerator testCoroutine() 
{ 
    While(true) 
    { 
        Debug.Log(“Do something!”); 
        yield return new WaitForSeconts(5f); 
    } 
    yield return null; 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

StartCoroutine()는 파라미터로 주어진 IEnumerator타입의 메소드를 실행시켜주는 역할을합니다.

IEnumerator타입 함수는 yield의 사용을 할수있어서 함수가 호출되고 나서 저희가 함수로 다시 돌아오고 어떻게 동작하는지 확인 할수있게 해줍니다.

 

Yield return new WaitForSecond()은 IEnumerator타입 함수가 재시작 할때까지 얼마나 오랫동안 기다려야하는지를 결정하는 유연성을 제공해줍니다. 파라미터로 원하는 시간을 넘겨주면 그시간동안 다음 동작을 기다립니다. 그후에 더이상의 이함수의 반복이 필요하지않은 부분에서 yield return null로 탈출해주면됩니다.

 

이 코루틴을 이용한 타이머는 타이머가 필요한 동작을 각각 분리하여 구현을 할수있다는것이 장점이 될수있습니다.

 

update로 하기에는 다양한 조건을 검사하거나 동시에 여러개의 타이머가 필요할때는 코루틴을 사용해 구현하는것이 편리할것같다고 생각합니다.

'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글

Unity 타이머  (0) 2024.07.08
7/5 수업  (0) 2024.07.05
7/3 강의 마커기반 AR  (0) 2024.07.03
7/1 FaceTracking2  (1) 2024.07.03
4일차 FaceTracking (6.30 강의)  (0) 2024.06.30

BallController Script를 만든다

 

SetBallPosition()이라는 함수를 만든다.

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

public class BallController : MonoBehaviour
{
    Rigidbody rb;  //녹색은 값을 넣어줘야함.
    //공이 준비 상태인지 확인하는 변수
    bool isReady = true;
    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        //리지드 바디의 물리 능력을 비활성화
        rb.isKinematic = true;
     
    }

    // Update is called once per frame
    void Update()
    {
        //공을 카메라 전방 하단에 배치
        SetBallPosition(Camera.main.transform);
    }

    void SetBallPosition(Transform anchor)
    {
        //카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
        // Vector3 = anchor로 부터 앞으로 0.5+ anchor로 부터 아래로 0.2
        Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
        //공의 위치를 offset만큼 이동
        transform.position = anchor.position + offset;
    }
}

Ball에 스크립트를 끌어다 놓고

 

 

공을 발사하고 3초후 공을 다시 만들어 주기위해 타이머를 만들어야 하는데 수업에서는 invoker를 사용하였다.

3초가 지나면 Ball을 Reset()해줘 위치를 초기화 해준다.

void Update()에서 터치후 드래그시 공에 addForce로 공을 약간 위로 나가게 해준다.

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

public class BallController : MonoBehaviour
{
    Rigidbody rb;
    // 공이 준비 상태인지 확인하는 변수
    bool isReady = true;
    // 터치 시작 지점
    Vector2 startPos;
    // 공을 초기화 할 시간
    float resetTime = 3f;
    // 포획 확률
    float captureRate = 0.5f;
    // 포획 결과 텍스트
    public Text result;

    // Start is called before the first frame update
    void Start()
    {
        // 포획 결과 텍스트 초기화
        result.text = "";
        rb = GetComponent<Rigidbody>();
        // 리지드 바디의 물리 능력을 비활성화
        rb.isKinematic = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (!isReady)
        {
            return;
        }
        // 터치가 입력 되었고, 공이 준비 상태라면
        if (Input.touchCount > 0 && isReady)
        {
            Touch touch = Input.GetTouch(0);
            // 만약 터치를 시작했다면
            if (touch.phase == TouchPhase.Began)
            {
                // 시작 지점 저장
                startPos = touch.position;
            }
            // 터치가 끝났다면
            else if (touch.phase == TouchPhase.Ended)
            {
                // 드래그한 y축 거리를 계산
                float dragDistance = touch.position.y - startPos.y;
                // 카메라를 기준으로 45도 각도 계산
                Vector3 throwAngle = (Camera.main.transform.forward
                    + Camera.main.transform.up).normalized;
                // 물리 능력 활성화
                rb.isKinematic = false;
                // 준비 상태 변경
                isReady = false;
                // 던질 방향과 드래그 거리만큼 공에 물리적 힘을 더함
                rb.AddForce(throwAngle * dragDistance * 0.005f, ForceMode.VelocityChange);
                // 3초 뒤에 공의 위치와 속도 초기화
                Invoke("ResetBall", resetTime);
            }
        }

        // 공을 카메라 전방 하단에 배치
        SetBallPosition(Camera.main.transform);
    }

    void SetBallPosition(Transform anchor)
    {
        // 카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
        // Vector3 = anchor로부터 앞으로 0.5 + anchor로부터 아래로 0.2
        Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
        // 공의 위치를 카메라 위치로부터 offset만큼 이동
        transform.position = anchor.position + offset;
    }

    void ResetBall()
    {
        // 물리 능력 비활성화
        rb.isKinematic = true;
        // 속도 초기화
        rb.velocity = Vector3.zero;
        // 준비 상태로 변경
        isReady = true;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (isReady)
        {
            return;
        }
        // 포획 확률을 랜덤한 값으로 설정
        float draw = Random.Range(0, 1f);
        // 만약 랜덤 값이 captureRate 보다 작다면 포획 성공
        if (draw <= captureRate)
        {
            result.text = "포획에 성공했습니다!";
        }
        // 그렇지 않다면 포획 실패
        else
        {
            result.text = "포획에 실패하여 도망쳤습니다.";
        }
        // 마커 오브젝트 제거
        Destroy(collision.gameObject);
        // 공 비활성화
        gameObject.SetActive(false);
    }
}

하이라키+를 눌러 Leagacy Text를 추가해준다.

Canvas Scaler는 Scale with Screen Size로 해주고 해상도는 다음과 같이해준다.

 

BallController.cs
0.00MB

 

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

public class BallController : MonoBehaviour
{
    Rigidbody rb;
    // 공이 준비 상태인지 확인하는 변수
    bool isReady = true;
    // 터치 시작 지점
    Vector2 startPos;
    // 공을 초기화 할 시간
    float resetTime = 3f;
    // 포획 확률
    float captureRate = 0.5f;
    // 포획 결과 텍스트
    public Text result;

    public GameObject effect;
    // Start is called before the first frame update
    void Start()
    {
        // 포획 결과 텍스트 초기화
        result.text = "";
        rb = GetComponent<Rigidbody>();
        // 리지드 바디의 물리 능력을 비활성화
        rb.isKinematic = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (!isReady)
        {
            return;
        }
        // 터치가 입력 되었고, 공이 준비 상태라면
        if (Input.touchCount > 0 && isReady)
        {
            Touch touch = Input.GetTouch(0);
            // 만약 터치를 시작했다면
            if (touch.phase == TouchPhase.Began)
            {
                // 시작 지점 저장
                startPos = touch.position;
            }
            // 터치가 끝났다면
            else if (touch.phase == TouchPhase.Ended)
            {
                // 드래그한 y축 거리를 계산
                float dragDistance = touch.position.y - startPos.y;
                // 카메라를 기준으로 45도 각도 계산
                Vector3 throwAngle = (Camera.main.transform.forward
                    + Camera.main.transform.up).normalized;
                // 물리 능력 활성화
                rb.isKinematic = false;
                // 준비 상태 변경
                isReady = false;
                // 던질 방향과 드래그 거리만큼 공에 물리적 힘을 더함
                rb.AddForce(throwAngle * dragDistance * 0.005f, ForceMode.VelocityChange);
                // 3초 뒤에 공의 위치와 속도 초기화
                Invoke("ResetBall", resetTime);
            }
        }

        // 공을 카메라 전방 하단에 배치
        SetBallPosition(Camera.main.transform);
    }

    void SetBallPosition(Transform anchor)
    {
        // 카메라의 위치로부터 일정 거리만큼 떨어진 위치 설정
        // Vector3 = anchor로부터 앞으로 0.5 + anchor로부터 아래로 0.2
        Vector3 offset = anchor.forward * 0.5f + anchor.up * -0.2f;
        // 공의 위치를 카메라 위치로부터 offset만큼 이동
        transform.position = anchor.position + offset;
    }

    void ResetBall()
    {
        // 물리 능력 비활성화
        rb.isKinematic = true;
        // 속도 초기화
        rb.velocity = Vector3.zero;
        // 준비 상태로 변경
        isReady = true;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (isReady)
        {
            return;
        }
        // 포획 확률을 랜덤한 값으로 설정
        float draw = Random.Range(0, 1f);
        // 만약 랜덤 값이 captureRate 보다 작다면 포획 성공
        if (draw <= captureRate)
        {
            result.text = "포획에 성공했습니다!";
        }
        // 그렇지 않다면 포획 실패
        else
        {
            result.text = "포획에 실패하여 도망쳤습니다.";
        }
        //이펙트생성
        Instantiate(effect, collision.gameObject.transform.position, Camera.main.transform.rotation);
        // 마커 오브젝트 제거
        Destroy(collision.gameObject);
        // 공 비활성화
        gameObject.SetActive(false);
    }
}

Asset Store에서 이펙트를 찾아 다운로드해주고

Import해준다.

스크립트에 effect변수에 import한 이펙트를 끌어다 놔준다. UI LegacyText로 끌어다 놔준다

실행해서 마커를 촬용하면 고양이가 나오고 볼을 드래그해서 맞추면 폭발이 일어나는데 확율에 의해 성공과 실패가 나뉜다. 

실제 해보면 공의 초기 위치와 고양이의 위치가 비슷해 고양이가 공위에 있다. AddForce가 앞으로 날라가기때문에 맞지 않는다. 공위로 고양이가 있을때 억지로 가깝게 해서 맞춰줘야야만 한다. 난 공을 좀더 카메라쪽(-) 고양이를 뒤로 위치시켜 거리를 만들어 공이 앞으로 날라가다 맞게 해주었다

'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글

Unity 타이머  (0) 2024.07.08
Unity 타이머  (0) 2024.07.06
7/3 강의 마커기반 AR  (0) 2024.07.03
7/1 FaceTracking2  (1) 2024.07.03
4일차 FaceTracking (6.30 강의)  (0) 2024.06.30

새로운 씬을 만든다. 씬폴더에서 우클릭 Create Scene 해준다.

PackageManager에서 

AR VR은 Main Camera가 아니라 AR VR전용카메라를 사용한다.

VR은 다른 플러그인 설치가 필요하다 여기서는 안쓴다.

하이라키에서 AR Session Orign을 추가한다 그러면 카메라가 2개니 지우라고 하고 MainCamera를 지운다

하이라키에서 AR Session을 추가한다.

AR Detection은 마커리스 마커 페이스디텍션등이 있다.

MarkerAR 폴더를 만든다.

맨먼저 마커 등록(학습)을 시켜야한다.

MarketAR폴더안에 Create>XR> Image or Object 2가지가 있다.

우선 이미지기반 마커를 만들어보자. XR>Reference Image Library를 선택하자.

마커로 사용되는 이미지는 너무 단순하면 안된다. 복잡할수록 좋다. 다운 받은 그림을 Marker Library 2D 에 끌어다 놓는다.

Add Image를 눌러 3개를 추가했다.

Unity Assets Store Character>Animal>CartoonCat을 가져온다. Unity에서 열기하면PackageManger가 나오는데 다운로드후 Import한다.

Cat_Idle을 끌어다 하이라키에 놓는다.

고양이 애니메이션을 컨트롤 할려면  애니메이터 컨르롤러를 알아야 한다.

현재는 전체 애니메이션이 순환 반복되는데 밥먹는거만 반복되게 해보자 일단 편집을 위해 플레이를 끈다.

 

CatAnim으로 이름 바꾸고 더블클릭

3개의 스테이지가 보이는데 Entry가 시작이다. Exit는 종료 Any State는 모든 스테이트에서 이동이 가능하다.

그래프 우클릭 하고

하이라키 Cat_Idle을 선택하고 Controller 동그라미를 클릭하고 CatAnim으로 바꿔준다.

 

하이라키 Cat을 끌어다 MarketAR폴더에 놓고 프리팹으로 만듬 하이라키 Cat은 삭제

Marke

Cat 프리팹을 끌어 Tracked Image Prefab에 놓는다.

빌드세팅즈 열고 MarketAR 이외는 꺼준다.

빌드앤런 처음 마커로 설정한 뽀로로 위에서만 고양이가 나타난다.

하이라키 MarketCat Delete

 

Rigidbody 컴포넌트 추가

 

Mass: 무게

Drag: 공기저항

Angular Drag:

Use Gravity :

Is Kinematic:체크되면 물리효과 무

Material  폴더를 만들고 Create>Material M_Ball로 이름을 만든다.

'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글

Unity 타이머  (0) 2024.07.06
7/5 수업  (0) 2024.07.05
7/1 FaceTracking2  (1) 2024.07.03
4일차 FaceTracking (6.30 강의)  (0) 2024.06.30
3일차 인디케이터에서 오브젝트 생성및 회전 (6월28일)  (0) 2024.06.28

이전에 마스크를 얼굴에 씌워봤는데 이번에는 동영상을 올려보겠다.

하이라키+를 누르고 CreateEmpty만들고 이름을 FaceModel로 하고 Transform을 리셋한다. 삼점을 누르면 된다.

 

FaceModel을 선택하고 MeshFilter, MeshRendere, MeshCollider, AR Face, AR Mesh Visualizer를 추가한다.

 

얼굴에 덮을 이미지를 적당히 찾는다 png가 좋다.

유니티 Material Folder로 가져온후 인스펙터에서 Transparecy 체크하고 apply

Material을 하나 만들고 M_Face로 하나 만들고 Redering Mode를 Cutout PNG를 Albedo 왼쪽에 끌어다 놓는다.

 

하이라키 FaceModel을 선택하고 머터리얼 M_Face를 끌어다 Materials Element 0 에 넣어준다.

이제 하이라키의 FaceModel을 프로젝트 Prefabs폴더에 끌어다 놓고 프리팹으로 만든다.

만든 프리팹을 하이라키의 AR Session Orign을 선택하고 AR Face Manager컴포넌트의 Face Prefab에 끌어다  적용한다.

하이라키의 FaceModel은 지운다.

빌드앤런 해보면 잘된다. 마스크가 3D로 적용된다 .

첫날은 MyMask라는 빈 오브젝트에 Mask라는 Quad에 M_Mask를 머터리얼로 얹은 2D 평면이었지만 이번에 만든 FaceModel은 3D화 되었다.

 

빈오브젝트에 이것저것 넣어서 만들기 귀찮으면

하이라키에서 우클릭후 AR Default Face를 추가하고 M_Face 머터리얼을 추가해고  AR Face Manager 프리팹에 적용해도 같은 효과가 난다.

 

이제 동영상을 마스크 대신 띄워보자 인터넷에서 영상을 캡쳐해서 머터리얼 폴더로 끌고오자.

하이라키에 CreateEmpty를 만들고 이름을 FaceVideo로 하자

VideoPlayer Component를 추가하고 비디오를 끌어다 Source에 연결해주자 Loop 체크하고 Mute를 체크해서 소리를 꺼준다.

 

프로젝트창 우클릭후 Create>RenderTexture를 만든다. 이름은 FaceVideoRT로 변경하고 이걸 하이라키의 FaceVideo의 TargetTexture에 넣어준다.

프로젝트창에 Create>Material만들고 이름을 M_FaceVideo로 한다. 알베도 왼쪽에 FaceVideoRT를 넣어준다.

 

아까 만든 FaceModel 프리팹을 열어 Matarial에 M_FaceVideo를 연결해준다. 

하이라키의 AR Session Orign>AR Face Manager의 Face Prefab에 Face Model을 연결해주자

정리해보면 M_FaceVideoRT 를 FaceVideoRT>알베도에 놓고 FaceVideoRT 를 M_FaceVideo->Target Texture 에 넣고 M_FaceVideo를 Face Mdel->Material-에 넣고 Face Mode을 AR FaceManager->Face prefab에 넣는다.

빌드런 해보면 잘된다.

 

Cavas 버튼을 2개더 복사해서 좌우로 펼쳐준다

 

버튼을 선택하고 이미지를 지워주자

 

Text를 Image Video로 바꾸고 폰트사이즈를 48로 키워준다.

UI_Manager 스크립트에 머터리얼 행 변수와 SwitchMaterial()함수를 만들어준다

    public Material[] faceMats;

    public void SwitchMaterial(int num)
    {

    }

하이라키의 Canvas를 선택하고 UI Manager(Script)의 Face Mats +를 2번 눌러 Element를 2개 만들고 Material을 2개 연결해준다.

 

2개의 버튼이 함수는 SwitchMaterial로 똑같지만. Button Image OnClick()은 0,ButtonVideo OnClick()은 1로 설정한다.

해본면 안된다. 아직 SwitchMaterial()함수를 정의 안해서 그런것 같다.

눈코입 위치 인식하기

C#스크립트를 만들고 FindDetection 이라고 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARCore;
using Unity.Collections;

public class FindDetection : MonoBehaviour
{
    public ARFaceManager afm; 
    public GameObject cube;  //얼굴에 띄워줄 cubeObject
    List<GameObject> faceCubes = new List<GameObject>();
    ARCoreFaceSubsystem subSys;
    NativeArray<ARCoreFaceRegionData> regionData;
    // Start is called before the first frame update
    void Start()
    {
        //얼굴 위치 표시를 위한 큐브 3개 생성
        for(int i = 0; i < 3; i++)
        {
            GameObject go = Instantiate(cube);
            faceCubes.Add(go);
            go.SetActive(false);
        }
        //얼굴 인식 함수 연결
        afm.facesChanged += OnDetectPoints;  //얼굴이 변화될때 아래 정의된 함수를 델리게이션 추가
        subSys = (ARCoreFaceSubsystem)afm.subsystem; //서브시스템의 정보를 가져와 저장한다.
    }
    //얼굴이 인식될 대마다 실행할 함수
    void OnDetectPoints(ARFacesChangedEventArgs args)
    {
        //얼굴 정보가 갱신된 것이 있다면
        if (args.updated.Count > 0)
        {
            //인식된 얼굴에서 특정 위치를 가져옴
            subSys.GetRegionPoses(args.updated[0].trackableId, Allocator.Persistent, ref regionData);
            //인식된 얼굴을 특정 위치에 오브젝트 배치
            for(int i = 0; i < regionData.Length; i++)
            {
                faceCubes[i].transform.position = regionData[i].pose.position;
                faceCubes[i].transform.rotation = regionData[i].pose.rotation;
                faceCubes[i].SetActive(true);
            }
        }
        //얼굴 정보를 잃었다면
        else if (args.removed.Count > 0)
        {
            //큐브오브젝 비활성화
            for( int i = 0; i< regionData.Length; i++)
            {
                faceCubes[i].SetActive(false);
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

하이라키+를 눌러 빈게임 오브젝트를 만들고 이름을 FaceElements로 한다  FindDetection을 끌어다 놓고 AR Session Origin을 끌어다 afm에 연결해준다.

하이라키+ 3D 오브젝트>Cube를 추가한다. 스케일을 0.02로 한다.

Cube를 프리팹폴더로 옮겨서 프리팹으로 만들고 FaceElements를 선택해서 Cube프리팹을 끌어다 놓는다.

빌드앤런 해보면 잘된 아까 페이스 위에 큐브 3개가 나온다.

3,91f 버전 설치

우리집이 아니라 처음부터 다시해야한다. ㅠㅠ APK도 추가하고 핸드폰 드라이버도 깔아야한다. 기종마다 다르니 메이커에 가서 다운 받아야 한다.

하이라키에 +XR>AR Sesssion 추가

하이라키에 +XR>AR Sesssion Origin 추가  AR Camera를 선택하고 Facing Direction을 User로 한다. 전면카메라는 뜻한다. 참고로 World는 후면카메라

 

하이라키 +XR>AR Default Face 추가

하이라키의 AR Default Face를 끌어다 프리팹으로 만든다. 이름을 MyMask로 한다. 프리팹 폴더를 만들어 넣어도 된다. 프리팹을 만들었으면 하이라키의 AR Default Face는 지우자

히이라키 AR Session Origin에 AR Face Manager 컴포넌트를 추가하자

방금 만든 프리팹 MyMask를 끌어다 놓자

빌드andRun을 눌러보자 빌드하고 실행해보면 전면카메라를 보면 노란 마스크가 보여야한다. 

좀 멋있는 마스크를 적용하기 위해 구글에서 Mask PNG를 이미지로 검색해 투명한 배경이 있는 마스크를 골라 다운로드 한다. 

이걸 Asset폴더에 Material을 만들고 끌어다 놓는다.

Material Folder를 만들고

머터리얼을 하나 Create하고 M_Mask라고 한다.

Inspector Albedo왼쪽에 M_Mask를 끌어다 놓는다. Rendering Mode는 cutout으로 한다.

이제 머터리얼을 만들었으니 이 머터리얼을 오브젝트에 띄워줘야한다.

하이라키에서 3D Object에서 Quad를 추가하고 Mask로 이름 바꾸주고 사이즈를 변경한다.

머터리얼도 적용해준다.

이상태라면 마스크가 얼굴 중앙에 오므로 좀 올려주가 위해 다시 CreateEmpt를 Create하고 MyMask로 이름을 바구고 방금 만든 Mak를 자식으로 끌어다 놓고 위치를 0.025로 올린다.

이제 MyMask를 프리팹으로 만들고 AR Session Origne>AR Face Manager의 FacePrefab을 바꾼다.

빌드하면 얼굴에 가면이 보인다.

이제 UI를 만들어 가면을 껏다 켰다 해보겠다. 하이라키+ UI>Legacy>Button을 선택하면 Cavas의 자식으로 Button이 생긴다.

Cavas를 선택하고 UI Scale Mode를 1080x1920으로 바꾼다.

2D 모드로 바꾼다.

Button을 선택하고  앵커는 아래쪽 중앙 포지션 사이즈를 다음과 같이 바군다.

그럼 버튼이 화면 아래 생긴다.

버튼에 이미지를 입혀주기 위해 Mask PNG를 ctrl-D카피한다 이름을 Mask_Btn으로 바꾼다. Inspector 뷰에서 Text Type을 2D and UI로 바꾼다 Transparency도 체크한다. Apply

하이라키의 Button을 클릭하고 Image를 Mask_btn으로 끌어다 넣어준다. 그럼 UI가 Mask로 바뀐다.

오랜만에 스크립트를 하나 만들고 UI_Manager라고 하자

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARCore;

public class UI_Manager : MonoBehaviour
{
    public ARFaceManager faceManager;

    public void ToggleMask()
    {
        foreach(ARFace face in faceManager.trackables)
        {
            if (face.trackingState == UnityEngine.XR.ARSubsystems.TrackingState.Tracking)
            {
                // face오브젝트 상태를 반대로 변경
                face.gameObject.SetActive(!face.gameObject.activeSelf);
            }
        }
    }
    // Start is called before the first frame update
    void Start(){}

    // Update is called once per frame
    void Update(){ }
}

이제 UI_Manager Script안의 ToggleMask()를 버튼과 연결해야한다.

 그런데 스크립트는 게임오브젝트와 연결이 안되기 때문에 스크립트를 일단 하라라키의 Cavnas아이콘위에 놓으면 자동으로 컴포넌트로 연결한다. 끌어다 놓으면 된다. 

연결후 AR SEssion Origne을 끌어다 FaceManger와 연결해준다.

다음 버튼을 선택하고 OnClick() +를 누르고 Canvas를 끌어다 놓는다. ToggleMask()함수를 선택한다.

마지막으로 가면이 처음에는 안보이게 

MyMask Prefab을 열고 체크박스를 해제하자.

이제 빌드런 해보면 처음에는 마스크가 안 나온지만 밑 버튼을 누르면 나온다.

 

이전 시간에 Animal Asset을 추가했다 Animals_Free 폴더 안에 Prefas가 있고 그중 Penguin_001을 선택해보면

다음과 같이 보이고 편집할수 있다 일단은 안한다.

ObjectManage.cs 스크립트를 열고 다음 코드를 추가한다. 터치가 있다면 model을 인디케이터 위치에 생성한다.

    public GameObject modeling;
    void Update()
    {
        Touch touch = Input.GetTouch(0);
        DetectGround();
        if (touch.phase == TouchPhase.Began)
        {
            Instantiate(modeling, indicator.transform.position, indicator.transform.rotation);
        }
    }

저장후 유니티 에디터에서 public변수 modling에 펭귄 프리팹을 연결해준다.

빌드후 실행해보면 펭귄의 뒷모습이 보여서 돌려주자

프리팹의 RotationY를 돌리면 될것같은데 AR에서는 안된단다.

하이리키+를 누르고 Create>EmptyObject를 만들고 이름을 Penguin으로 하고 자식으로 Penguin_001을 끌어다 놔주고 Rotation과 Scale을 재설정해주자

설정이 끝났으면 Penguin을 끌어다 프리팹에 넣어주고 프리팹을 만든뒤 하이라키의 펭귄은 지워주자

AR Session Origin > Object Manager Modeling의 값을 방금 만든 프리팹을 끌어다 연결해준다.

빌드앤런 해보고 터치하면 펭귄이 앞을 바로 보고 있다 그런데 지금은 터치할때 마다 펭귄이 계속 생기므로 하나만 생기게 해보겠다. ObjectManager CS를 열고 코드를 추가한다 .Instatiate()는 객체참조를 리턴하므로 이걸 저장했다고 null이면 생성하고 아니면 위치를 현재 Indicator로 움직여 보겠다.

//생성된 모델
GameObject placedObject;

    void Update()
{
    Touch touch = Input.GetTouch(0);
    DetectGround();
    if (touch.phase == TouchPhase.Began)
    {
        //만약 생성된 오브젝트가 없다면 모델링 생성및  placedObject변수에 할당
        if(placedObject == null)
        { // 인디케이터 위치에 모델링 생성
            placedObject = Instantiate(modeling, indicator.transform.position, indicator.transform.rotation);
        } else
        {
            placedObject.transform.SetPositionAndRotation(indicator.transform.position, indicator.transform.rotation);
        }
    }
}

빌드런 해보면 이제는 하나만 생긴다. 터치하면 계속 중앙으로 이동한다.

이제는 터치하고 드래그 하면 좌우로 회전하게 만들어 보겠다.

 

스크립터 폴더에 우클릭하고 스크립트를 하나 만들고 이름을 Controller로 한다.

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

public class Controller : MonoBehaviour
{
    Vector2 touchStartPos; //터치 시작 시점
    float rotationSpeed = 0.1f; // 회전속도

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.touchCount == 1)
        {    //인풋의 첫번째 데이터를 가져옴
            Touch touch = Input.GetTouch(0);
            if (touch.phase == TouchPhase.Began)
            {   //터치 시작점을 저장
                touchStartPos = touch.position;
            } else if (touch.phase == TouchPhase.Moved)
            {
                //현재 터치위치 - 시작 터치위치
                Vector2 touchDelta = touch.position - touchStartPos;
                float rotationY = touchDelta.x * rotationSpeed;
                transform.Rotate(transform.up, rotationY, Space.World);
                touchStartPos = touch.position;
            }
        }
    }
}

이 스트립트는 펭귄을 돌리므로 펭귄 프리펜이 넣어준다 자의할점은 펭귄 프리펩의 자식에 넣어주어야 한다  안그러면 안움직인단다.

빌드런 하면 한번 클릭하면 움직이고 누른채로 좌우로 움직이면 펭귄이 좌우로 회전한다.

 

AR Session추가

Hierachy의 +를 눌러 AR Session Origin을 추가한다

Session Origin을 눌러보면 안에 AR카메라가 포함되어 있다. 메인 카메라는 하나만 있으면 되므로 원래잇던 MainCamera는 지워준다.

AR Session, AR Plane Manager 추가

다음은 ARSession을 추가해준다. AR의 생명주기를 담당하는 컴포넌트이다.

 

하이라키에서 AR Session Origin을 선택하고 Add Component를 누르고  AR Plane Manager를 검색해서 넣어준

AR Plane Manager를 평면을 찾아주는 컴포넌트인데 수직, 수평 이나 전부를 선택할수도 있다.

DetectedPlane 만들기

하이라키에서 +를 눌러 CreateEmpty를 만들고 이름을 DectedPlane으로 한다.

Add Component를 눌러 Mesh Renderer, Mesh Filter, Mesh Collider, AR Plane Mesh Visualizer 를 추가한다.

Mesh Renderer : 평면의 메시의 머터리얼및 색상 지정

Mesh Filter : 

Mesh Collider : 이게 없으면 충돌처리가 안되고 RayTraycing도 안된다.

AR Plane Mesh Visualizer : 

AR Plane Mesh Visualizer도 추가한다.  검색된 플레인의 표시방식을 설정한다.  AR Plane AR Mesh Visualizer 2개가 생긴다

Assets 폴더아래 Materials 폴더를 하나 만들자

Material 폴더로 들어가 우클릭해서 Material을 create해주고 이름을 M_Material로 해주자. Inspector에서 Rendering Mode를 Transparent로 변경

Albedo를 눌러 칼라를 적당 Alpha 를 150정도

Assets폴더에 Prefabs폴더를 만들고 들어가서 하이어라키의 DetectedPlane을 끌어다 폴더에 놓는다. 이후 하이라키의 DetectedPlane은 지운다.

이제 프리팹 폴더의 DetectedPlain을 선택하고 Inspector에서 Materials Element0에 아가 만든 머터리얼을 끌어다 놔준다.

하이라키에서 AR Session Origin을 선택하고 AR Plane Manager 컴포넌트의 Plane Prefab에 방금만든 프리팹을 끌어다 놓는다. 그럼 None이 프리팹이름으로 바낀다. 동그라미를 눌러 선택해도 된다.

RayCastManager

 

 

인디케이터 표시하기

평면을 인식했더니 평면을 감지해서 위에 표식을 띄워보자.

AR Session Origin 을 선택후 AR Raycast Manager를 추가하자.

인디케이터로 쓸 투명  PNG를 적당히 찾아 유니티 머터리얼 폴더로 끌어다 놓는다.

인디케이터 파일을 선택하고 Inspectord에서 Transparency를 체크하고 Apply한다.

머티리얼을 새로만들어 M_Indicator로 하고 Rendering Mode를 Cutout로 변경하고 Indicator PNG를 끌어다 albedo 앞 박스에 놓는다. 

하이라키+를 눌러 Quad를 추가하고 indicator로 이름을 바꾼다

씬뷰의 기즈모를 줄이기 위해 뷰포트 우상 기즈모 위 지구본 옆 아래 화살표를 누르면 3D Icons를 줄일수 있다.

하이라키의 Indicator를 고르고 Inspector의 MeshRenderere의 Materials에 M_Indicator를 끌어다 놓는다. 

Position Y를 1로 변경해서 약간 올려준다.

 

Assets폴더밑에 Scripts폴더를 만들고 Script를 만들고 이름을 바로 ObjectManager로 바군다. 클래스명 때문에 그렇다.

만들어진 스크립트를 쳐보면  VisualStudio가 열린다. 안열리면 Edit>Preference를 체크한다.

VisualStudio가 열리면  다음 네임스페이스를 추가한다.

using UnityEngine.XR.ARFoundation;

스크립트를 완성한다.이건 처음 앱리 로딩하면 인디케이터가 사라지게 해준다

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

public class ObjectManager : MonoBehaviour
{
    //변수선언
    public GameObject indicator;
    ARRaycastManager arManager;
    // Start is called before the first frame update
    void Start()
    {
        //AR Raycast Manager 컴포넌트를 가져옴
        arManager = GetComponent<ARRaycastManager>();
        //인디케이터 비활성화
        indicator.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

AR Session Origin을 선택하고 스크립트를 끌어다 추가하고 Indicator변수에 하이라키의 indicator를 끌어다 연결한다.

 

재생버튼을 누르면

Indicator가 사라진다. 다시 재생버튼을 눌러 멈춘면 나타난다. 플레이버튼이 켜진상태에서는 편집변경이 저장 안된다.

다음 스크립터를 추가하면 앱이 Plane을 생성하면 그 위에 인디케이터를 표시해준다

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

public class ObjectManager : MonoBehaviour
{
    //변수선언
    public GameObject indicator;
    ARRaycastManager arManager;
    // Start is called before the first frame update
    void Start()
    {
        //AR Raycast Manager 컴포넌트를 가져옴
        arManager = GetComponent<ARRaycastManager>();
        //인디케이터 비활성화
        indicator.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        DetectGround();
    }
    void DetectGround()
    {
        //스크린 중앙 지점을 찾음
        Vector2 screenSize = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
        List<ARRaycastHit> hitInfos = new List<ARRaycastHit>();
        //만약 스크린 중앙에서 레이를 발사했을 때 평면이 있다면 인디케이터 활성화
        if (arManager.Raycast(screenSize, hitInfos, UnityEngine.XR.ARSubsystems.TrackableType.Planes))
        {
            indicator.SetActive(true);
            //인디케이터의 위치와 회전 값을 레이가 닿은 지점에 일치시킴
            indicator.transform.position = hitInfos[0].pose.position;
            indicator.transform.rotation = hitInfos[0].pose.rotation;
            //위치를 위로 0.1m 옮림
            indicator.transform.position += indicator.transform.up * 0.1f;


        } else
        {
            indicator.SetActive(false);
        }
    }
}



빌드하기

실험을 위해 핸드폰에서 실행하기 위해서는 개발자모드 설정을 해야한다. 설정에서 빌드번호를 검색후 계속 누르면 개발자가 된다. 다시 개발자모드를 검색후  사용, USB디버기을 활성화 해준다.

File>Build Setting에 가서 Add Open Scenes를 클릭해서 현재 씬을 넣어준다 물론 Andrid 가 선택되어져있어야한다.

이후 아래  Build and Run을 누른다 파일명을 물어보면 Build폴더를 만들고 적당히 이름을 지정후 저장한다.

오래걸림

난 Build 는 되는데 Build and Run은 연결을 체크해봐라 문제없다면 드라이브 문제라는 헛소리가 나와서 드라이버를 깔아봤는

https://everyday-devup.tistory.com/90

 

[Unity] Android Debug ( Logcat ) - 안드로이드 디버깅, 개발자 옵션 ( Samsung, LG )

Unity로 안드로이드 게임을 개발할 때, Editor에서는 재현이 되지 않고 디바이스에서만 발생하는 이슈가 있다. 그런 이슈들은 디바이스의 로그를 통해서 이슈가 되는 부분을 찾아야 한다. Editor에서

everyday-devup.tistory.com

드라이버를 깔고 다시 해도 안된다. 그리고 핸드폰을 좀만 만지면 접촉이 안좋와서 그런지 자꾸 연결이 끊어졌고 그런 과정에서 핸드폰을 보니 개발자디버깅을 허용하겠냐는 팝업이 떠서 그걸 체크했더니 Build and run이 실행되었다.

 

터치하면 인디케이터에 오브젝트 표시하기

에셋스토어에서 3D 에셋을 다운로드하다

 

https://assetstore.unity.com/packages/3d/characters/animals/animals-free-260727

 

Animals FREE | 3D 동물 | Unity Asset Store

Elevate your workflow with the Animals FREE asset from ithappy. Find this & other 동물 options on the Unity Asset Store.

assetstore.unity.com

 

하면 PackageManager가 뜨면서 download import 하면 자동으로 폴더가 만들어진다.

 

 

설치

일단 유니티 사이트에서 유니티 허브를 설치

아이디 생성후 로그인후 유니티 에디터를 설치해야함

Archive탭에서 Download archive를 클릭해

21.3.39f1을 설치한다. 강의하시는 선생님이 이버전을 사용해서인데 최신버전을 사용해도 된다.

허브가 자동으로 열린다.

Anidroid Build Support를 체크후 Continue한다 2022가 있는데 2019를 꼭 갈아야하는지는 모르겠다.

비주얼스튜디오도 설치하고

유니티게임개발을 체크해준다.

 

프로젝트만들기

유니티 허브를 열고 프로젝트를 만들자

3D를 선택하고 경로는 한글로만 되어야 한다.

에디터가 열리면 windows 메뉴에서 Package Mannage를 열고 AR은 올인원 패키지라 용량이 크므로 개별로 설치하

밑으로 내려가면  AR Foundation을 선택후 오른쪽 아래 install을 누른다

다음은 구 플래폼을 위해 AR Core를 설치한다. ios라면 다른걸 해야한다.

더움운 발드를 위한 설정을 위해 Fie>Buid Settings로 들어간다. windows에서 Android로 바꾸고 Switch Platform

만일이 모듈이 없으면 설치하라고 나온다 해야함. 잘 설치되면 유니티아이콘이 옆에 보인다.

왼쪽아래 PlayerSettings를 클릭하고

Quality카테고리에서 안드로이드를 Mediaum으로 체크한다. 

Player카테고리의 OtherSetting Color Space를 Gamma에서 Linear로 변

앱의 이름및 버전을 설정할 수도 있다.

밑의 Auto Graphic API를 해제후 Graphics API창이 나타나는데

모바일에서 지원안하는 vulkan을 -를 눌러 지워준다.

조금더 아래 Multithreaded Rendering을 체크해주자

아래 Minimum API Level을 Android 7.0으로 바꾼다. Nuga 

Scripting Backend를 IL2CPP, API Compatibility Level을 .NET Framework로 변경한다.

ARM64 채크

XR Plug-In Management 카테고리로 이동후  ARCore를 체크해주면 된다.

게임부를 Simulator로 변경후 자신의 안드로이드 기종으로 변경한다.

 

https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@5.1/manual/index.html

 

AR Foundation | AR Foundation | 5.1.5

AR Foundation AR Foundation enables you to create multi-platform augmented reality (AR) apps with Unity. In an AR Foundation project, you choose which AR features to enable by adding the corresponding manager components to your scene. When you build and ru

docs.unity3d.com

AR Foundation은 현실오브젝트를 인식하고 기기의 위치를 인식 이미지들을 렌더해서 합성해주는 라이브러리다.

+ Recent posts