본문 바로가기
게임/Unity

[Unity 3D] 캐릭터 움직임 구현

by 신인용 2019. 11. 23.
반응형

오늘 해 볼 것은 유니티 게임의 기초 중에 기초를 배워보겠습니다.

 

캐릭터의 움직임 

 

 

움직임을 구현하는 방법에는 여러가지가 있는데 차근차근 알아보겠습니다.

 

0. 기본셋팅

기본 셋팅으로 움직일 캐릭터(Sphere)와 땅(Plane),

그리고 캐릭터에는 오브젝트에 물리효과를 입히기 위한 Rigidbody Component를 추가해주고,

움직임을 구현할 소스코드를 작성하기 위한 CharacterMove라는 스크립트를 추가해줍니다.

구별하기 쉽게 Plane에는 초록색을 씌워주고 캐릭터 오브젝트의 이름은 Character라 지어줍니다.

 

 

간단하게 기본 셋팅을 해보았고, 움직임을 구현하는 방법에 대해 알아봅시다.

 

 

 

1. Translate를 이용한 위치 이동

 

말 그대로 상하좌우 키를 눌렀을 때 캐릭터의 위치를 상하좌우로 옮기는 방식입니다.

가장 단순한 방법이죠.

 

(여기서는 Rigidbody Component를 잠시 없애도록 하겠습니다. 물리 구현이 필요없기 때문입니다.)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CharacterMove : MonoBehaviour
{
    public float speed = 5f;
 
    void Update(){
        if (Input.GetKey(KeyCode.LeftArrow)){
            transform.Translate(-speed * Time.deltaTime, 00);
        }
        else if (Input.GetKey(KeyCode.RightArrow)){
            transform.Translate(speed * Time.deltaTime, 00);
        }
        else if (Input.GetKey(KeyCode.UpArrow)){
            transform.Translate(00, speed * Time.deltaTime);
        }
        else if (Input.GetKey(KeyCode.DownArrow)){
            transform.Translate(00-speed * Time.deltaTime);
        }
    }
}
 
cs

Translate를 이용한 상하좌우 움직임.          

* 코드 + *

▶ Translate란?

- Translate(x, y, z): Object를 x,y,z만큼 이동시킨다.

(참고)

 Vector3.right   : Vector3(1,0,0)

 Vector3.up      : Vector3(0,1,0)

 Vector3.forward : Vector3(0,0,1)

 Input.GetKey

- Input.GetKey(KeyCode."입력키"): "입력키"를 누르고 있는 동안

- Input.GetKeyDown(KeyCode."입력키"): "입력키"를 누르는 순간

- Input.GetKeyUp(KeyCode."입력키"): "입력키"를 떼는 순간

 Transform.transform이 아니라 transform ???

- transform은 스크립트가 가리키는(스크립트를 가지고있는) 오브젝트의 transform으로 바로 접근 가능!

▶ Time.deltaTime

- 유니티의 Update함수는 화면이 깜빡일 때마다(프레임 수마다) 작동하도록 되어있습니다.

deltaTime은 일정 프레임(1초당 60번)마다 적용한다고 생각하기.

 

 

 

이렇게 간단하게 움직임을 구현했습니다.

하지만 실제로 구현해보니 너무 딱딱하고 부자연스럽습니다.

캐릭터 구실을 못하죠.

그럼 물리를 이용하여 구현해봅시다.

 

 

 

 

 

2. AddForce를 이용한 물리적인 이동

이제 물리구현을 하는 Rigidbody Component를 이용합니다.

AddForce는 이름 그대로 물체에 힘을 주는 것입니다.

물체에 힘을 줘서 밀리는 것을 이용해서 이동하는 것이죠.

(구가 아닌 다른 모형에게 AddForce하면 쓰러지거나 꿈쩍 안하는 등 원하는 대로 작동을 하지 않을 수도 있습니다.)

 

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CharacterMove : MonoBehaviour
{
    public float speed = 5f;
    private Rigidbody characterRigidbody;
 
    void Start(){
        characterRigidbody = GetComponent<Rigidbody>();
    }
 
    void Update(){
        if (Input.GetKey(KeyCode.LeftArrow)){
            characterRigidbody.AddForce(-speed, 00);
        }
        else if (Input.GetKey(KeyCode.RightArrow)){
           characterRigidbody.AddForce(speed, 00);
        }
        else if (Input.GetKey(KeyCode.UpArrow)){
            characterRigidbody.AddForce(00, speed);
        }
        else if (Input.GetKey(KeyCode.DownArrow)){
            characterRigidbody.AddForce(00-speed);
        }
    }
}
 
cs

AddForce를 이용한 상하좌우 움직임          

* 코드 + *

▶ characterRigidbody = GetComponent<Rigidbody>();

- characterRigidbody라는 변수로 Rigidbody Component를 통제한다는 뜻입니다.

즉, Inspector가 아니라 코드에서도 통제가 가능한 것이죠.

▶ AddForce란?

- AddForce(x, y, z) : Object의 Rigidbody에 (x, y, z)만큼 힘을 추가하는 것입니다.

- 이동이 아니라 "힘을 준다"이기 때문에 관성이 존재합니다.

(참고)

 AddForce(x, y, z, ForceMode.Force) : (질량 적용) 연속적인 힘을 가함

 AddForce(x, y, z, ForceMode.Impulse) : (질량 적용) 순간적인 힘을 가함

 AddForce(x, y, z, ForceMode.Acceleration) : (질량 무시) 연속적인 힘을 가함

 AddForce(x, y, z, ForceMode.VelocityChange) : (질량 무시) 순간적인 힘을 가함

 

 

 

얼음장에서 움직이는 것 같지만,,, 그래도 그나마 자연스럽게 움직입니다.

캐릭터 구실을 조금이나마 하게 되었습니다.

 

 

 

그래도! 아직 부족한 점이 있습니다.

첫째로, 만약 내가 키를 바꾸고 싶다면??? 코드를 일일이 수정해줘야 합니다....

둘째로, X Z 축으로만 움직이는데 굳이 조건을 4개나 설정하는 것입니다.

셋째로, 이 코드는 컴퓨터 외에 다른 기기에선 작동하기 힘듭니다.

 

 

 

 

3. Input Axis를 이용한 움직임

우선, Unity > Edit > Project Setting > Input > Axis를 들어가보면 여러 인풋값이 설정되어 있습니다.

이 중에서 저는 Horizontal과 Vertical을 사용하여 구현하겠습니다.

 

구현하기 전에 Horizontal을 예를 들어 설명하면,

값의 범위가 ( -1 ~ 1 ) 까지인데, Nagative Button인 left키를 누르면 값이 감소하고 반대로 Positive Button인 right키를 누르면 값이 증가합니다. Vertical도 마찬가지입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CharacterMove : MonoBehaviour
{
    public float speed = 5f;
    private Rigidbody characterRigidbody;
 
    void Start(){
        characterRigidbody = GetComponent<Rigidbody>();
    }
 
    void Update(){
        float inputX = Input.GetAxis("Horizontal");
        float inputZ = Input.GetAxis("Vertical");
        // -1 ~ 1
 
        Vector3 velocity = new Vector3(inputX, 0, inputZ);
        velocity *= speed;
        characterRigidbody.velocity = velocity;
    }
}
 
cs

Input Axis를 이용한 움직임

 

* 코드 + *

▶ float inputX = Input.GetAxis("Horizontal");  float inputZ = Input.GetAxis("Vertical");

- inputX와 inputZ 값의 범위는 ( -1 ~ 1 ) 입니다. 이 값을 조절하는 것이 Horizontal과 Vertical에 대응하는 키들입니다. inputX로 좌우를 구현했고, inputZ로 앞뒤를 구현할 수 있었습니다.

▶ characterRigidbody.velocity

- 원래 코드로 구현한다면, inputX와 inputZ를 받은 후에 (16번째 줄 이후)

characterRigidbody.AddForce(inputX*speed, 0, inputZ*speed);

이런 식으로 구현해도 되지만, 이렇게 한다면 힘을 받고 질량, 모양 이러쿵저러쿵 계산해서 velocity라는 변수에 최종속도를 주게 됩니다. 복잡하게 하지말고 바로 velocity에 값을 넣어버려 물리적인 이동을 제외한 것입니다.

(그리고 "힘을 준다"기 보다는 "이동"하는 것이 게임에선 훨씬 자연스럽습니다. 저는 그렇습니다ㅎ)

 

 

Input Axis를 활용하여 자연스럽게 캐릭터를 움직일 수 있게 되었습니다!

캐릭터 구실을 이제 좀 제대로 하네요ㅎㅎ

 

 

 

마지막으로, 이 코드는 y값이 매 프레임마다 0으로 초기화되어 캐릭터가 추락하지 않습니다.

그래서 떨어지는 속도를 따로 저장 후 다시 초기화를 해주는 방식으로 구현하겠습니다.

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CharacterMove : MonoBehaviour
{
    public float speed = 5f;
    private Rigidbody characterRigidbody;
 
    void Start(){
        characterRigidbody = GetComponent<Rigidbody>();
    }
 
    void Update(){
        float inputX = Input.GetAxis("Horizontal");
        float inputZ = Input.GetAxis("Vertical");
        // -1 ~ 1
 
        float fallSpeed = characterRigidbody.velocity.y; // 떨어지는 속도 저장
 
        Vector3 velocity = new Vector3(inputX, 0, inputZ);
        velocity *= speed;
        velocity.y = fallSpeed; // 떨어지는 속도 초기화
        characterRigidbody.velocity = velocity;
    }
}
 
                   추락 추가된 Input Axis를 이용한 움직임

 

 

 

이렇게 최종적으로 자연스러운 캐릭터 움직임을 구현할 수 있게 되었습니다.

 

Input Axis

 

 

 

 

 

반응형

'게임 > Unity' 카테고리의 다른 글

[Unity 이론] Firebase Database  (0) 2019.11.28
[Unity 이론] Object Pooling  (0) 2019.11.26
[Unity 이론] Coroutine  (1) 2019.11.26
[Unity 3D] 충돌 체크  (0) 2019.11.25
[Unity 이론] Time.deltaTime  (0) 2019.11.24

댓글