Unity Chapter 11-12. 좀비 TPS 게임 만들기 : 파티클 시스템
카테고리: Unity Lesson 1
태그: Unity Game Engine
인프런에 있는 이제민님의 레트로의 유니티 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
Common
- 대부분에 사용될 일반 피탄 이펙트
Flesh
- 피부나 살에 총알이 부딪혔을때 사용할 피가 튀는 이펙트
- 파티클 프리팹 두개를 할당한 후 복제해서 게임 도중 생성할 것이다.
commonHitEffectPrefab
- 🟦Metal Impact 프리팹을 할당해준다.
fleshHitEffectPrefab
- 🟦Flesh Impact 프리팹을 할당해준다.
멤버 함수
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
니까 일단targetPrefab
을commonHitEffectPrefab
로 지정한다.
- 일반적으로 쓰이는 이펙트는
- 그런데 만약에 이펙트 타입이
Common
이 아닌Flesh
라면 그때targetPrefab
을fleshHitEffectPrefab
로 지정한다.
- var
- 이펙트 복제 생성 (from 프리팹)
- var effect = Instantiate(targetPrefab, pos, Quaternion.LookRotation(normal));
- 이펙트의 부모가 될 Transform이 인수로 들어온게 있다면
- 그것을 이펙트의 부모로 설정
- effect.transform.SetParent(parent);
- 그것을 이펙트의 부모로 설정
- 이펙트 재생
파티클 성능 관리
파티클 프리팹으로 부터 복제 생성된 파티클 오브젝트들이 총을 너무 많이 쏴서 씬 상에 너무 많이 생성되면 성능 저하가 일어날 수 있다.
- 이에 대한 대처 방법
- 오브젝트 풀링
- 재사용 가능한 객체들을 미리 몇개 생성해두고 이를 돌아가며 가져다 쓴다.
- 이들을 사용중/사용안함 으로 관리한다.
- 디자인패턴 : 오브젝트 풀 패턴 참고
- 재생 종료된 파티클은 그때 그때 파괴시켜 메모리 해제시켜 주기
- 이 수업에서는 이 방식을 택할 것이다.
- 사용할 이펙트 프리팹인 🟦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;
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기