본문 바로가기

GAME

[Unity]입력처리와 오브젝트 이동

728x90

목표

키보드 마우스로 오브젝트 이동시키기(골드 메탈 - 유니티 기초 B6)

목표지점으로 오브젝트 이동시키기(골드 메탈 - 유니티 기초 B7)

델타타임 (골드 메탈 - 유니티 기초 B8)

 

인풋 값 처리하기

먼저 입력값을 받아주는 함수와 클래스에 대해 알아보자

Input Class : 게임 내 입력을 관리하는 클래스

 

1. 마우스 / 키보드 둘 다 해당하는 입력

anyKeyDown: bool형을 리턴하는 property , 아무 키나 최초로 입력되면 true값을 가진다

anyKey: 아무 키를 "누르는 동안" true값을 가짐

 

Mouse_event라는 스크립트를 생성한 후 

오브젝트를 만들고 스크립트를 적용시킨다

스크립트를 더블 클릭해서 다음과 같이 위에서 나온 property를 사용해보자

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

public class Mouse_event : MonoBehaviour
{

    // Update is called once per frame
    void Update()
    {
        if(Input.anyKeyDown)
            Debug.Log("플레이어가 아무 키를 눌렀습니다.");

        if(Input.anyKey)
            Debug.Log("플레이어가 아무 키를 누르고 있는 중 입니다..");


    }
}

실행 후 "플레이 화면(view)"에 아무 마우스나 클릭 / 키보드 입력해보면 콘솔 창에 실행됨을 확인할 수 있다.

 

 

2. 키보드 입력

키보드 입력에는 3가지가 존재한다 

- 키보드를 누름

- 키보드가 눌린 상태에서 그 상태를 유지하고 있을 때

- 키보드에서 손을 뺏을 때

 

롤로 비유하면 바루스 Q스킬과 같다

Q를 처음 누르면 우리의 바루스가 화살을 든다

Q를 계속 누르고 있으면, 누르는 동안 쏘지 않고 이제 어디로 쏠지 킬각을 잴 수가 있다

그리고 마침내 Q에서 손을 떼면 화살이 날아간다

키보드가 3개의 입력 상태로 나눠져 있기 때문에 가능한 대표적인 스킬이었다

 

3가지를 표현하는 함수를 알아보자

이 3개는 property가 아닌 함수로 매개변수로 KeyCode를 가진다

GetKeyDown(KeyCode. 원하는 키) : 키보드를 누름 

GetKey(KeyCode. 원하는 키) : 키보드가 눌리고 있는 중 

GetKeyUp(KeyCode. 원하는 키) : 키보드에서 손을 땜 

KeyCode는 원하는 키가 무엇인지 불러올 수 있는 클래스이다

원하는 키는 그냥 Q면 Q, 오른쪽 방향키는 RightArrow 이런 식인데

특이하게 Enter키는 Return임에 주의하자 

또 ESC는 Escape이다

바루스 화살의 예를 들어보면 아마

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

public class Mouse_event : MonoBehaviour
{

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Q))
            Debug.Log("바루스 : 화살 장전(?)");

        if(Input.GetKey(KeyCode.Q))
            Debug.Log("바루스 : 화살 조준");

        if(Input.GetKeyUp(KeyCode.Q))
            Debug.Log("바루스 : 화살 발사");
    }
}

 

 

3. 마우스 입력

마우스 입력 또한 키보드 입력과 마찬가지로 3가지 동일한 기능을 한다.

매개변수로 받는 것은 마우스 왼쪽/오른쪽 버튼인데, 숫자로 표현한다
0 : 마우스 왼쪽
1 : 마우스 오른쪽

GetMouseButtonDown(0 or 1) : 마우스를 누름 

GetMouseButton(0 or 1) : 마우스가 눌리고 있는 중 

GetMouseButtonUp(0 or 1) : 마우스에서 손을 땜 

 

단순한 클릭을 하면 미사일을 발사하고, 

오래 모았다가 발사하면 슈퍼 미사일을 발사하는 코드를 짜 보자

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

public class Mouse_event : MonoBehaviour
{

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

        if(Input.GetMouseButtonDown(0))
            Debug.Log("미사일 발사!");

        if(Input.GetMouseButton(0))
            Debug.Log("미사일 모으기");

        if(Input.GetMouseButtonUp(0))
            Debug.Log("슈퍼 미사일 발사 ");
    }
}

 

 

4. 버튼 입력

버튼이 무엇이냐 하면.. 유니티에서 제공하는 더 세밀한 조절이 가능하며, 

이미 대다수에 게임에서 많이들 쓰는 설정으로 얘네들이 지정해놓은 키이다

Edit -> Project Manger에 들어가 보면 

18개가 기본으로 있는 버튼이다 , 기본 설정이 되어있는데 누르면 설정을 변경할 수 있다.

이미 유니티에서 기본 설정값으로 주기 때문에 유니티를 처음 실행하고, 이걸로 코딩해도 잘 움직인다

몇 개만 알아보자

Horizontal 횡이동 키
키보드 <- / -> 
키보드 a/d인 경우도 많다
Vertical 종이동 키
위/아래 방향키 , w/s
Jump 점프키(space)

왼쪽에 쓰인 것이 버튼의 이름인데 버튼의 이름을 사용해서 코딩이 가능하다

GetButtonDown("버튼 이름") : 해당 버튼 이름에 설정되어 있는 키를 누름 


GetMouseButton("버튼 이름") : 해당 버튼 이름에 설정되어 있는 키가 눌리고 있는 중 


GetMouseButtonUp("버튼 이름") : 해당 버튼 이름에 설정되어 있는 키에서 손을 땜 

아래의 예시를 보면 이해가 쉬울 것이다

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

public class Mouse_event : MonoBehaviour
{

    // Update is called once per frame
    void Update()
    {
        if(Input.GetButtonDown("Jump"))
            Debug.Log("점프!");

        if(Input.GetButton("Jump"))
            Debug.Log("점프 모으기");

        if(Input.GetButtonUp("Jump"))
            Debug.Log("슈퍼 점프!! "); 
    }
}

Jump라는 버튼에 설정된 키는 space키다

space키를 각각 누르기/누른 상태 유지/때기 하면 각각의 함수가 실행된다

 

모든 버튼이 초기화된 키가 따로 있으니 클릭해서 확인해보자, 자기가 키를 수정할 수도 있으니 유용하게 사용해 보도록 하자

모바일도 가능하다는 점에서 아주 유용하다

 

또한 18의 크기를 변경하면 내가 원하는 이름을 가진 버튼을 만들어낼 수도 있다

 

 

추가적으로 자주 쓰이는 함수

GetAxis("수평/수직 버튼") : 수평/수직 버튼을 입력받으면 가중치를 부여하여 float값을 반환함 

가속도를 표현하듯이 가중치가 부여되어 출력됨 (오래? 세게? 오른쪽을 누르면 0~1 사이의 값으로 점점 커지게 됨)

GetAxisRaw("수평/수직 버튼") : 수평/수직 버튼을 입력받으면 -1(왼쪽) 1(오른쪽)을 반환함 / 같이 누르면 0 

가중치 X

마찬가지로 Input클래스의 함수이므로 Input.GetAxis("Horizontal/Vertical") 형식으로 사용함 

 

일단 전체 코드를 한번 올려놓고

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

public class Mouse_event : MonoBehaviour
{

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

        //키보드와 마우스 둘다에 해당되는 입력
        if(Input.anyKeyDown)
            Debug.Log("플레이어가 아무 키를 눌렀습니다.");

        if(Input.anyKey)
            Debug.Log("플레이어가 아무 키를 누르고 있는 중 입니다..");


        //키보드입력 3가지 
        if(Input.GetKeyDown(KeyCode.Q))
            Debug.Log("바루스 : 화살 장전(?)");

        if(Input.GetKey(KeyCode.Q))
            Debug.Log("바루스 : 화살 조준");

        if(Input.GetKeyUp(KeyCode.Q))
            Debug.Log("바루스 : 화살 발사");


        //마우스 입력 3가지
        if(Input.GetMouseButtonDown(0))
            Debug.Log("미사일 발사!");

        if(Input.GetMouseButton(0))
            Debug.Log("미사일 모으기");

        if(Input.GetMouseButtonUp(0))
            Debug.Log("슈퍼 미사일 발사 ");


        //버튼입력 
        if(Input.GetButtonDown("Jump"))
            Debug.Log("점프!");

        if(Input.GetButton("Jump"))
            Debug.Log("점프 모으기");

        if(Input.GetButtonUp("Jump"))
            Debug.Log("슈퍼 점프!! "); 



        //유용한 기능
        if(Input.GetButton("Horizontal"))
            Debug.Log("횡 이동 중..."+Input.GetAxis("Horizontal"));


        if(Input.GetButton("Vertical"))
            Debug.Log("횡 이동 중..."+Input.GetAxisRaw("Vertical"));    
       
    }
}

 

오브젝트 이동시키기

이제 오브젝트를 한번 실제로 움직여 보도록 하자

오브젝트 이동을 위해 새로운 C# script를 만들어 주었다

이름은 moving.cs라고 지은 후 

 

Transform : 오브젝트 형태에 대한 기본 컴포넌트 , 위치/회전/크기 등의 내용들을 포함하는데 빈 오브젝트라고 할지라도 트랜스폼은 꼭 필요함, 오브젝트와 1대 1 관계

오브젝트는 항상 Transform클래스로 만든 변수(이름 transform)를 가지고 있기 때문에(이미 초기화되어있음) 따로 선언해주지 않아도 됨

더보기

그러니까 이게 무슨뜻이나면..

아래에서 그림을 보면 오브젝트를 Transform이라는 칸에서 Position/Rotation/Scale을 변경할 수 있는 것을 알 수 있다.

이를 C# script 내에 코드를 통해 position을 변경하여 오브젝트를 이동시키는 게 우리의 목적이다 

그러면 코드로 포지션을 바꾸려면 transform이라는 변수를 통해 조작해야 할 텐데

모든 오브젝트와 트랜스폼은 1대 1이라 이미 내가 그 변수를 생성해주지 않아도

Transform transform이라고 변수가 이미 만들어져 있는 것

아래 코드를 보면 알 수 있을 것이다

Cylinder를 더블클릭하면 오른쪽 상단에 Transform이 있음을 확인할 수 있음

 

골드 메탈님이 변경하셨길래 나도 한번 변경해봄

 

Transform class의 함수

transform.Translate(Vector3/Vector2 변수명) : 해당 오브젝트를 Vector3/2 변수의 크기만큼 이동한다

여기서 잠깐 또 설명해야 할 것은 

2D를 만들고 싶다면, Vector2를 -> 2차원 : x, y좌표상의 벡터 

3D를 만들고 싶다면, Vector3을 사용하는데  -> 3차원 : x, y, z좌표상의 벡터

각각 Vector2/Vector3는 클래스이므로 사용 전에 미리 생성해주면 사용할 수 있다.

 

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

public class moving : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Vector3 vec = new Vector3(3,0,0);

        transform.Translate(Vector3);

    }


실행해주면 지금 x, y, z 가 0.3 1.5 -0.3 상태에서 

생성해준 vec 변수 (3,0,0) 만큼 이동했음을 확인할 수 있다.

 

만약 Update() 함수 안에서 실행한다면 1초에 60번 정도씩 실행되므로 매우 빠르게 x축으로 계속해서 이동할 것이다

-> 결국 카메라 시야를 벗어날 것

 

여기서 팁이 있다면, 보통 게임은 플레이어가 움직이는 대로 카메라도 따라 이동한다

그렇다면 moving.cs코드를 Main Camera오브젝트에도 적용해주면, 실린더 오브젝트가 x축으로 이동할 때 카메라도 동시에 이동하여 

실린더 오브젝트가 시야에서 벗어나지 않게 될 것이다.

 

 

입력값을 이용해 오브젝트 이동시키기

그럼 키보드 조작을 통해 오브젝트를 이동시켜보자

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

public class moving : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //Vector3 vec = new Vector3(3,0,0);
        //transform.Translate(vec);

    }


    void Update(){

        Vector3 vec = new Vector3(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"),0);
        transform.Translate(vec);

    }
}

일단 z축의 값은 0으로 두고

아까 float값을 반환하는 함수를 이용해 방향키를 누르는 대로 오브젝트가 이동하게 만들었다

GetAxis함수를 사용하면 가속도를 표현할 수 있을 것이고,

GetAxisRaw함수를 이용하면 일정 속도로 이동할 것이다

*0.002등을 이용해 속도를 조절할 수도 있을 것이다

 

오브젝트 목표지점으로 이동시키기

Vector3 클래스에 내장된 이동 함수 4가지를 이용해서 서로 다른 이동 방식을 살펴보자

MoveTowards(현재 위치, 목표 위치, 속도 f) : 현재 위치에서 입력 속도에 비례하여로 목표 위치로 이동(일정한 속도)

SmoothDamp(현재 위치, 목표 위치, 참조 속도, 속도 f) :가다가 목표지점에 착륙할 때는 좀 느려지면서 부드러워짐
입력속도에 반비례
하여 속도가 증가함

Lerp(현재 위치, 목표 위치, 속도 f):선형 보간, smoothdamp보다 감속 시간이 길다.
입력속도에 비례하여 속도가 증가함 (최대속도 값 = 1)

Slerp(현재 위치, 목표 위치, 속도 f):구면 선형 보간, 호를 그리며 이동 
입력속도에 비례하여 속도가 증가함 (최대속도 값 = 1)

 

1.MoveTowards

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

public class Move : MonoBehaviour
{
    Vector3 target = new Vector3(8, 1.5f, 0); //이동할 목표지점 

    // Update is called once per frame
    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position,target,1f);
    }
}

 

2. SmoothDamp

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

public class Move : MonoBehaviour
{
    Vector3 target = new Vector3(8, 1.5f, 0); //이동할 목표지점 


    // Update is called once per frame
    void Update()
    {
        //2. SmoothDamp
        Vector3 velo = Vector3.zero; // velo는 0이라고 가정한 속도이며, 참조속도로 사용됨 
                                    //그외에도 Vector3.up (* 목표위치)등이 있는데 참조속도의 위치값으로 smooth하게 이동된다 -> 목표지점의 의미가 퇴색되므로 잘사용하지 않음

        transform.poistion = Vector3.SmoothDamp(transform.position, target, ref velo, 1f);

    }
}

 

3. Lerp

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

public class Move : MonoBehaviour
{
    Vector3 target = new Vector3(8, 1.5f, 0); //이동할 목표지점 

    // Update is called once per frame
    void Update()
    {
        //3. Lerp(선형 보간)
        transform.position = Vector3.Lerp(transform.position,target,1f);


    }
}

 

4.Slerp

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

public class Move : MonoBehaviour
{
    Vector3 target = new Vector3(8, 1.5f, 0); //이동할 목표지점 

    // Update is called once per frame
    void Update()
    {
        //4. Slerp(구면 선형 보간)
        transform.position = Vector3.Slerp(transform.position,target,1f);
    }
}

 

직접 해보면서 이동모습을 보는 게 좋을 것 움짤을 만들긴 귀찮아서..

 

델타 타임

1 프레임에 사용된 시간(이전 프레임의 완료까지 걸린 시간)  

프레임이 몇 개 지나갔나 알고 싶으면 Update함수가 몇 번 실행됐는지 확인하자 

 

더보기

Update함수에 오브젝트를 1 이동시키는 함수를 실행했다

그럼 같은 시간에 10 프레임을 도는 컴퓨터와 60 프레임을 도는 컴퓨터가 같은 온라인 게임상에서 돌아간다고 하면

60 프레임컴퓨터가 60이동할동안 10프레임 컴퓨터는 10을 이동한다

=>??? 게임을 정상적으로 진행 불가 

그때 사용하는 것이 델타 타임이다

60프레임 컴퓨터는 델타 타임이 짧고, 10프레임 컴퓨터는 델타타임이 길 것 

그러니 이동 값에 델타 타임을 곱하면 프레임 수가 크던 작던 나오는 값이 동일해진다

 

TIme.deltaTime 사용방법 

Translate : 벡터에 곱하기

transform.Translate(Vec * Time.deltaTime);


Vector함수 : 시간 매개변수에 곱하기

Vector3.Lerp(Vec1, Vec2, T*Time.deltaTime);

 

키보드 조작으로 오브젝트를 이동시킨 예제에 적용해보자

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

public class moving : MonoBehaviour
{

    void Update(){

        Vector3 vec = new Vector3(Input.GetAxis("Horizontal")*Time.delatTime,Input.GetAxis("Vertical")*Time.delatTime,0);
        transform.Translate(vec);

    }
}

 

 

 

시간있으신 분은 한번 보는 것을 추천드립니다

<참고자료>

youtu.be/wqRwsW03JR4

youtu.be/QGFaA3WYAwk

youtu.be/gnO1GVRuKxk

 

728x90

'GAME' 카테고리의 다른 글

[Unity]기초 3D게임 만들기-1  (4) 2020.07.30
[Unity]UI Setting  (0) 2020.07.17
[Unity]오브젝트 컨트롤  (0) 2020.07.17
[Unity]C#기초와 유니티LIFE CYCLE  (0) 2020.07.10
[Unity]유니티 기초  (0) 2020.07.10