유니티 유닛

만들 것

간단하게 땅을 만들고, 발사대를 만들고, 로켓과 발사대에 올라갈 착륙대를 만든다.

- 기능의 세부적인 것에 너무 많은 시간을 투자하기 전에 우선 작동하도록 만든다.

 

유니티 월드 좌표축

유니티 씬 화면의 우측 상단에 월드 좌표축이 있다.

좌표축

유니티는 1유닛을 기본 단위로 사용하는데 1유닛당 편의상 미터로 생각해도 된다. ex) 단위를 맞춰줘서 현실과 크기 비교 가능

아래는 스케일이 x,y,z로 각 1유닛씩인 트랜스폼이다. ex) 플레이어 크기가 2유닛이면 2m쯤 된다고 생각

유닛

스케일을 증가시킬 때 축의 양의 방향과 음의 방향으로 나누어 같이 증가하기 때문에 이에 대응해 이동한다면 증가한 스케일 축으로 증가한 반절 값만큼 이동하면 된다.

스케일 변화 후 이동

오브젝트 프리펩화

오브젝트 프리펩화

게임 디자인

플레이어 경험

정밀함, 기술적

핵심 매커닉

- 우주선을 능숙하게 조종해 주변의 자연 위험요소를 피하는 것

게임 루프

- 특정 레벨을 완료하려면 A에서 B로 가야하고 다음 레벨로 넘어감

- 마지막 레벨을 클리어하면 다시 처음 레벨로 돌아감

게임 테마

: 비주얼, 게임의 느낌을 이야기함

- 플레이어는 실험적인, 이전 시대의 초기 우주선임

- 모르는 행성에서 탈출하는 것

필수 요소

- 좌우 움직임

- 부스트 (중력 반대 방향)

- 움직이는 물체(장애물)

- 출발지, 도착지

 

 

양파 디자인

게임에서 가장 중요한 요소를 정하는 것 = 반드시 있어야 하는, 없이는 게임을 만들 수 없는 것이 무엇인지 보기

- 1순위 2순위 3순위 ... 가 양파처럼 층층이 쌓임

- 시간이 없으면 제일 중요한 필수적인 요소들을 만들고 멈춤

- 다음 요소를 추가해야 할지 고민할 때 그것이 핵심요소를 더 좋게 만드는지 생각해보고 결정

ex)

1순위 : 우주선 이동

2순위 : 장애물(충돌)

3순위 : 출발지, 도착지 (레벨 진행)

 

추가 요소 예시

- 연료 추가

- 총 발사

- 파워 업

 

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 부스트 프로젝트' 카테고리의 다른 글

소스 컨트롤  (0) 2022.08.12
오브젝트 회전과 매개변수와 Rigidbody  (0) 2022.08.04
부스터  (0) 2022.08.03
클래스, Input 클래스  (0) 2022.08.03
유니티 유닛  (0) 2022.08.03

Transform

트랜스폼 클래스에는 객체를 변형할 수 있는 프로퍼티들과 함수들이 들어있다.

회전하는 객체를 만들어 보자

Transform.Rotation();

Spinner.cs

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

public class Spinner : MonoBehaviour
{
    [SerializeField]
    private float xAngle;
    [SerializeField]
    private float yAngle;
    [SerializeField]
    private float zAngle;

    void Update()
    {
        // 프레임마다 x,y,z각도에 각 변수씩 더해진다.
        transform.Rotate(xAngle, yAngle, zAngle);
    }
}

transform.Rotation

추가로 오브젝트가 밀리는 경우가 좀 있는데 Collider를 사용할 때 위치 이동으로 충돌이 이루어져서 그렇다. 이러한 물리 작용을 할 때는 AddForce로 하는 방법이 있다.

 

 

Prefab

오브젝트를 프리펩화시키면 복제, 다른 씬에서의 사용 등 여러가지 좋은 점이 많다.

Prefabs

 

장애물 코스 만들기

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

Tag  (0) 2022.08.02
Score, Time.time, If, Rigidbody  (0) 2022.08.02
OnCollisionEnter(), GetComponent<>()  (0) 2022.08.02
메서드  (0) 2022.08.02
Collision  (0) 2022.07.28

Tag

게임 오브젝트에 태그를 넣어 관리할 수 있다.

- 태그로 검사 가능

Tag

 

목표

1. ObjectHit 스크립트에서 태그로 충돌을 검사하여 Player일 때 색을 변경하고 자신의 Tag를 Hit으로 변경하기

2. Scorer 스크립트에서 태그로 충돌을 검사하여 Hit인지 검사하고 Hit이 아니면 점수를 올리기

ObjectHit.cs

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

public class ObjectHit : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision)
    {
        // 충돌한 객체의 게임 오브젝트의 태그가 Player이면
        if (collision.gameObject.tag == "Player")
        {
            GetComponent<MeshRenderer>().material.color = new Color(1, 0, 0, 1); // red
            // ObjectHit이 있는 해당 오브젝트의 tag를 Hit으로 변경함
            gameObject.tag = "Hit";
        }
    }
}

Scorer.cs

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

public class Scorer : MonoBehaviour
{
    // 점수를 담을 변수
    int hits = 0;

    private void OnCollisionEnter(Collision collision)
    {
        // 충돌한 객체의 태그가 Hit이면(이미 충돌한 객체이면) 스킵
        // if (collision.gameObject.tag != "Hit")과 반대
        if (collision.gameObject.tag == "Hit")
            return;
        
        hits++;

        // 문자열 + 변수이름 하면 붙어서 출력 (문자열변수 이런 식) 
        Debug.Log($"You've bumped into a thing this many times: " + hits); 
    }
}

Tag로 검사

Score

Scorer.cs

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

public class Scorer : MonoBehaviour
{
    // 점수를 담을 변수
    int hits = 0;

    private void OnCollisionEnter(Collision collision)
    {
        // hits가 hits에 1을 더한 값
        // hits = hits + 1;와 동치
        hits++;

        // 문자열 + 변수이름 하면 붙어서 출력 (문자열변수 이런 식) 
        Debug.Log($"You've bumped into a thing this many times: " + hits); 
    }
}

Score

 

 

문제과 해결방안

해결할 문제 : 개체가 3초 정도 이후에 떨어지게 만드는 것

해결책 :

1. 타이머 - Time.time

2. 3초가 지나면 무엇인가를 하는 메커니즘 - if문

3. 개체를 3초 이후에 떨어지게 하는 방법 - disable / enable gravity (3초 이후에 중력 활성화)

 

 

Time.time

게임이 시작하고 난 이후부터 소요된 초 단위의 시간

- Time클래스의 프로퍼티 중 하나

- 읽기전용(접근은 가능해도 변경할 수 없음)

 

Dropper.cs

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

public class Dropper : MonoBehaviour
{
    void Start()
    {
        
    }

    void Update()
    {
        Debug.Log(Time.time);   
    }
}

Debug Time.time

 

 

If

Dropper.cs

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

public class Dropper : MonoBehaviour
{
    [SerializeField]
    private float seconds;
    void Start()
    {
        // bool 값이 true(참)이면 if문 코드 실행 아니면 스킵
        /*if (bool 값)
        {
            무언가를 하시오
        }*/
    }

    void Update()
    {
        // 조건
        if (Time.time > seconds)
        {
            Debug.Log($"{seconds} seconds has left");
        }
    }

    
}

if문과 Serialized 변수

 

 

Rigidbody

Rigidbody컴포넌트의 Use Gravity는 키면 중력을 허용하고 끄면 중력을 허용하지 않는다.

- MeshRenderer컴포넌트처럼 껐다가 킬 수 있음 => 둘 다 꺼서 떨어지기 전엔 안 보이도록 함

Rigidbody

 

캐싱

자주 사용되는 데이터나 정보를 필요할 때 쉽게 접근할 수 있도록 메모리에 저장하는 기술

캐싱

 

Dropper.cs

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

public class Dropper : MonoBehaviour
{
    // Meshrenderer형을 담는 renderer
    MeshRenderer renderer;
    Rigidbody rigid;

    [SerializeField]
    private float seconds;
    void Start()
    {
        // GetComponent<MeshRenderer>().enabled = false;
        // 캐싱
        renderer = GetComponent<MeshRenderer>();
        renderer.enabled = false;

        rigid = GetComponent<Rigidbody>();
        rigid.useGravity = false;
    }

    void Update()
    {
        // 조건
        if (Time.time > seconds)
        {
            Debug.Log($"{seconds} seconds has left");
            renderer.enabled = true;
            rigid.useGravity = true;
        }
    }

    
}

캐싱

 

Directional light

- 위치는 상관 없고 회전이 그림자에 관련 있음

Directional Light

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

회전하는 객체, Prefab, 장애물 코스 만들기  (0) 2022.08.02
Tag  (0) 2022.08.02
OnCollisionEnter(), GetComponent<>()  (0) 2022.08.02
메서드  (0) 2022.08.02
Collision  (0) 2022.07.28

ObjectHit.cs

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

public class ObjectHit : MonoBehaviour
{
    // private은 이 함수가 이 클래스 내에서만 접근할 수 있다는 말임
    // Collision은 부딪힌 대상에 대한 정보가 들어있음
    // 들어왔을 때 충돌을 감지함 (들어올 시점에 1번) - 떨어졌다 다시 부딪치면 다시 감지
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("Bumped into a wall");
        // GetComponent메서드
        GetComponent<MeshRenderer>().material.color = new Color(1, 0, 0, 1); // red
    }
}

Collision, GetComponent

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

Tag  (0) 2022.08.02
Score, Time.time, If, Rigidbody  (0) 2022.08.02
메서드  (0) 2022.08.02
Collision  (0) 2022.07.28
Cinemachine  (0) 2022.07.28

메서드 이론

함수로 불리기도 하며 게임에서 작은 특정한 것을 하도록 만드는 코드의 블록을 실행하는 것이다.

 

수행해야하는 것

1. 메서드를 선언하고 정의한다. (이것을 하는 거야) ex) CleanYourRoom // 옷 정리하기, 쓰레기 버리기

2. 메서드를 실행하고 싶을 때 불러와야 한다. (이제 가서 실행해)

1. 메서드 선언

 

1. 반환을 요청 가능(반환 값이 있을 시 중괄호 내에 return 반환형 값; 필수)

2. 메서드를 불러올 때 필요한 매개변수를 설정할 수 있음(매개변수 있을 시 앞에 타입을 적어줌)

선언 - 메서드 선언 코드 내부에 ';' 있음

/*반환형 함수이름(파라미터)
    {
        ~해라;
    }*/
void Clean Your Room(int deadline) 
{
	// ~해라; 
}

// 반환 유형은 불려진 곳으로 돌아가고 매개변수는 불린 곳에서 인자를 받아옴
bool CleanYourRoom(int time)
{
	return false; // 반환 키워드(반환 타입이 bool타입 일 때)
}

2. 메서드 호출

호출 - 메서드 이름 뒤에 ';' 있음

// 함수명(매개변수 있을 시 값만 써줌);

CleanYourRoom();

 

그럼 Start()와 Update()는?!

유니티 내부 로직이 적절한 시기에 대신 호출해줌

Start() - Play버튼 누를 때

Update() - Start() 후 매 프레임마다 실행 됨

 

 

메서드 실습

Mover.cs

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

public class Mover : MonoBehaviour
{
    [SerializeField]
    float moveSpeed;
    void Start()
    {
        // 함수로 실행하면 가독성이 좋음
        // 문제가 생기면 작성했던 곳에서 수정하면 됨
        // 여러 곳에서 반복해서 사용할 수 있음
        PrintInstruction();
    }

    void Update()
    {
        MovePlayer();
    }

    // 반환 값 없고 매개변수 값 없음
    void PrintInstruction()
    {
        Debug.Log("welcome to the game");
        Debug.Log("Press arrow keys to move");
        Debug.Log("avoid walls");
    }

    void MovePlayer()
    {
        float xValue = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
        float zValue = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
        transform.Translate(xValue, 0f, zValue);
    }
}

Method

 

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

Score, Time.time, If, Rigidbody  (0) 2022.08.02
OnCollisionEnter(), GetComponent<>()  (0) 2022.08.02
Collision  (0) 2022.07.28
Cinemachine  (0) 2022.07.28
Time.deltaTime  (0) 2022.07.27

배운 것들

유니티 생애주기

이벤트 함수의 실행 순서(Unity Docs)

유니티 LifeCycle

 

싱글톤과 옵저버 패턴

싱글톤 패턴

 

UI

유니티 내장 UI

유니티 내장 UI

Rect transform

Rect transform

TextMesh Pro

TextMesh Pro

멀티 캔버스와 Extension

UI Extension 링크

Multi Canvas / Extension

 

 

실습 과제

싱글톤 패턴 구현하기

싱글톤과 옵저버

 

UI 포트리스 게임 만들기(진행중)

UI 포트리스

 

 

한 주 후기

 이번 주에는 유니티 생애주기, 싱글톤 패턴과 옵저버 패턴, UI에 대해서 배웠다. 유니티 생애주기가 왜 이런 순서로 되어있고 프로그래밍을 할 때 이 생애주기를 참고하면 된다고 배웠다. 싱글톤 패턴은 게임 매니저와 같이 객체들을 관리하는 객체를 따로 두어 유일한 객체로 만들고 이 객체에 대한 접근은 어디서든 할 수 있게 하는 패턴이다. 옵저버 패턴은 subject가 object가 하는 일들을 대신 호출해주고 object는 subject로만 함수를 실행하게 되는 패턴이다. 옵저버 패턴은 싱글톤 패턴과 자주 혼용되어 사용된다고 배웠다. UI는 팝업 창, 버튼 등등 유저가 상호작용할 수 있는 것들인데 유니티의 내장 UI와 TextMesh Pro, Extension UI도 설치해 사용해 보는 시간을 가졌다.

 이번 주에 배우면서 느낀 점은 UI요소들이 너무 많다는 점이었다. UI를 배우는 것 자체가 코드 보다는 일단 다 씬에 배치해보고 어떤 기능인지 아는 게 중요한데 수가 많다보니까 시간이 조금 더 걸린 것 같았다. 또 Rect transform 개념이 이해하기 쉽지 않았는데 앵커에서 축끼리 min과 max가 같으면 포인트가 되고 너비를 줄 수 있고, min max가 다르면 범위가 되어 마진 값을 줄 수 있다고 생각하니까 이해가 되었다. pivot 부분도 헷갈렸는데 pivot은 좌측 아래부터 x와 y값이 있는 로컬 기준점이라고 생각하니 이해가 되었다.

 이번 주에 배운 UI들은 많기도 하고 내가 모르는 부분이 더 많은 느낌이었다. 되게 간단한 버튼 UI나 Text UI만 다룰 수 있었는데 다른 여러가지 UI들도 계속 사용해봐야지 용도를 이해할 수 있는 것들이기에 앞으로 계속 써봐야겠다는 생각이 들었다. 이번에 과제를 할 때도 기본 과제와 심화과제의 UI를 다른 방식으로 사용해서 제출하는 것을 목표로 하고 있는데 이것으로 UI 적용 부분에서 다른 상황에도 적용할 수 있는 유연성을 가졌으면 좋겠다.

 UI까지 배우면서 이렇게 계속 진행하면 뭔가 만들 수 있을 것 같다는 생각이 들었다. 내가 성장하는 느낌이 들고 이게 많은 양의 지식을 습득하는 데 긍정적인 영향을 주는 것 같아서 기분이 좋았다. 기본 과제부터 심화 과제까지 정복하여 잘해지고 싶은 마음 뿐이다. 다음 주도 화이팅 하자!

 

 

유데미코리아 바로가기

본 포스팅은 유데미-웅진씽크빅 취업 부트캠프 유니티 1기 과정 후기로 작성되었습니다.

Collider

플레이어가 부딪히거나 통과하지 못하는 투명한 결계 ex) 맵 끝 밖으로 가지 못하게 막는 투명한 벽

Cube 오브젝트로 플레이어나 Wall을 생성했기 때문에 컴포넌트로 박스 콜라이더가 들어있다.

- Box Collider의 Size로 콜라이더의 크기를 조절할 수 있다.

- Box Collider의 Center로 콜라이더의 중심 위치를 조절할 수 있다.

Box Collider

* 초록색 부분이 Collider이다.

Collider

Collider가 컴포넌트에 없다면 Inspector창의 AddComponent - Box Collider로 추가하면 된다.

* 상황에 맞는 콜라이더를 넣으면 됨 - 대부분의 경우는 개체의 크기와 맞게

Colliders

 

 Rigidbody

개체에 질량을 부여하여 물리 시스템에게 물리를 사용해서 개체의 반응을 일으키게 함

- 플레이어를 움직여도 벽과의 충돌이 안 이루어지는데 이 때 최소 둘 중 한 오브젝트에 Rigidbody 컴포넌트가 존재해야 충돌이 이루어진다.

- Use Gravity : 중력 사용 

벽과의 여러 번 충돌 이후 움직임에 버그가 생겼다.

fly

이 문제를 해결하려면 Inspector창 - Rigidbody - Constraints - Freeze Rotation과 Freeze Position을 조정해서 해결할 수 있다.

* 여기선 각 축의 회전과 y축 이동은 사용하지 않으므로 y축 position을 고정했다.

Constraints

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

OnCollisionEnter(), GetComponent<>()  (0) 2022.08.02
메서드  (0) 2022.08.02
Cinemachine  (0) 2022.07.28
Time.deltaTime  (0) 2022.07.27
C# 포맷팅, Input.GetAxis()메서드  (0) 2022.07.27

Cinemachine

- 씬에 있는 여러 카메라를 관리하고 쉽게 카메라에 법칙을 추가할 수 있는 패키지

ex) 전투를 할 때, 숲 속을 달릴 때 컷 씬이나 극적인 순간을 보여줄 때 다른 카메라를 원할 수 있음

- 메인 카메라에 Cinemachine Brain을 추가해 어떤 가상 카메라를 통해서 봐야할 지 알도록 만든다.

ex) 전투를 위한 카메라는 오버 숄더 샷의 카메라로 잡음, 정글을 위한 카메라는 나무에 부딪히지 않도록 좀 더 멀리나 아래에서 씬을 잡을 수 있다.

 

Cinemachine 설치

Window - Pakage Manager - Pakage: Unity Registry - 우측 돋보기에서 Cinemachine 입력 후 선택하여 Install

설치된 모습

Inspector에서 AddComponent로 Cinemachine Brain을 선택하여 추가한다.

* 만약 카메라가 한 대라면 Cinemachine Brain 컴포넌트 추가 없이 바로 아래의 Hierachy창에 우클릭 - Cinemachine - Virtual Camera를 하면 main Camera에 Cinemachine Brain 컴포넌트가 자동으로 생성된다.

 

CinemachineBrain

Hierachy창에 우클릭 - Cinemachine - Virtual Camera를 한다.

Create Virtual Camera

이후 Virtual Camera의 이름을 Follow Cam으로 바꾼 후 드롭다운인 Body를 클릭하여 Framing Transposer로 변경한다.

- Follow : 정해진 위치에서 선택한 개체를 따라다님

- Look At : 감시카메라처럼 선택한 개체를 바라보며 회전함

Follow에서 플레이어를 선택하여 추가함

Follow

Body - Camera Distance : 개체와 카메라 거리

Save During Play : 체크하면 Play 중 수정이 플레이 끝나고도 적용된다.

'유데미 강의 > C#과 Unity로 3D 게임 개발하기 : 장애물 코스' 카테고리의 다른 글

메서드  (0) 2022.08.02
Collision  (0) 2022.07.28
Time.deltaTime  (0) 2022.07.27
C# 포맷팅, Input.GetAxis()메서드  (0) 2022.07.27
SerializedField  (0) 2022.07.27

+ Recent posts