본문 바로가기

카테고리 없음

[게임 개발자가 되어보자] 슈팅게임 Prototype 제작해보기 ft. 인생유니티

해당 글은 성안당 교과서의 인생유니티 교과서에 대한 내용을 담고 있습니다.

모든 코드와 그림의 출처는 아래 책과 같습니다.

저자: 이영훈 ,  김태환 외 6명

프로젝트의 제작

  1. 프로토타입
    • 프로젝트의 가능성 검증
  2. 알파
    • 프로젝트 전체 구현 작업 완성
  3. 베타
    • 클라이언트에 보여주는 단계
    • 퀄리티 작업, 최적화 작업
    • 디버깅 & 리펙토링
    • ex ) Open Beta, Close Beta → 클라이언트의 의견과 콘텐츠의 안정성 점검및 검증
  4. 최종( = Master.ver)

0. 프로젝트 생성과 환경 설정

  • 3D 환경에서 제작 but 사용자에게는 2D로 보여짐 → 2D로 보여지는 화면을 구성 할 것임
  • 프로젝트 생성은 3D로 진행 → 작업환경은 2D형태로 변경 예정
    • 왜 2D로 만들지 않는가? → 다양한 상황에 대응하기 위해 2D환경에 필요한 것이 무엇인지 파악하는 과정이라고 생각할것

1. 유니티 레이아웃 설정하기

  • 기존 페이지에서 설명

2. 2D 작업환경 만들기

  • 씬의 기즈모를 변경 (persp → ISO(아이소매트릭)) → 쿼터 뷰 확인이 가능한 직교 모드(= 원근감이 없는 상태)
  • 기즈모의 색상과 xyz 3차원을 표현하는 영문자는 매칭되어있음 (RGB→XYZ)
  • Main Camera 객체가 바라보는 구도로 씬화면 변경 → Z 축 반대편 클릭(ISO → back 으로 변경)

⇒ 여기까지가 씬뷰의 [2D] 버튼을 눌렀을때와 동일한 상태

⇒ 2D버튼을 눌러서 세팅하면 기즈모가 사라짐

    • 카메라 설정
      • 카메라 = 플레이어의 눈
      • Main Camera → 3개의 컴포넌트(Transform, Camera, Audio Listener)
      • 💡 Audio Listener 컴포넌트가 붙어있는 게임 오브젝트는 씬에 단 하나만 있어야 함
      • 카메라의 Projection 속성을 Orthographic(직교모드)로 변경
        • projection 속성 : 화면을 어떻게 찍을지 지정하는 역활(렌즈)
      • Position Y값도 0으로 설정
      • Camera의 Size 속성 = 카메라 세로크기의 절반
        • Size 키우면 멀리보는 효과
        • Size 줄이면 가까워지는 효과
    • 조명 설정
      • 2D에서는 조명 필요없음(무조건적인건 아니에욥)
      • Directional Light에서 Light 컴포넌트 비활성화 → 조명 사라짐 → 암것도 안보임 ㅠㅠ
      • 일반적인 2D 콘텐츠에서는 Sprite를 사용해 2D 제작
        • but 우리책은 다른 방식으로 진행  
        • 더보기
          💡 Light Mapping 비활성화 [Window]→[Rendering]→[Lighting]What is Light Mapping?
          • 조명상태를 계속 감지해 변화가 생겼을 때 그 상태를 저장해 이미지로 만드는 기능
          • 2D에서는 작업에 방해가 됨
    • 조명이 없으면 화면에 아무것도 안보이는데 어떡하지?
- 화면의 반사 성질에 따라 빛은 난반사광(Diffuse), 정반사광(Specular), 주변 환경광(Ambient) 3가지 요소가 합쳐져 표현됨
- 빛을 없앴다 → Diffuse와 Specular를 적용하지 않았다는 것
- Ambient 값은 Lighting Settings 창에서 지정해서 사용 가능
- 그래서 우리는 Ambient값을 color로 지정해준뒤 색을 하얀색으로 바꾼다
  • 해상도 설정
    • 배포환경에 맞춰 변경

3. 플레이어 이동 제작

*context menu

  1. 게임 오브젝트 생성
    • cube 생성
  2. 이동 스크립트 생성후 할당
    1. Project뷰에서 Scripts Folder 생성
    2. C# Scripts 생성 ( 확장자 : cs)
    3. 파일이름과 클래스 이름은 동일해야함
    4. 스크립트를 드래그하여 Hierarchy 의 Player 객체에 할당 → 이후 Player 객체에 새로운 컴포넌트가 할당돼 붙게 됨
  3. 이동 스크립트 구현
    1. 목표 → 사용자의 입력에 따라 플레이어를 이동시키고 싶다
    2. 순서 세분화
      1. 사용자 입력 처리
      2. 방향 만들기
      3. 플레이어 이동

플레이어 이동시키기 1

// Code 3.1-1

public class PlayerMove : MonoBehavior
{
    void Update( )
    {
        //저장후 유니티에서 실행시키면 Player 객체가 오른쪽으로 이동
        transform.Translate(Vector3.right * 5 * Time.deltaTime);
        // 회전은 .Rotate 이용
    }
{
  • 벡터
    • 크기와 방향을 가짐
    • 자료형(data type) 일종
    • 더하기, 빼기, 곱하기(내적, 외적) 연산 중요
    • ex) 플레이어를 대각선으로 이동시키기 위해 위쪽과 오른쪽 방향키를 동시에 누름 → 이때 벡터의 합에 의해 플레이어는 대각방향으로 이동
    • 벡터의 더하기 : 가해지는 모든 힘의 합
    • 벡터의 빼기 : 방향을 구할때?
    • 벡터의 정규화 : 벡터의 크기를 1로 만들어주는 동작 → 크기를 일정하게 함으로써 순간이동 안함
// Code 3.1-2
// 객체의 이동속도를 전역변수로 빼서 조작

public class PlayerMove: MonoBehavior
{
    //플레이어가 이동할 속력 -> 이렇게 변수로 빼놔야지 기획자가 수정하면서 게임의 밸런스를 잡아가기 용이함
    public float speed = 5;

    void Update( )
    {
        //저장후 유니티에서 실행시키면 Player 객체가 오른쪽으로 이동
        transform.Translate(Vector3.right * speed * Time.deltaTime);
        // 기획자는 이렇게 노출된 속성을 개발 초기 단계부터 변경해가면서 게임의 밸런스를 잡아감
    }
{
  • Life - Cycle 함수
    • 함수를 특수한 목적으로 사용하고 있는 것
    • 객체의 라이프 사이클 : 태어남 → 살다가 → 죽음
      • 각 사이클의 특징
        1. 일어나는 횟수
        2. 일어나는 때를 아는지에 대한 여부
      • Start, Update, OnDestroy가 Life - Cycle 역할을 하는 유니티의 내부 함수
      • Life - Cycle 표
      구분 태어나서 살다가 죽다
      발생 횟수 1 계속 1
      발생 일시 확인 여부 O O X
      유니티 함수 Start Update OnDestroy
  • deltaTime
    • 하나의 일을 처리하는데 걸리는 시간?
    • 1초에 n번의 일을 처리한다고 했을때 하나의 일을 처리할때 걸리는 시간
    • | ——-|——-|——-|——-| : 4번의 일을 처리하는 1초 → deltatime = 0.25초
    • 시스템간의 동기화를 위해 사용
    • 이동만이 아닌 회전하는 에니메이션 처리, 크기 변환하는 애니메이션 처리에서도 사용
  • 사용자 입력 처리
// Code 3.1-3
// 객체의 이동속도를 전역변수로 빼서 조작

public class PlayerMove: MonoBehavior
{
	//플레이어가 이동할 속력
	public float speed = 5;
	
	void Update( )
	{
			float h = Input.GetAxis("Horizontal"); //vs GetAxisRaw : -1,0,1만을 반환해서 이동속도 더 빠름
			print(h);
			transform.Translate(Vector3.right * speed * Time.deltaTime);
	}
{
//저장후 유니티 실행
// A키를 누르면 -1(벡터가 이런식이구만)
// D키를 누르면 1
// 아무것도 안누르면 0
//[Edit] - [Project Settings] - [Input]의 Axes목록 확인 가능

 

  • 방향 만들기
// Code 3.1-3
// 객체의 이동속도를 전역변수로 빼서 조작

public class PlayerMove: MonoBehavior
{
    //플레이어가 이동할 속력
    public float speed = 5;

    void Update( )
    {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");

            //방향과 관련된 값이 필요 -> dir
            Vector3 dir = Vector3.right * h + Vector3.up * v; //벡터의 더하기 이용
            transform.Translate(dir * speed * Time.deltaTime);
    }
{
//Vector3가 정확히 어떤 자료형이지? Vector2,1도 있나?
//방향에 관련된 값을 만들어 기억해야만 '방향으로 이동하기'를 할 수 잇음
//방향을 기억하고 있을 변수 dir 사용
// Code 3.1-3
// 객체의 이동속도를 전역변수로 빼서 조작

public class PlayerMove: MonoBehavior
{
    //플레이어가 이동할 속력
    public float speed = 5;

    void Update( )
    {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");

            //Vector3 dir = Vector3.right * h + Vector3.up * v; //벡터의 더하기 이용
            Vector3 dir = new Vector3(h, v, 0); //성분값으로 방향 표현

            transform.Translate(dir * speed * Time.deltaTime);
    }
{
//Vector3가 정확히 어떤 자료형이지? Vector2,1도 있나?
//방향에 관련된 값을 만들어 기억해야만 '방향으로 이동하기'를 할 수 잇음
//방향을 기억하고 있을 변수 dir 사용

플레이어 이동시키기2

  • 코드가 유니티에 너무 종속되면 유동성이 떨어짐
  • 유니티에 종속된 코드내용(translate함수)을 실제 원리에 기반해서 구현할수 있어야 함
  • 이번 물체의 이동에 사용할 공식은 P = P0 + vt를 사용
// Code 3.1-7
// 종속적인 유니티 코드를 등속운동 공식에 기반해 변형

public class PlayerMove: MonoBehavior
{
    //플레이어가 이동할 속력
    public float speed = 5;

    void Update( )
    {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");
            Vector3 dir = new Vector3(h, v, 0); //성분값으로 방향 표현

            //P = P0 + vt 공식으로 변경 , 직선운동이 아니니까 dir이 있는건 당연한거지
            transform.position = transform.position + dir * speed * Time.deltaTime;
            //중복 제거
            transform.position += dir * speed * Time.deltaTime;            
    }
{

 


 

여기까지가 플레이어의 이동과 관련된 부분이다.

다음시간에는 총알 오브젝트를 생성하고 이동및 발사 액션을 만들어보자!