Unity Chapter 11-12. 좀비 TPS 게임 만들기 : 파티클 시스템

Date:     Updated:

카테고리:

태그:

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


Chapter 11. 좀비 TPS 게임 만들기

파티클 시스템

  • 파티클 제어를 담당할 빈 게임 오브젝트 Effect Manager를 생성한다.
    • 위치는 상관 없긴 하지만 그래도 reset 해주자.


📜EffectManager.cs

빈 게임 오브젝트 Effect Manager에 붙여준다.

싱글톤으로서 존재한다.

using UnityEngine;

public class EffectManager : MonoBehaviour
{
    private static EffectManager m_Instance;
    public static EffectManager Instance
    {
        get
        {
            if (m_Instance == null) m_Instance = FindObjectOfType<EffectManager>();
            return m_Instance;
        }
    }

    public enum EffectType
    {
        Common,
        Flesh
    }

    public ParticleSystem commonHitEffectPrefab;
    public ParticleSystem fleshHitEffectPrefab;

    public void PlayHitEffect(Vector3 pos, Vector3 normal, Transform parent = null, EffectType effectType = EffectType.Common)
    {
        var targetPrefab = commonHitEffectPrefab;

        if (effectType == EffectType.Flesh)
        {
            targetPrefab = fleshHitEffectPrefab;
        }

        var effect = Instantiate(targetPrefab, pos, Quaternion.LookRotation(normal));

        if (parent != null) effect.transform.SetParent(parent);

        effect.Play();
    }
}

싱글톤

파티클에 접근하는 여러 스크립트들에서 직접 파티클 오브젝트를 참조할 수도 있지만 그렇게 하면 여러곳에서 동시에 참조할 수 있으니까 너무 혼잡 난잡! 👉 싱글톤을 사용하는 이유

    private static EffectManager m_Instance;
    public static EffectManager Instance  // 이펙트 매니저 인스턴스를 리턴받을 프로퍼티
    {
        get
        {
            if (m_Instance == null) m_Instance = FindObjectOfType<EffectManager>();
            return m_Instance;
        }
    }
  • private한 m_Instance를 리턴해주는 Instance 프로퍼티를 통하여 기존의 📜EffectManager 인스턴스가 없을 때만, 즉 m_Instace == null일때만 📜EffectManager 인스턴스인 m_Instance를 리턴 받는다.
    • 📜EffectManager 인스턴스가 오직 하나만 존재하도록 관리해주는 것!


멤버 변수

  • 파티클 상태 EffectType
    1. Common
      • 대부분에 사용될 일반 피탄 이펙트
    2. Flesh
      • 피부나 살에 총알이 부딪혔을때 사용할 피가 튀는 이펙트
  • 파티클 프리팹 두개를 할당한 후 복제해서 게임 도중 생성할 것이다.
    • commonHitEffectPrefab
      • 🟦Metal Impact 프리팹을 할당해준다.
    • fleshHitEffectPrefab
      • 🟦Flesh Impact 프리팹을 할당해준다.
    • image


멤버 함수

public void PlayHitEffect

    public void PlayHitEffect(Vector3 pos, Vector3 normal, Transform parent = null, EffectType effectType = EffectType.Common)
    {
        var targetPrefab = commonHitEffectPrefab;

        if (effectType == EffectType.Flesh)
        {
            targetPrefab = fleshHitEffectPrefab;
        }

        var effect = Instantiate(targetPrefab, pos, Quaternion.LookRotation(normal));

        if (parent != null) effect.transform.SetParent(parent);

        effect.Play();
    }
  • 인수
    • pos 이펙트 위치
    • normal 이펙트가 바라볼 방향
    • parent 이펙트에게 할당할 부모
      • 디폴트 null
      • 움직이는 대상으로 이펙트가 생성 되었을 때 이펙트가 움직이는 물체를 따라가야 하는 경우에는 그 대상을 이펙트의 부모로 할당해주어야 한다.
    • effectType 이펙트 타입
      • 디폴트 Common
  • 이펙트 할당
    • var targetPrefab = commonHitEffectPrefab;
      • 일반적으로 쓰이는 이펙트는 commonHitEffectPrefab 니까 일단 targetPrefabcommonHitEffectPrefab로 지정한다.
    • 그런데 만약에 이펙트 타입이 Common이 아닌 Flesh라면 그때 targetPrefabfleshHitEffectPrefab로 지정한다.
  • 이펙트 복제 생성 (from 프리팹)
    • var effect = Instantiate(targetPrefab, pos, Quaternion.LookRotation(normal));
  • 이펙트의 부모가 될 Transform이 인수로 들어온게 있다면
    • 그것을 이펙트의 부모로 설정
      • effect.transform.SetParent(parent);
  • 이펙트 재생


파티클 성능 관리

파티클 프리팹으로 부터 복제 생성된 파티클 오브젝트들이 총을 너무 많이 쏴서 씬 상에 너무 많이 생성되면 성능 저하가 일어날 수 있다.

  • 이에 대한 대처 방법
    1. 오브젝트 풀링
    2. 재생 종료된 파티클은 그때 그때 파괴시켜 메모리 해제시켜 주기
      • 이 수업에서는 이 방식을 택할 것이다.
      • 사용할 이펙트 프리팹인 🟦Flesh Impact 와 🟦Metal Impact 의 Stop Action 부분을 Destroy로 설정한다.


파티클 재생을 누가 할 것인가

  • IDamageable타입이라서 데미지를 입을 수 있는 오브젝트라면
    • 👉 스스로 어떤 파티클을 재생 시켜야할지 결정한다.
    • 굳이 총을 쏘는 사람 입장에서 파티클 효과를 결정해줄 필요가 없다.
      • 각각 IDamageable인터페이스를 오버라이딩 하는 데미지 입을 수 있는 오브젝트들(스크립트)에서 각각에서 오버라이딩 한 ApplyDamage 함수내에서 파티클 효과를 결정할 것!
      • target.ApplyDamage(damageMessage);
  • 반대로 데미지를 입을 수 있는 오브젝트가 아니라면
    • 범용적인 파티클 효과로! 미리 설정해둠.
    • 스스로 어떤 파티클을 재생시켜야 할지를 결정하지 않음
      • EffectManager.Instance.PlayHitEffect(hit.point, hit.normal, hit.transform);

📜Gun.cs

Shot 함수

✨✨ 부분 추가

 if (target != null)
{
    DamageMessage damageMessage;

    damageMessage.damager = gunHolder.gameObject;
    damageMessage.amount = damage;
    damageMessage.hitPoint = hit.point;
    damageMessage.hitNormal = hit.normal;

    // 상대방의 OnDamage 함수를 실행시켜서 상대방에게 데미지 주기
    target.ApplyDamage(damageMessage); // 💛
}
else
{
    EffectManager.Instance.PlayHitEffect(hit.point, hit.normal, hit.transform);  // ✨✨
}
// 레이가 충돌한 위치 저장
hitPosition = hit.point;


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

맨 위로 이동하기


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

댓글 남기기