VFX와 Particle을 사용하여 검을 휘두를 때 검기 이펙트가 나와 더욱 풍부한 비주얼을 보여줄 수 있도록 검기 이펙트 VFX와 파티클을 만들고 적용합니다.
💬 서론
- 위 영상을 통해 검기 이펙트를 위한 VFX 베이스를 잡고, 기존 지식을 활용하여 보완하여 만들었습니다.
✅ 구현
· VFX 만들기
- VFX는 영상을 통해 기본적인 프레임을 만들고, 기존 지식을 활용하여 수정하여 만들었습니다.
- [유니티 VFX] 검기(칼 효과) + 쉐이더에서 쉐이더그래프와 파티클을 받을 수 있습니다.
- 조금 더 번쩍이는 효과를 구현하기위해 색상값을 Color에 사용하지 않고 Emission에 사용하여 효과를 강조하였습니다.
- 영상에서는 블렌더를 이용하여 검기를 위한 메시를 직접 제작하여 필자 또한 메시를 제작하였습니다. 해당 메시파일은 아래 첨부파일에서 다운로드할 수 있습니다.
· VFX 관리
- VFX는 런타임 도중 특정 조건이되면 활성화되었다가 사라지는 방식으로 사용합니다. 이러한 상황에서 오브젝트 풀링을 이용하여 더욱 효율적으로 관리하면 좋습니다.
- 파티클 시스템과 달리 VFX는 자동으로 Disable 또는 Destroy 옵션이 없기 때문에 LifeTime을 미리 지정하여 VFX 오브젝트가 비활성화되는 시간을 미리 정해줘 자동으로 Disable이 되어 풀링 할 수 있도록 구현합니다.
· VFXController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VFXController : MonoBehaviour
{
[Header("VFX의 지속시간(이 시간이 지나면 disable)")]
[SerializeField] private float mLifeTime;
private Coroutine? mCoDisable; // 비활성화 코루틴
public void Play(Transform? targetTransform = null)
{
if (targetTransform is not null)
{
transform.position = targetTransform.position;
transform.rotation = targetTransform.rotation;
}
if (mCoDisable is not null)
StopCoroutine(mCoDisable);
mCoDisable = StartCoroutine(CoDisable());
}
private IEnumerator CoDisable()
{
yield return new WaitForSeconds(mLifeTime);
gameObject.SetActive(false);
}
}
[Header("VFX의 지속시간(이 시간이 지나면 disable)")]
[SerializeField] private float mLifeTime;
- VFX가 몇초후에 Disable 될지 시간초를 지정합니다.
- 이 시간이 지나면 오브젝트는 비활성화됩니다.
- 비활성화되면 오브젝트풀링에서 이 오브젝트를 재사용할 수 있도록 합니다.
private Coroutine? mCoDisable; // 비활성화 코루틴
- 코루틴을 이용하여 mLifeTime을 기준으로 비활성화하도록 하는 상황 속에서 코루틴이 중복으로 호출될 수 있는 가능성을 고려하여 이미 실행 중인 코루틴을 종료하도록 하기 위해 사용합니다.
public void Play(Transform? targetTransform = null)
- VFX 효과를 재생합니다.
- targetTransform은 해당 트랜스폼에 위치하여 재생할 수 있도록 해줍니다.
· 오브젝트 풀
- 오브젝트 풀링은 별도로 설명하지 않겠습니다.
- 풀링을 사용하는 스크립트는 오래전에 작성한 글과 크게 다르지 않습니다.
- [유니티] 오브젝트 풀링 이곳에서 확인할 수 있습니다.
✅ 사용
- 오브젝트 풀링을 사용하여 런타임 도중 특정 조건(검을 휘두를 때)에 풀링에서 오브젝트를 꺼내 VFX를 재생하도록 합니다.
- 해당 스크립트는 FSM 및 애니메이션 이벤트를 사용하여 특정 메시지가 전달되면 호출되는 방식이며, 이 스크립트가 아니어도 특정 조건에 오브젝트 풀링에서 VFX를 꺼내 사용하면 됩니다.
/// <summary>
/// 기본 공격 1
/// </summary>
public class SWORD_ATTACK_1 : State<PlayerController>
{
...
public override bool OnMessage(PlayerController entity, Telegram telegram)
{
...
if (telegram.message == "ANIM_PlayerSwordAttack01")
{
...
VFXPool.Instance.GetFromPool(VFX_TYPE.SWORD_SLASH, entity.SwordSlashVfxAnchor);
ParticlePool.Instance.GetFromPool(PARTICLE_TYPE.WEAPON_IMPACT_CIRCLES, entity.SwordSlashVfxAnchor);
}
if (telegram.message == "ANIM_PlayerSwordAttack01End") { mIsAnimEnd = true; }
...
return false;
}
}
VFXPool.Instance.GetFromPool(VFX_TYPE.SWORD_SLASH, entity.SwordSlashVfxAnchor);
ParticlePool.Instance.GetFromPool(PARTICLE_TYPE.WEAPON_IMPACT_CIRCLES, entity.SwordSlashVfxAnchor);
- VFXPool을 싱글턴으로 구현하여 특별한 임포트나 컴포넌트 획득 없이 GetFromPool을 통해 해당 오브젝트를 얻어올 수 있습니다.
- entity.SwordSlashVfxAnchor는 칼에 붙어있는 앵커의 위치입니다. 해당 트랜스폼과 같은 속성값으로 VFX가 생성되어 재생됩니다.
- entity.SwordSlashVfxAnchor의 위치는 다음과 같습니다. 방향또한 영향을 받습니다.
✅ 결과
- 아래의 영상과 같이 검을 휘두를때마다 VFX 및 파티클이 재생되어 더욱 풍부해진 효과들로 이뤄진 것을 볼 수 있습니다.
- entity.SwordSlashVfxAnchor의 트랜스폼 속성으로 인해 위치뿐만아니라 회전값 또한 칼을 휘두르는 시점 당시의 회전값을 사용하여 방향이 자연스러운 것을 볼 수 있습니다.
'unity game modules' 카테고리의 다른 글
[유니티] 외곽선 쉐이더 구현 및 관리 (0) | 2023.03.21 |
---|---|
[유니티] Skybox Blender (0) | 2023.03.09 |
[유니티] 발소리 구현 (2) | 2023.03.04 |
[유니티] 구글 스프레드 시트(엑셀) 연동 3 - 데이터 가져오기 (0) | 2023.03.02 |
[유니티] 구글 스프레드 시트(엑셀) 연동 2 - 유니티 연결 (0) | 2023.03.02 |