user d8cdf1a4d2 ADD: 의상 기반 변신 연출 + Piloto Studio VFX 에셋
- AvatarOutfitController: 의상 변경 시 NiloToon renderCharacter 토글 + VFX/SFX/컬러 플래시 연출
- TransformEffectPreset ScriptableObject 로 프리셋 공유
- 아바타별 isTransforming 플래그로 동시 변신 지원
- 의상 리스트 순서 변경 (▲▼) 기능
- Piloto Studio 파티클 번들 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 02:21:30 +09:00

93 lines
3.0 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
namespace PilotoStudio
{
[ExecuteAlways]
public class ParticleHandler : MonoBehaviour
{
public GameObject castParticle;
public float castFXDuration;
public GameObject loopingParticle;
public float loopDuration;
public GameObject endParticle;
private ParticleSystem castParticleSystem;
private ParticleSystem loopingParticleSystem;
private ParticleSystem endParticleSystem;
float startEmission;
private void OnEnable()
{
castParticleSystem = castParticle.GetComponent<ParticleSystem>();
loopingParticleSystem = loopingParticle.GetComponent<ParticleSystem>();
endParticleSystem = endParticle.GetComponent<ParticleSystem>();
if (!castParticleSystem || !loopingParticleSystem || !endParticleSystem)
{
Debug.LogError("ParticleHandler: Missing particle systems. Ensure they are referenced correctly.");
return;
}
Cast();
}
public void Cast()
{
StartCoroutine(Flow());
}
IEnumerator Flow()
{
PlayParticles(castParticleSystem, castFXDuration);
yield return new WaitForSeconds(castFXDuration);
PlayParticles(loopingParticleSystem, loopDuration);
yield return new WaitForSeconds(loopDuration);
PlayParticles(endParticleSystem);
yield return WaitUntilParticleSystemStops(endParticleSystem);
}
private IEnumerator WaitUntilParticleSystemStops(ParticleSystem particleSystem)
{
while (particleSystem.IsAlive(true))
{
yield return null;
}
}
private void PlayParticles(ParticleSystem particleSystem, float duration = 0f)
{
particleSystem.gameObject.SetActive(true);
var particleSystemMain = particleSystem.emission;
if (startEmission == 0)
startEmission = particleSystemMain.rateOverTimeMultiplier;
if (particleSystem.main.startLifetime.constantMax == Mathf.Infinity)
StartCoroutine(WaitUntilParticleSystemStops(particleSystem));
else
particleSystemMain.rateOverTimeMultiplier = startEmission;
particleSystem.Play();
if (duration > 0f && particleSystem.main.startLifetime.constantMax != Mathf.Infinity)
{
StartCoroutine(StopParticleAfterTime(particleSystem, duration));
}
}
IEnumerator StopParticleAfterTime(ParticleSystem particleSystem, float duration)
{
yield return new WaitForSeconds(duration);
var particleSystemMain = particleSystem.emission;
particleSystemMain.rateOverTimeMultiplier = 0;
// particleSystem.gameObject.SetActive(false);
}
}
}