본문 바로가기
Unity/유니티강의1

Unity Chapter 4 - 1. 소코반 게임 만들기 : 초기 씬 구성 + 플레이어 조작

by 싸비비 2022. 5. 17.

인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 

[강의 들으러 가기]


[맵 바닥 색깔 입히기]

1. 맵 바닥 만들기(3d object - plane)

2. Asset 폴더에 Material 생성

- Material 은 물감같은 것이다. 쉐이더와 텍스처가 합쳐진 것.

- Albedo 속성에서 색깔 변경

- smoothness 속성은 표면의 반들거림 정도

3. 만든 Material을 오브젝트에 붙여주면 색이 입혀진다.

 

[플레이어 : 구 만들기]

1. 구 만들기(3d object - sphere)

2. 이름 바꿔주기(player)

3. 위치 설정하기

4. Rigidbody 추가하기

 

[플레이어 : C# 스크립트 작성하기]

- script 파일의 이름은 반드시 대문자!! 로 시작하여야 한다!(클래스는 대문자로 시작하자는 프로그래머들이 한 약속)

- 변수나 함수는 소문자로 시작

- 그 스크립트를 해당 오브젝트에 붙여줘야 한다.

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

public class Player : MonoBehaviour // class명 시작은 대문자!
{
    public float speed = 10f;            // public 으로 해놨기 때문에 인스펙터 창에 슬롯으로 보인다.
    public Rigidbody playerRigidbody;    // public 으로 해놨기 때문에 인스펙터 창에 슬롯으로 보인다. Rigidbody 컴포넌트는 슬롯에 할당해주어야 한다.

    void Start()
    {
        playerRigidbody.AddForce(0, 1000, 0);  // 하늘로 점프했다가 떨어짐.
    }

    void Update()
    {
        
    }
}

[플레이어 조작 스크립트 작성하기]

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

public class Player : MonoBehaviour
{
    public float speed = 10f;
    public Rigidbody playerRigidbody;
    
    void Start()
    {
        
    }

    void Update()
    {
        if(Input.GetKey(KeyCode.W)) 
          playerRigidbody.AddForce(0, 0, speed);  // z축

        if(Input.GetKey(KeyCode.A)) 
          playerRigidbody.AddForce(-speed, 0, 0); // x축

        if(Input.GetKey(KeyCode.S)) 
          playerRigidbody.AddForce(0, 0, -speed); // z축

        if(Input.GetKey(KeyCode.D)) 
          playerRigidbody.AddForce(speed, 0, 0);  // x축
    }
}

[Input]

- UnityEngine 에서 제공하는 입력과 관련된 집합

- 키보드, 모바일, 조이스틱의 입력을 받을 수 있는 여러 함수들의 집합

 

[Input.GetKey()]

- 파라미터 값을 입력 받으면 True를 리턴, 아니면 False를 리턴

 

KeyCode

- 키보드의 각 자판들은 정수와 매칭(ex, W = 119), 그 정수를 일일이 외울 수 없으므로 편하게 쓰려는 목적.

- ex) KeyCode.W

 

단점 : 키보드를 일일이 명시할 필요가 없다, 꼭 방향을 4가지로 나눌 필요가 없다.

 

따라서 사용되는 것

 

[Input.GetAxis]

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

public class Player : MonoBehaviour
{
    public float speed = 10f;
    public Rigidbody playerRigidbody;

    void Start()
    {

    }

    void Update()
    {
        // -1 ~ +1
        float inputX = Input.GetAxis("Horizontal");

        // 발사 기능 - "Fire" - 마우스 오른쪽 버튼
        // 앉는 기능 - "Crunch" - 키보드 C
        // 점프 기능 - "Jump" - 키보드 F

        // "Horizontal" -> 키보드 수평방향에 대응되는 키가 맵핑되있음
        // <- ->


        float inputZ = Input.GetAxis("Vertical");

        playerRigidbody.AddForce(inputX * speed, 0, inputZ * speed);
    }
}

Edit - Project Settings - Input 에 들어가서 인스펙터창에 InputManager를 보면 Axes가 있고 펼치면

할당된 역할을 확인 할 수 있다.

 

[Input.GetAxis("Horizontal")]

여기에 A와 D 가 맵핑 되어있다.

그리고 float 값을 리턴하는데 이유는 조이스틱 입력 때문이다.

 

[관성 없애기]

Rigidbody의 AddForce는 내부적으로 관성, 마찰력 등등 이런것들이 종합적으로 계산되어 작용하게 된다.그래서 관성으로 인해 방향키를 눌렀을 때 살짝 지연이 있은 후, 움직인다.따라서 관성없이 바로 즉시 움직이게 하고싶다면, 힘(addforce) 말고 속도(velocity) 값을 지정해 주면 된다.

playerRigidbody.velocity = new Vector3(inputX, 0, inputZ);

이처럼 velocity는 Vector3를 사용한다.(x, y, z를 가지는 집합)

 

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

public class Player : MonoBehaviour
{
    public float speed = 10f;
    public Rigidbody playerRigidbody;
    
    void Start()
    {
        
    }

    void Update()
    {
        float inputX = Input.GetAxis("Horizontal");

        float inputZ = Input.GetAxis("Vertical");

        Vector3 velocity = new Vector3(inputX, 0, inputZ); 
        velocity = velocity * speed; // 한방에 각 x, y, z 마다 speed를 곱함

        playerRigidbody.velocity = velocity;
    }
}

[문제점]

바닥을 벗어났을때 떨어져야 되는데 바로 떨어지지않는다. 왜??떨어질때 속도가, 입력을 하지않을 때의 속도 0으로 매프레임마다 바뀌기 때문이다.

 

그래서 떨어지는 속도는 유지 시켜주기 위해 다음과 같이 코드를 추가한다.

 void Update()
    {
        float inputX = Input.GetAxis("Horizontal");

        float inputZ = Input.GetAxis("Vertical");

        float fallSpeed = playerRigidbody.velocity.y; //원래 y의 속도를 보존

        Vector3 velocity = new Vector3(inputX, 0, inputZ);  
        velocity = velocity * speed; 

        velocity.y = fallSpeed;

        playerRigidbody.velocity = velocity;
    }

 

[GetComponent()]

유니티 협업할때의 문제점은 public되어 있는 어떤 컴포넌트를 실수로 건드렸다던가, 값을 수정해버리면 게임이 터질 수도 있다. 그래서 슬롯을 열지 않은채 참조를 하려면 어떻게 해야할까??

 

바로 GetComponent<컴포넌트 이름>() 을 사용하면 된다.

<>안에 적혀있는 컴포넌트가 그 오브젝트에 붙어 있는 상태라면 그 컴포넌트를 리턴해준다.

이 방법을 통해 슬롯 없이 코드에서 바로 해당 컴포넌트를 변수에 연결할 수 있다.

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

public class Player : MonoBehaviour
{
    public float speed = 10f; 
    Rigidbody playerRigidbody; // public이 아닌 private 상태(앞에 아무것도 없으면 디폴트로 private)
    
    void Start()
    {
        playerRigidbody = GetComponent<Rigidbody>(); // Rigidbody 컴포넌트가 붙어 있다면 찾아서 리턴
    }

    
    void Update()
    {
        float inputX = Input.GetAxis("Horizontal");

        float inputZ = Input.GetAxis("Vertical");

        float fallSpeed = playerRigidbody.velocity.y; 

        Vector3 velocity = new Vector3(inputX, 0, inputZ);
        velocity = velocity * speed;

        velocity.y = fallSpeed;  

        playerRigidbody.velocity = velocity;   
    }
}

 

댓글