[Unity Engine] 유니티 엔진 게임 개발 일지 #4

신형석·2023년 3월 14일
0

게임 개발 일지

목록 보기
4/10

저번까지 플레이어의 움직임과, 마우스 커서 방향으로 총알을 쏘는 알고리즘을 만들어보았다. 이번엔, 파티클 시스템에 대한 간단한 설명과 적용 방법을 알아보도록 하자.

파티클 시스템(Particle System)은, 해석 그대로 입자에 관련된 시스템이다. 폭발하는 이펙트, 연기 등등 입자를 가지고 노는 것이라고 보면 된다. 유니티 파티클 시스템에 대한 자세한 내용은 이곳을 참조하면 될 것 같다.

작성자가 만드는 게임에서 파티클이 필요한 부분은 총 2가지였다.

  1. 총알이 벽에 부딪히는 경우, 파티클을 불러오며 총알을 삭제시킨다
  2. 총알이 플레이어나 적에게 부딪히는 경우, 파티클을 불러오며 게임의 승패를 결정한다.

이렇게 2가지 경우가 있다. 현재 적이 구현되어있지 않으므로, 1번만 먼저 구현해보겠다.

파티클 시스템은 유니티의 왼쪽 부분을 우클릭하여, Effects -> Particle System을 클릭하면 위 사진과 같이 생성된다.

이 중 우리가 건드릴 수치는 총 3가지로, Boom Effect, Emission, Shape가 있다. 하나하나씩 설명해보겠다.

이 부분은 파티클이 나오는 방식을 커스터마이징할 수 있다. 각 수치를 조정하면 원하는 파티클이 나오게 할 수 있다. 폭발하는 이펙트는 Duration을 극도로 줄이고, Start Speed를 조금 늘린 후 Looping을 끄면 된다. 또한, Start Delay, Start Lifetime 등등과 같은 옵션들은 왼쪽에 보이는 하얀 역삼각형을 누르면 Random Between Two Constants라는 항목이 있다. 이것을 클릭하면, 두 상수 사이의 랜덤값으로 적용된다.

또한, 우리가 게임을 시작 할 때부터 켜는 것이 아닌, 특수한 상황에서만 켜주면 되므로 Play On Awake를 꺼준다.

Emission 부분은 파티클의 개수를 지정할 수 있다. Rate over Time은, 1초마다 내뿜는(?) 입자의 개수를 정하는 것이고, Rate over Distance는 한 단위의 거리마다 내뿜는 입자의 개수를 정할 수 있다.

Shape 부분은 파티클이 나오는 모양을 정할 수 있다. Shape와 Angle, Radius 부분만 조정해도 좋은 효과를 만들 수 있다.

각자 자신이 원하는 총알이 폭발하는 이펙트를 만들었으면, 이를 사용하는 코드를 작성해보겠다. 이 코드는 맵에서의 벽에 적용해놓았고, 벽에는 Trigger가 아닌 Collider를 적용해놓았다.

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

public class BulletDestroy : MonoBehaviour
{
    [SerializeField] ParticleSystem playerParticle;
    [SerializeField] ParticleSystem enemyParticle;
    ParticleSystem particle;

    Quaternion pos;
    // Start is called before the first frame update
    void Start()
    {
        pos = this.gameObject.transform.rotation;
    }

    // Update is called once per frame
    void OnTriggerEnter2D(Collider2D other) 
    {
        if (other.tag == "Player_Bullet" || other.tag == "Enemy_Bullet"){
            if (other.tag == "Player_Bullet")
            {
                particle = playerParticle;
            }
            else
            {
                particle = enemyParticle;
            }
            particle.transform.position = other.transform.position;
            particle.transform.rotation = pos;
            particle.Play();
            Debug.Log("Boom!");
            Destroy(other.gameObject);
        }
    }
}

이 코드에는 사실 총알의 삭제 코드도 포함되어 있으니, 하나씩 보도록 하겠다.

우선 SerializeField를 이용, 직접 만든 파티클 시스템을 받아올 수 있게 하였고, ParticleSystem 형의 particle 변수를 하나, Quarternion 형의 pos 변수를 하나 만들었다.

void Start()
{
    pos = this.gameObject.transform.rotation;
}

pos 변수에, 자기 자신(벽)의 rotation 값을 집어넣는다. 이는, 만들어진 파티클의 각도를 조정하기 위한 초석이다.

void OnTriggerEnter2D(Collider2D other) 
{
    if (other.tag == "Player_Bullet" || other.tag == "Enemy_Bullet"){
        if (other.tag == "Player_Bullet")
        {
            particle = playerParticle;
        }
        else
        {
            particle = enemyParticle;
        }
        particle.transform.position = other.transform.position;
        particle.transform.rotation = pos;
        particle.Play();
        Debug.Log("Boom!");
        Destroy(other.gameObject);
    }
}

tag를 활용하여, 벽에 맞는 bullet이 플레이어의 것인지 적의 것인지 판별한다. 만약 플레이어의 bullet이라면, particle에 playerParticle의 값을 집어넣고, 그렇지 않다면 enemyParticle을 집어넣는다.

그 후, transform.position과 transform.rotation을 이용하여 위치와 각도를 이동시켜 어색하지 않은 이펙트를 만들어준다. position은 other.transform.position과 일치시켜, bullet이 벽에 맞은 부분에서 particle을 생성할 수 있게 한다. rotation은 pos와 일치시켜, 벽의 각도에 따라 다른 방향으로 particle을 생성할 수 있게 한다.

particle.play()는, 꺼져있는 particle을 실행할 수 있게 해주는 코드이다. 아까, 우리는 게임을 실행하자마자 particle이 실행되는 것을 원치 않았기 때문에, Play On Awake를 꺼주었다. 이러면 우리가 play()를 불러오기 전까지는 실행되지 않는다. 그러므로, 꼭 particle을 원하는 위치에 불러온 후 play()를 실행해주도록 하자.

Destroy(other.gameObject);

이 코드는 간단하다. 벽에 부딪힌 other.gameObject(bullet)을 삭제시키는 코드이다. 우리가 발사한 bullet은 이전 게시글에서 bulletPrefab으로 만들었기 때문에, 총알을 삭제해도 무방할 것이다.

이렇게 파티클 이펙트에 대해 정리해보았다. 다음은, 적을 하나 만들어 일정 범위 내에 들어오면 플레이어쪽으로 총알을 발사해보는 것을 만들어보도록 하겠다.

파티클 시스템이 적용된 것을 보고 싶다면, 이전 게시글에서 마우스 방향으로 발사하는 영상에 이미 적용되어 있으니 그것을 보면 될 것 같다.

0개의 댓글

관련 채용 정보