farmer.fbx
0.34MB

위의 fbx 파일은 제가 무료 blender 툴로 직접 제작한 캐릭터입니다.

학습용 도로 사용하도록 합시다.

 

<npc 숨쉬기 애니메이션 넣기>

먼저, 모델을 유니티로 가져온다.

유니티로 가져온 모델을 클릭하면 제일 위에 Model, Rig, Animation, Materials 가있다

애니메이션을 클릭한다. 

캐릭터의 기본 애니메이션이 계속 유지되기 위해 아래의 설정이 필요하다.

 

 

Idle 애니메이션을 Source Take 에서 선택한다. 

그리고 Loop Time을 체크해주면 해당 에니메이션은 무한 반복된다. 

 

모델을 클릭하여

 

해당 에니메이션을 클릭하면

 

 

Loop Time에 체크가 돼있는 것을 확인할 수 있다.

 

애니메이션을 적용하기 위해서 

 

프로젝트 창에서마우스 우클릭 -> Create -> Animator Controller를 클릭하여 애니메이터 컨트롤러를 생성한다.

 

 

애니메이터 컨트롤러를 더블클릭하면 애니메이터 화면이 나타난다.

그 후, 해당 애니메이션을 드래그 엔 드롭하게 되면 위 화면처럼 된다. 

지금 작업한 에니메이터 컨트롤러를 사용하기 위해서

 

우선, 엠티 오브젝트를 생성한다.

그 후 해당 모델을 엠티 오브젝트의 자식으로 한다.

주의사항으로 만약 블렌더 작업하고 모델을 유니티로 가져올 경우

블렌더 모델의 좌표를 0,0,0으로 저장한 후 해당 blender 파일을. fbx로 추출해야 한다.

유니티 게임을 실행시키면 블렌더 작업 당시 캐릭터 위치로 이동하게 된다. 

 

 

 

모델을 클릭한다.

Controller가 None으로 되어 있을 것이다. 우리가 작업해준 애니메이터 컨트롤러를 드래그 엔 드롭해주면 된다.

 

 

npc와 상호작용 하기 위한 캐릭터를 생성한다.

 

<플레이어 컨트롤>

NPC와 상호작용 하기 위해서 플레이어를 만들어 준다.

 

저자는, 캡슐을 생성하여 플레이어로 하였다.

아래의 소스코드는 플레이어의 움직임을 컨트롤하기 위한 소스코드이다.

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Player : MonoBehaviour {
 
    float speed = 10f;
 
    Rigidbody rigidbody;
    Vector3 movement;
    float h, v;
 
    void Start()
    {
        rigidbody = GetComponent<Rigidbody>();
    }
    void Update()
    {
        h = Input.GetAxisRaw("Horizontal");
        v = Input.GetAxisRaw("Vertical");
    }
    void FixedUpdate()
    {
        movement = movement.normalized * speed * Time.deltaTime;
        rigidbody.MovePosition(transform.position + movement);
    }
    
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

 

플레이어를 만들었다면

메인 카메라를 플레이어의 자식 객체로 만든다.

그렇게 되면 플레이어 1인칭을 간단하게 구현할 수 있다.

그다음 카메라의 Transform을 아래와 같이 만든다.

그럼 이제 플레이어의 시각이 적당해진다.

 

 

<npc가 플레이어 바라보게 만들기>

다음으로 npc의 부모 엠티 객체에 Sphere Collider를 아래와 같이 설정한다.

트리거 내부에 플레이어가 감지되면 npc가 플레이어가 바라보도록 

transform.LookAt(target); 을 활용하겠다.

코드는 아래와 같이 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class LookAtPlayer : MonoBehaviour
{
    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "Player")
        {
            transform.LookAt(other.transform);
        }
 
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

위의 코드를 보면 알 수 있지만 플레이어라고 생성한 객체의 Tag를 Player로 설정해주기 바란다.

위의 코드를 npc의 부모 엠티 객체에게 넣어준다.

그러면 이제 npc 주변으로 가면 npc가 플레이어를 바라보게 된다. 

 

 

의도한 것은 아니지만 기분 나쁘게 npc가 바라보는 거 같다.

블렌더에선 밝아 보였지만 유니티로 가져오니 모델이 명암이 더욱 어두워 보인다.

다음부터는 과다하게 밝게 모델링할 필요가 있을 것 같다.

 

<NPC 대화 상자 만들기>

 

이번엔 대화 상자를 만들어 보겠다.

 

히어라키 창에서 패널을 생성한다. 패널은 Create -> UI -> panel이다.

그 후, 같이 생성된 캔버스 통째로 npc 부모 객체의 자식으로 넣어준다.

캔버스의 Render Mode는 World Space로 바꿔준다.

그다음, 중요한 부분인데 scale을   

뒤의 이미지처럼 줄여준다. 이때 width, Height값을 줄이는 식으로 하면

글자가 안 나올 수 도 있으니 주의하도록 한다.

 

 

위의 느낌처럼 UI를 만든다.

 

이제 대화를 진행시키기 위해서 아래 스크립트를 사용한다.

아래 스크립트는 panel에 적용시킨다.

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
[System.Serializable]
public class Dialogue
{
    // 여러줄을 쓸 수 있게 해준다.
    [TextArea]
    public string dialogue;
}
 
public class text_log : MonoBehaviour
{
    static public int npc_talk_int=0;
    Boolean justOne = false;
    public Text txt_Dialogue;
    public Button button_1;
    public Button button_2;
    public Button button_3;
    // [SerializeField] 을 달면 유니티 inspector 창에서 해당 변수를 조작 할 수 있다.
 
    static public bool isDialogue = true;
 
    // 대화가 얼마나 진행 되었는지 확인
    private int count = 0;
 
    static private String[] dialogue; // 대화가 들어가는 배열
 
    private void Awake()
    {
        dialogue = new String[100];
        // 처음 intro 대사
        dialogue[0= "[농부]\n\n안녕하세요 플레이어님 반가워요";
        dialogue[1= "[농부]\n\n날씨가 아주 화창하군요! 감자 심기 좋은날이네요";
        dialogue[2= "[농부]\n\n그럼 지금 감자 심기를 배워 보도록 하겠습니다.";
        dialogue[3= "[농부]\n\n혹시 추가적으로 감자에 관해 알고 싶다면 앞에 저를 레이저 포인터로 클릭 해주세요";
        dialogue[4= "[농부]\n\n레이저 포인터는 뒤로가기 버튼을 클릭하면 켜집니다.";
        dialogue[5= "[농부]\n\n다시 누르면 꺼집니다.";
        dialogue[6= "[농부]\n\n레이저 포인터가 켜져있는 상태로, 리모컨의 큰 원을 클릭하세요 ";
        dialogue[7= "[농부]\n\n그럼 레이저 포인터가 가르키고 있는 대상과 상호 작용 할 수 있게 됩니다.";
        dialogue[8= "[농부]\n\n준비가 되었다면 저에게 알려주세요";
        // 대화 끝에 null을 넣어서 대화가 끝났음을 알린다.
        dialogue[9= "";
        dialogue[10= "end";
        dialogue[12= "[농부]\n\n무었을 도와드릴까요?";
        dialogue[13= "[농부]\n\n무었을 도와드릴까요?";
        dialogue[14= "[농부]\n\n무었을 도와드릴까요?";
 
    }
    private void Start()
    {
        button_1.gameObject.SetActive(false);
        button_2.gameObject.SetActive(false);
        button_3.gameObject.SetActive(false);
 
        ShowDialogue(0);
    }
 
    public void ShowDialogue(int count_)
    {
        count = count_;
        NextDialogue();
    }
    public void talk_npc()
    {
        button_1.gameObject.SetActive(true);
        button_2.gameObject.SetActive(true);
        button_3.gameObject.SetActive(true);
        count =12;
        txt_Dialogue.text = dialogue[count];
    }
 
    private void NextDialogue()
    {
        txt_Dialogue.text = dialogue[count];
        count++;
    }
 
 
 
    void Update()
    {
        if(npc_talk_int == 1&& justOne == false)
        {
            talk_npc();
            justOne = true;
        }
        else if(npc_talk_int == 2)
        {
 
            button_1.gameObject.SetActive(false);
            button_2.gameObject.SetActive(false);
            button_3.gameObject.SetActive(false);
            justOne = false;
        }
        // count 가 12면 선택지 대화 진행중이라 막아 둔다.
        if (isDialogue && count != 12)
        {
            if(dialogue[count].Equals("end"))
            {
                npc_talk_int = 1;
            }
            //if (OVRInput.GetDown(OVRInput.Button.One))
            if (Input.GetKeyDown(KeyCode.G))
            {
                if (count < dialogue.Length)
                    NextDialogue();
            }
        }
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

 

https://youtu.be/sOK_mCxvlSs

 

+ Recent posts