Unity Chapter 6-1. 어메이징 볼링 게임 만들기 : 회전 포신, 포탄

Date:     Updated:

카테고리:

태그:

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


Chapter 6. 어메이징 볼링 게임 만들기

필요한 에셋 임포트

  1. Window - Assets Store 로 에셋 스토어에 접속
  2. 아래 에셋 3개를 검색하여 다운로드 받고 Import 해주자.
    • 체크되있는 모든 것들을 Import 해주기.
    1. “Unity Particle Pack” - 파티클
    2. “Free Music Bundle” - 배경음악
    3. “8-Bit Sfx” - 효과음


회전 포신 만들기

회전 포신의 모양이 될 오브젝트 만들기

  1. 큐브 오브젝트를 만든다.
    • 얘가 볼을 쏘는 포신의 모양이 될 것!
    • 이름은 Ball Barrel Model
  2. 가로로 길쭉해야 하니 scale 값은 (0.2, 0.2, 2)
  3. “Barrel”이름의 Material을 만들어 색을 입혀주자
  4. Box Collider 컴포넌트는 삭제해주자. (Remove Component)
    • 얘는 물리적 표면 충돌 처리 필요가 없어서.
    • Ball Barrel Model 얘는 단순한 3D 그래픽 모양이다.
    • 어떤 기능 처리 X

회전 포신을 제어하는 오브젝트 만들기

  1. 빈 오브젝트를 만든다.
    • 회전 포신을 제어하는 기능을 할 것.
    • 진짜 볼을 쏘는 기능
    • 이름은 Shooter Pivot
    • 볼을 쏘는 Pivot 위치의 중심이 될 것.
  2. Ball Barrel ModelShooter Pivot의 자식으로 넣어준다.
    • Shooter Pivot이 움직이면 이제 Ball Barrel Model도 같이 움직일 것.
  3. Pivot - Local 상태로 해주고
  4. Shooter Pivot는 원점 정중앙에 두고 Ball Barrel Model위치만 z축으로 1 이동시켜준다.
    • pivot은 중앙에 있고 포신 모양은 좀 앞으로 나온 상태.

📜ShooterRotator.cs : 발사버튼을 누르고 있는 동안 포신이 발사 각도를 조절하게

📜ShooterRotator.cs

  • Shooter Pivot에 붙여주자.
  • 포신이 먼저 수평방향으로 회전한 후에 수직방향으로 회전하게 할 것.
  • enum을 사용하여 포신의 현재 상태를 4가지로 정의하자.
    • Idle : 처음 게임 시작했을 때 모습
    • Vertical : 포신이 세로 방향으로 회전하고 있는 상태
    • Horizontal : 포신이 가로 방향으로 회전하고 있는 상태
    • Ready : 포탄을 쏠 수 있는 상태가 됐을 때
  • 수평방향 회전 👉 y 축을 기준으로 회전
  • 수직방향 회전 👉 x 축을 기준으로 회전
  • 동작 순서
    1. Idle 상태
    2. 마우스좌클 or 왼쪽 Ctrl키 누르는 순간(GetKeyDown)
    3. Horizontal 상태가 된다.
    4. 마우스좌클 or 왼쪽 Ctrl키 누르는 동안(GetKey)
    5. 수평 방향으로 회전한다.
      • y 축을 기준으로 1프레임 당 1/360도 만큼 회전
    6. 마우스좌클 or 왼쪽 Ctrl키 떼는 순간(GetKeyUp)
    7. Vertical 상태가 된다.
    8. 마우스좌클 or 왼쪽 Ctrl키 누르는 동안(GetKey)
    9. 수평 방향으로 회전한다.
      • x 축을 기준으로 1프레임 당 1/360도 만큼 회전
    10. 마우스좌클 or 왼쪽 Ctrl키 떼는 순간(GetKeyUp)
    11. Ready 상태가 된다.
      • Redy state에 대응되는 if 조건문은 없기 때문에 Ready가 되면 대기 상태가 된다.
  • Ball Barrel Model는 자식 오브젝트기 때문에 Shooter Pivot가 이렇게 회전하면 `Ball Barrel Model도 같이 회전한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShooterRotator : MonoBehaviour
{
    private enum RotateState
    {
        Idle, Vertical, Horizontal, Ready
    }

    private RotateState state = RotateState.Idle; // 1. 처음 시작은 Idle로
    public float verticalRotateSpeed = 360f; // 2. 수직방향 회전값 초기값 360도
    public float horizontalRotateSpeed = 360f; // 3. 수직방향 회전값 초기값 360도

    void Update()
    {
        if (state == RotateState.Idle)
        {
            if (Input.GetButtonDown("Fire1")) // 누르는 순간
            {
                state = RotateState.Horizontal; //  Horizontal 상태로 바꾸기
            }
        }
        else if (state == RotateState.Horizontal)
        {
            if (Input.GetButton("Fire1")) // 누르는 동안
            {
                transform.Rotate(new Vector3(0, horizontalRotateSpeed * Time.deltaTime, 0));// 수평 방향으로 `회전시키기`
            }
            else if (Input.GetButtonUp("Fire1")) // 떼는 순간
            {
                state = RotateState.Vertical; // Vertical 상태로 바꾸기
            }
        }
        else if (state == RotateState.Vertical)
        {
            if (Input.GetButton("Fire1")) // 누르는 동안
            {
                transform.Rotate(new Vector3(-verticalRotateSpeed * Time.deltaTime, 0, 0));// 수직 방향으로 `회전시키기`. 뒤로 넘어지는 것처럼 회전 (마이너스)
            }
            else if (Input.GetButtonUp("Fire1")) // 떼는 순간
            {
                state = RotateState.Ready; // Ready 상태로 바꾸기
            }
        }
    }
}
  • if (Input.GetButtonDown("Fire1"))
    • "Fire1"
      • 유니티 - Edit - Project Setting - input 에서 확인해 보면
      • 현재 “Fire1”은 왼쪽 Ctrl키와 마우스 좌클에 대응된다.
        • 누르는 순간(GetKeyDown)
        • 누르는 동안(GetKey)
        • 떼는 순간(GetKeyUp)
      • 참고 포스트
  • transform.Rotate(new vector3(-verticalRotateSpeed * Time.deltaTime, 0, 0))
    • - verticalRotateSpeed
      • x축 기준으로 플러스 방향으로 회전하면 앞으로 넘어지는 것 처럼 회전해서 마이너스를 붙여 뒤로 넘어지는 것 처럼 회전하게끔.


포탄 만들기

enum은 switch문에 쓰기 좋다.

📜ShooterRotator.cs 의 많은 if-else문을 switch-case문으로 변경했다.

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

public class ShooterRotator : MonoBehaviour
{
    private enum RotateState
    {
        Idle, Vertical, Horizontal, Ready
    }

    private RotateState state = RotateState.Idle; // 1. 처음 시작은 Idle로
    public float verticalRotateSpeed = 360f; // 2. 수직방향 회전값 초기값 360도
    public float horizontalRotateSpeed = 360f; // 3. 수직방향 회전값 초기값 360도

    void Update()
    {
        switch(state)
        {
            case RotateState.Idle:
                if (Input.GetButtonDown("Fire1")) // 누르는 순간
                {
                state = RotateState.Horizontal; //  Horizontal 상태로 바꾸기
                }
            break;

            case RotateState.Horizontal:
                if (Input.GetButton("Fire1")) // 누르는 동안
                {
                    transform.Rotate(new Vector3(0, horizontalRotateSpeed * Time.deltaTime, 0));// 수평 방향으로 `회전시키기`
                }
                else if (Input.GetButtonUp("Fire1")) // 떼는 순간
                {
                    state = RotateState.Vertical; // Vertical 상태로 바꾸기
                }
            break;

            case RotateState.Vertical:
                if (Input.GetButton("Fire1")) // 누르는 동안
                {
                    transform.Rotate(new Vector3(-verticalRotateSpeed * Time.deltaTime, 0, 0));// 수직 방향으로 `회전시키기`. 뒤로 넘어지는 것처럼 회전 (마이너스)
                }
                else if (Input.GetButtonUp("Fire1")) // 떼는 순간
                {
                    state = RotateState.Ready; // Ready 상태로 바꾸기
                }
            break; 

            case RotateState.Ready:
            break;
        }
    }
}

포탄 오브젝트 만들기

  1. Sphere 오브젝트를 만들어준다.
    • 이름은 Ball
  2. “Ball”이름의 Material을 만들어 색을 입혀주자
  3. Sphere Collider 컴포넌트에 is Trigger를 체크해주자.
    • Ball은 다른 오브젝트와 부딪치면 튕겨 나간다던지 등등 그런 물리적인 표면 기능은 부여하지 않을 것이다.
    • 다만 다른 오브젝트와 충돌이 일어나면 어떤 이벤트 처리를 해줄 것이기 때문에 체크!
  4. Rigidbody 컴포넌트를 추가해준다.
    • 물리 기능이 필요하므로!
    • 포탄을 발사하면 날아가야 하니까.
  5. 파티클 사용할 준비
    • 다운받아 Import한 “EffectExamples” 폴더에 들어가서 사용할 파티클 Prefab을 Hierarchy창에 옮겨주자.
    • /📁EffectExamples/📁Fire&Explosion/📁Prefab
    • 🟦PlasmaExplosionEffect 프리팹 을 Heierarchy 창에 가져와 오브젝트로서 씬 상에 실존하게 해주자. (오브젝트 찍어 만들기)

Import 해 온 🟦PlasmaExplosionEffect 프리팹을 수정하여 나만의 프리팹으로 만들기.

  • Prefab오브젝트를 찍어낼 수 있게 미리 틀처럼 만들어진 오브젝트!
    • Assets 폴더에 만들어 놓은 Prefab 을 Hierarchy 창으로 드래그 하면 오브젝트를 찍어낼 수 있다.
    • 반대로 Hierarchy 창에서 기존에 실존하던 오브젝트를 Assets 폴더에 옮기면 이 오브젝트를 프리팹으로 만들 수 있다.
  • 포탄이 바닥에 떨어지는 순간 빵 터지게 할 것이기 때문에 파티클 효과가 필요하다. Import 해 온 이 파티클을 원하는대로 수정해보자
  • 파티클 시스템은 2D 이미지를 랜덤하게 생성해서 특수 효과를 만들어 주는 방식이다.
  • 여러 오브젝트(Prefab)이 자식으로 붙어있다. 이 경우엔 4가지 자식이 있음.
  1. Particle System 컴포넌트에서 Looping 을 체크 해제해준다.
    • 파티클 효과는 포탄이 바닥에 떨어지는 그 순간에만 딱 한번 일어나야 하기 때문에 Looping 해제.
    • PlasmaExplosionEffect 오브젝트 를 비롯한 자식 파티클들까지 전부 선택해준 후 (shift 단축키 이용) Looping을 해제해준다.
  2. Particle System 컴포넌트에서 Play On Awake 를 체크 해제해준다.
    • 파티클 효과 언제 시작될지는 스크립트에서 제어할 것
    • PlasmaExplosionEffect 오브젝트 를 비롯한 자식 파티클들까지 전부 선택해준 후 (shift 단축키 이용) Play On Awake을 해제해준다.
  3. 터질 때 효과음을 주자
    • PlasmaExplosionEffect 오브젝트Audio Source 컴포넌트를 붙여주자.
    • Audio Clip 부분에 Import 한 mp3 목록 중 “Explosion_00.mp3”을 붙여주도록 하자. (오른쪽에 조그만 동그라미 버튼을 누르면 mp3파일 목록중에서 선택 가능)
    • Play On Awake 은 체크 해제 해주자. 재생 되는 시기는 스크립트에서 제어할 것. 참고로 얘를 체크하면 오브젝트가 생성 되자마자 바로 재생한다.
  4. /📁Assets 에 📁Prefabs 폴더를 새로 만들어 Hierarchy 창에 있는 PlasmaExplosionEffect 오브젝트 을 드래그 앤 드롭 하여 🟦PlasmaExplosionEffect 프리팹 으로 만들어주자.
    • 사용하는 프리팹은 폴더에 따로 만들어 관리하자. (Original로 드래그 앤 드롭)
    • 1 ~ 2까지 수정해 만든 오브젝트다시금 *프리팹*으로 만든 것이다.
    • 수정한 현재 씬 상에서의 기존 PlasmaExplosionEffect 오브젝트는 삭제해주자.
  5. 새로 수정하여 만든 🟦PlasmaExplosionEffect 프리팹 을 Hierarchy창으로 드래그 하여 Ball 오브젝트의 자식 오브젝트 로 넣어 주자. (PlasmaExplosionEffect 오브젝트 를 만듬)
    • 위치는 0, 0, 0으로 Ball의 위치와 같게
    • Ball의 자식이니까 Ball과 함께 졸졸 따라다닐 것.
    • 그러다가 Ball이 터지는 자리에서 파티클 효과와 효과음을 재생시킬 것.

📜Ball.cs

  1. 📜Ball.cs을 Ball 오브젝트에 붙여주자.
  2. 발사 할 때마다 Ball 오브젝트를 찍어낼 수 있도록 Ball 오브젝트를 Prefab으로 만들어 주자.
    • /📁Assets/📁Prefabs 로 드래그
  3. 3D Object Plane 오브젝트를 만들어 바닥을 만들어 주자.
    • 위치는 원점
    • Material로 색깔 주기
    • sclae은 (10, 10, 10)

📜Ball.cs 의 역할

  1. Ball 오브젝트가 죽는 순간 자식인 PlasmaExplosionEffect 오브젝트(파티클)을 생성하고 죽는다.
  2. Ball 오브젝트 주변의 오브젝트들(프롭)도 같이 파괴해야 한다. (👉 다음 포스팅에서 구현)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball : MonoBehaviour
{
    //  ParticleSystem 컴포넌트와 AudioSource 컴포넌트가 붙어 있는  `PlasmaExplosionEffect` 오브젝트를 이 2개의 슬롯에 드래그 앤 드롭 해줄 것.
    public ParticleSystem explosionParticle;  
    public AudioSource explosionAudio;

    public float maxDamage = 100f; // 주변에 뿌릴 수 있는 최대의 데미지. 100으로 설정.
    public float explosionForce = 1000f; // 폭발 반경 내로 주변에 뿌리는 힘. 1000으로 설정.
    public float lifeTime = 10f; // 볼의 수명. 10초 이상 파괴가 안되면 스스로 파괴하게끔 할 것이다. (맵 밖, 버그 등으로 볼이 파괴가 안될 때 파괴해주려고)
    public float explosionRadius = 20f; // 폭발 반경

    void Start()
    {
        Destroy(gameObject, lifeTime); // 자기 자신을 10초 뒤에 파괴하게끔
    }

    private void OnTriggerEnter(Collider other) // Is Trigger가 체크된 `Trigger`인 Collider와 충돌할 때 자동으로 실행된다. other는 충돌한 상대방.
    {
        explosionParticle.transform.parent = null; // PlasmaExplosionEffect 오브젝트의 부모를 없애버림

        explosionParticle.Play();  // 파티클 효과 재생 (Particle System)
        explosionAudio.Play();  // 효과음 재생 (Audio Source)

        Destroy(explosionParticle.gameObject, explosionParticle.duration); // explosionParticle가 참조하는 gameObject 파괴
        Destroy(gameObject); // 자기 자신(Ball) 파괴
    }
}
  • 변수
    • explosionParticle
      • ParticleSystem 컴포넌트가 붙어 있는 PlasmaExplosionEffect 오브젝트를 이 슬롯에 드래그 앤 드롭 해줄 것.
    • explosionAudio
      • Audio Source 컴포넌트가 붙어 있는 PlasmaExplosionEffect 오브젝트를 이 슬롯에 드래그 앤 드롭 해줄 것.
    • maxDamage
      • 주변에 뿌릴 수 있는 최대의 데미지.
    • explosionForce
      • 폭발 반경 내로 주변에 뿌리는 힘.
    • lifeTime
      • 볼의 수명.
      • 10초 이상 파괴가 안되면 스스로 파괴하게끔 할 것이다.
        • 맵 밖, 버그 등으로 볼이 파괴가 안될 때 파괴해주려고
    • explosionRadius
      • 폭발 반경
  • 함수
    • void Start()
      • Ball 오브젝트가 생성된 후 10초가 지나면 자기 자신을 파괴.
    • onTriggerEnter(Collider other)
      • Is Trigger가 체크된 Trigger인 Collider와 충돌할 때 자동으로 실행된다.
      • other는 충돌한 상대방.
      • 충돌하면 자기 자신(Ball 오브젝트)을 파괴하고 PlasmaExplosionEffect 오브젝트(파티클)를 재생해야 한다.
        1. 그러나 부모(Ball)가 파괴되면 자식(PlasmaExplosionEffect)도 파괴되므로 Ball이 파괴되는 순간 PlasmaExplosionEffect부모를 없애야 한다.
          • explosionParticle.transform.parent = null;
          • PlasmaExplosionEffect의 부모를 없애준다.
          • 부모 자식 관계는 *Transform 컴포넌트*가 관리한다.
        2. PlasmaExplosionEffect의 Particle System 재생
          • explosionParticle.Play();
        3. PlasmaExplosionEffect의 Audio Source 재생
          • explosionAudio.Play();
        4. PlasmaExplosionEffect 오브젝트 파괴
          • Destroy(explosionParticle.gameObject, explosionParticle.duration)
          • duration : 특수 효과가 재생되는 러닝타임을 Particle System 오브젝트 스스로 알고 있다.
        5. Ball 오브젝트(자기 자신)도 파괴.
          • Destroy(gameObject)
  • 이제 explosionParticle 슬롯에 PlasmaExplosionEffect 오브젝트를, explosionAudio 슬롯에 PlasmaExplosionEffect 오브젝트를 드래그 앤 드롭으로 붙여주고 실행해보자.
  • Apply를 눌러서 Assets의 Prefab에도 적용시켜주자.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 1 카테고리 내 다른 글 보러가기

댓글 남기기