반응형

 

2022.0118 - [Unity] - Unity3D - 유니티3D with AdMob 광고의 내용을 진행하다 보면 예상치 못한 에러를 만날 수 있다. 몇 가지 에러를 해결해 보자.

 

Resolving Android Dependencies 과정 중 발생하는 에러

환경 변수에 JAVA_HOME이 등록되지 않아 발생하는 에러다.

 

유니티 설치 폴더에 있는 OpenJDK 경로를 JAVA_HOME 변수로 등록한다.

 

Google.IOSResolver.dll을 로드할 수 없어 발생하는 에러

안드로이드 앱을 개발하기 위해 iOS Build Support를 설치하지 않아 발생하는 에러다.

 

Unity Hub를 실행한다.

 

 

설치되어 있는 Unity 아이콘 오른쪽 점(...)을 클릭하고 Add Modules를 선택한다.

 

iOS Build Support를 선택하고 DONE을 클릭해 설치한다.

 

반응형
Posted by J-sean
:
반응형

 

2021.12.30 - [Unity] - Unity3D - 유니티 3D with OpenCV 1 에서 만든 라이브러리(OpenCVDll.dll)와 

2021.12.29 - [Unity] - Unity3D - 유니티 3D WebCamTexture 라이브 비디오 텍스쳐 의 WebCamTexture를 이용해 라이브 비디오 데이터를 프로세싱하고 오브젝트의 텍스쳐로 사용해 보자.

 

이미지 프로세싱에 사용할 OpenCVDll 라이브러리를 세팅하고 Cube를 생성한다.

 

Cube에 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
using System.Runtime.InteropServices;
 
public class UnityWithOpenCV : MonoBehaviour
{
    [DllImport("OpenCVDll")]
    private static extern void FlipImage(ref Color32[] rawImage, int width, int height);
 
    Renderer renderer;
    WebCamTexture webCamTexture;
    Color32[] image;
 
    // Start is called before the first frame update
    void Start()
    {
        renderer = GetComponent<Renderer>();
        webCamTexture = new WebCamTexture(64048060);
        webCamTexture.Play();
 
        image = new Color32[webCamTexture.width * webCamTexture.height];
    }
 
    // Update is called once per frame
    void Update()
    {
        webCamTexture.GetPixels32(image);
 
        // Image processing
        FlipImage(ref image, webCamTexture.widthwebCamTexture.height);
 
        Texture2D texture2D = new Texture2D(webCamTexture.width, webCamTexture.height);
        texture2D.SetPixels32(image);
        renderer.material.mainTexture = texture2D as Texture;
        (renderer.material.mainTexture as Texture2D).Apply();
    }
}
 

 

Cube에 추가한 스크립트에 코드를 작성하고 저장한다. 모든 프레임에 텍스쳐가 이미지 프로세서(FlipImage())에 의해 상하좌우 반전된다.

 

유니티로 돌아오면 스크립트가 컴파일 된다. 실행 버튼을 클릭하면 매 프레임마다 Cube의 텍스쳐가 상하좌우 반전 처리된다.

 

 

스크립트의 FlipImage()를 주석처리하고 실행하면 원래 이미지의 텍스쳐가 표시된다.

 

프로그램을 실행하는 동안 처리된 이미지가 Inpector창의 Material Preview에도 실시간 적용된다.

 

반응형
Posted by J-sean
:
반응형

카메라 영상을 텍스쳐로 사용해 보자.

 

Cube를 하나 생성한다.

 

스크립트(CamTexture)를 만든다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CamTexture : MonoBehaviour
{
    Renderer renderer;
    WebCamDevice[] webCamDevices;
    WebCamTexture webCamTexture;
 
    // Start is called before the first frame update
    void Start()
    {
        renderer = GetComponent<Renderer>();
 
        // 카메라 조사
        webCamDevices = WebCamTexture.devices;
        for (int i = 0; i < webCamDevices.Length; i++)
        {
            Debug.Log($"{i}) {webCamDevices[i].name}: {(webCamDevices[i].isFrontFacing ? "Front" : "Back")} camera");
        }
 
        // 첫 번째 전면 카메라 선택
        for (int i = 0; i < webCamDevices.Length; i++)
        {
            if (webCamDevices[i].isFrontFacing == true)
            {
                webCamTexture = new WebCamTexture(webCamDevices[i].name);
                break;
            }
        }
 
        // 텍스쳐에 적용
        if (webCamTexture != null)
        {
            webCamTexture.requestedFPS = 60;
            renderer.material.mainTexture = webCamTexture;
            webCamTexture.Play();
        }
 
        // 간단히 하고 싶다면 아래처럼 하면 된다.
        /*
        webCamTexture = new WebCamTexture(640, 480, 60);
        // If no device name is supplied to the constructor or is passed as a null string, the first device found will be used.
        renderer.material.mainTexture = webCamTexture;
        webCamTexture.Play();
        */
    }
 
    // Update is called once per frame
    void Update()
    {
 
    }
 
    private void OnDestroy()
    {
        if (webCamTexture != null)
        {
            webCamTexture.Stop();
            WebCamTexture.Destroy(webCamTexture);
        }
    }
}
 

 

소스를 입력하고 저장한다.

 

실행하면 Cube에 카메라 영상이 재생된다.

 

반응형
Posted by J-sean
:
반응형

3D 모델을 임포트하고 텍스쳐를 적용해 보자.

 

모델과 텍스쳐를 임포트한다.

 

Woman.fbx
2.63MB
WomanSkin.png
0.00MB

 

임포트한 모델을 씬으로 불러와도 텍스쳐가 자동으로 적용되지 않는다. 인스펙터창의 Material은 비활성화 되어 있다.

 

임포트한 모델의 Material에서 Create Material Preset을 클릭한다.

 

모델의 Material과 동일한 Material이 생성된다.

 

 

모델을 선택하고 위에서 생성한 Woman Material을 Drag&Drop한다. 씬에 있는 모델에 직접 Drag&Drop 하거나 인스펙터창 Add Component 버튼 아래에 Drag&Drop한다.

 

Material의 Albedo옆 작은 동그라미를 클릭하고 WomanSkin을 선택한다.

 

텍스쳐가 적용되었다.

 

반응형
Posted by J-sean
:
반응형

모델에 포함된 애니메이션도 인스펙터 창에서 직접 수정 할 수 있다.

 

모델을 임포트한다.

 

Woman.fbx
2.63MB

 

Assets 창에서 모델을 선택하고 인스펙터 창에서 Animation 탭으로 이동한다.

 

Idle 애니메이션을 선택하고 Loop Time을 체크한다. Apply를 클릭한다.

 

Assets창 모델의 애니메이션을 확인하면 Loop Time이 체크 되어있다.

 

 

씬에 모델을 Drag&Drop 한다.

 

애니메이터 컨트롤을 생성한다.

 

생성한 애니메이터 컨트롤을 씬에 있는 모델에 Drag&Drop 한다.

 

애니메이터 창을 확인한다.

 

 

Assets창 모델의 애니메이션(Idle)을 애니메이터창으로 Drag&Drop 한다.

 

플레이하면 Idle상태가 반복된다.

 

다른 애니메이션도 추가해 테스트 해 보자.

 

반응형
Posted by J-sean
:
반응형

캐릭터 모델을 임포트하고 애니메이션(애니메이터)을 사용해 보자.

 

 

Woman.fbx
2.63MB

 

Assets - Model 폴더에 모델을 복사한다.

 

Project 창에서 확인할 수 있다.

 

Animation 폴더를 만든다.

 

 

모델에 포함된 애니메이션을 복사한다(Ctrl+D)

 

Animation 폴더에 넣는다.

 

애니메이션 목록 중 Walking 에는 Loop Time을 체크한다.

 

경고는 신경쓰지 않는다.

 

 

모델을 씬으로 불러온다.

 

애니메이션 목록 중 Idle, Jump, Walking을 모델로 drag&drop 한다.

 

Animator를 확인해 보자.

 

위 그림과 같은 트랜지션을 만든다.

 

 

Walk(Bool), Jump(Trigger) 파라미터를 만든다.

 

Idle -> Walk 트랜지션의 컨디션을 설정한다. (Walk -> true, Has Exit Time 체크 해제)

 

Walk -> Idle 트랜지션의 컨디션을 설정한다. (Walk -> false, Has Exit Time 체크 해제)

 

Any State -> Jump 트랜지션의 컨디션을 설정한다. (Jump, Has Exit Time 체크 해제)

 

 

컨트롤러 스크립트를 만든다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Controller : MonoBehaviour
{
    private Animator animator;
 
    // Start is called before the first frame update
    void Start()
    {
        animator = GetComponent<Animator>();
    }
 
    // Update is called once per frame
    void Update()
    {
        float xInput = Input.GetAxis("Horizontal");
        float zInput = Input.GetAxis("Vertical");
 
        if (xInput != 0 || zInput != 0)
        {
            animator.SetBool("Walk"true);
        }
        else
        {
            animator.SetBool("Walk"false);
        }
 
        if (Input.GetKeyDown(KeyCode.Space))
        {
            animator.SetTrigger("Jump");
        }
    }
}
 

스크립트를 작성한다.

 

컨트롤러 스크립트를 모델에 넣는다.

 

이 상태에서 실행해 보면 Idle, Walk는 생각대로 작동하지만 Jump 후 다시 Idle이나 Walk로 돌아가지 못한다.

Jump 후 다른 애니메이션으로 가는 트랜지션이 없기 때문이다.

 

Jump -> Idle 트랜지션을 만들고 Has Exit Time을 체크한다. (컨디션은 설정하지 않는다)

 

 

다시 실행해 보자.

 

반응형
Posted by J-sean
:
반응형

하나의 객체만 존재해야 하는 싱글턴 패턴 게임 매니저 예제.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
using UnityEngine.SceneManagement;
using UnityEngine.UI;
 
public class GameManager : MonoBehaviour
{
    public static GameManager instance;
 
    public bool isGameover = false;
    private Text scoreText; // Awake()에서 대입.
    public Text gameoverText;   // Editor - Inspector에서 대입. 시작할 때 비활성화 된
                                // 오브젝트이기 때문에 GameObject.Find()로 찾을 수 없다.
                                // 자식 오브젝트를 찾는 방식으로만 찾을 수 있다.
    
    public int marbleCount; // 마블 생성기에서 초기화.
 
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
 
            scoreText = GameObject.Find("ScoreText").GetComponent<Text>();
        }
        else
        {
            Debug.LogWarning("Game manager exists already.");
            Destroy(gameObject);
        }
    }
 
    // Update is called once per frame
    void Update()
    {
        if (!isGameover)
        {
            if (marbleCount <= 0)
            {
                isGameover = true;
                gameoverText.gameObject.SetActive(true);
            }
 
            scoreText.text = marbleCount + " marbles to go!!";            
        }
        else
        {
            if (Input.GetKeyDown(KeyCode.N))
            {
                isGameover = false;
                gameoverText.gameObject.SetActive(false);
                SceneManager.LoadScene(SceneManager.GetActiveScene().name);                
            }
        }
    }
}
cs

 

다른 스크립트에서 GameManager.instance.XXX 와 같은 방식으로 사용한다.

 

반응형
Posted by J-sean
:
반응형

씬에 있는 비활성화된 오브젝트는 FindXXX()로 직접 찾을 수 없다. 하지만 부모 오브젝트가 있는 자식 오브젝트라면 부모 오브젝트를 먼저 찾고 transform 컴포넌트의 Find(), GetChild() 등으로 찾을 수 있다.

 

부모 오브젝트(Parent) 아래에 자식 오브젝트(1st, 2nd)를 만든다.

 

자식 오브젝트(1st, 2nd)는 비활성화 시킨다.

 

적당한 스크립트에 비활성화된 자식 오브젝트를 찾는 코드를 입력한다.

 

찾은 자식 오브젝트의 이름이 출력된다.

 

반응형
Posted by J-sean
: