feat: VFX 인프라 구축 및 Ground Target 시스템 구현
- VfxEffect 스킬 이펙트 클래스 추가 (일회성 VFX 스폰, 위치/스케일/파티클 제어) - SkillEffect.IsVisualOnly 프로퍼티 추가로 서버 가드 없이 모든 클라이언트에서 VFX 로컬 실행 - SkillProjectile 트레일 VFX 지원 (OnNetworkSpawn에서 양쪽 생성, despawn 시 월드 분리) - SkillProjectile HitEffectClientRpc 추가로 충돌 이펙트 클라이언트 동기화 - Ground Target 시스템: 타겟팅 모드 상태머신, 인디케이터, 지면 위치 RPC 전달 - 마법 오름 Ground Target 스킬 에셋 및 VfxEffect 에셋 추가 - 마법 오름 애니메이션 클립 추가 - Ground layer (Layer 7) 추가 - ProjectileBasic에 trailPrefab/hitEffect 필드 추가 - Prefabs/VFX/ 폴더 생성
This commit is contained in:
@@ -74,6 +74,7 @@ namespace Colosseum.Skills
|
||||
private int currentRepeatCount = 1;
|
||||
private int currentIterationIndex = 0;
|
||||
private GameObject currentTargetOverride;
|
||||
private Vector3? currentGroundTargetPosition;
|
||||
|
||||
// 쿨타임 추적
|
||||
private Dictionary<SkillData, float> cooldownTracker = new Dictionary<SkillData, float>();
|
||||
@@ -270,6 +271,17 @@ namespace Colosseum.Skills
|
||||
return ExecuteSkillInternal(loadoutEntry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지면 타겟 위치와 함께 스킬 시전.
|
||||
/// Ground Target 스킬에서 사용합니다.
|
||||
/// </summary>
|
||||
public bool ExecuteSkill(SkillLoadoutEntry loadoutEntry, GameObject targetOverride, Vector3 groundTargetPosition)
|
||||
{
|
||||
currentTargetOverride = targetOverride;
|
||||
currentGroundTargetPosition = groundTargetPosition;
|
||||
return ExecuteSkillInternal(loadoutEntry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스킬 시전 공통 로직
|
||||
/// </summary>
|
||||
@@ -328,17 +340,29 @@ namespace Colosseum.Skills
|
||||
if (currentSkill == null)
|
||||
return;
|
||||
|
||||
// VFX는 모든 클라이언트에서 로컬 생성 (서버 가드 무시)
|
||||
for (int i = 0; i < currentCastStartEffects.Count; i++)
|
||||
{
|
||||
SkillEffect effect = currentCastStartEffects[i];
|
||||
if (effect != null && effect.IsVisualOnly)
|
||||
{
|
||||
if (debugMode) Debug.Log($"[Skill] Cast start VFX: {effect.name} (index {i})");
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 게임플레이 효과는 서버에서만 실행
|
||||
if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < currentCastStartEffects.Count; i++)
|
||||
{
|
||||
SkillEffect effect = currentCastStartEffects[i];
|
||||
if (effect == null)
|
||||
if (effect == null || effect.IsVisualOnly)
|
||||
continue;
|
||||
|
||||
if (debugMode) Debug.Log($"[Skill] Cast start effect: {effect.name} (index {i})");
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride);
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
|
||||
if (currentCastStartAbnormalities.Count <= 0)
|
||||
@@ -371,23 +395,35 @@ namespace Colosseum.Skills
|
||||
if (currentSkill == null || currentTriggeredEffects.Count == 0)
|
||||
return;
|
||||
|
||||
if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer)
|
||||
return;
|
||||
|
||||
if (currentSkill.SkillClip != null && currentSkill.SkillClip.events != null && currentSkill.SkillClip.events.Length > 0)
|
||||
return;
|
||||
|
||||
if (!currentTriggeredEffects.TryGetValue(0, out List<SkillEffect> effectsAtZero))
|
||||
return;
|
||||
|
||||
// VFX는 모든 클라이언트에서 로컬 생성 (서버 가드 무시)
|
||||
for (int i = 0; i < effectsAtZero.Count; i++)
|
||||
{
|
||||
SkillEffect effect = effectsAtZero[i];
|
||||
if (effect == null || effect.TargetType != TargetType.Self)
|
||||
if (effect != null && effect.IsVisualOnly && effect.TargetType == TargetType.Self)
|
||||
{
|
||||
if (debugMode) Debug.Log($"[Skill] Immediate self VFX: {effect.name} (index {i})");
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 게임플레이 효과는 서버에서만 실행
|
||||
if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < effectsAtZero.Count; i++)
|
||||
{
|
||||
SkillEffect effect = effectsAtZero[i];
|
||||
if (effect == null || effect.TargetType != TargetType.Self || effect.IsVisualOnly)
|
||||
continue;
|
||||
|
||||
if (debugMode) Debug.Log($"[Skill] Immediate self effect: {effect.name} (index {i})");
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride);
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,8 +597,6 @@ namespace Colosseum.Skills
|
||||
/// </summary>
|
||||
public void OnEffect(int index)
|
||||
{
|
||||
if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer) return;
|
||||
|
||||
if (currentSkill == null)
|
||||
{
|
||||
if (debugMode) Debug.LogWarning("[Effect] No skill executing");
|
||||
@@ -583,10 +617,24 @@ namespace Colosseum.Skills
|
||||
return;
|
||||
}
|
||||
|
||||
// VFX는 모든 클라이언트에서 로컬 생성 (서버 가드 무시)
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
SkillEffect effect = effects[i];
|
||||
if (effect == null)
|
||||
if (effect != null && effect.IsVisualOnly)
|
||||
{
|
||||
if (debugMode) Debug.Log($"[Effect] VFX: {effect.name} (index {index})");
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 게임플레이 효과는 서버에서만 실행
|
||||
if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer) return;
|
||||
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
SkillEffect effect = effects[i];
|
||||
if (effect == null || effect.IsVisualOnly)
|
||||
continue;
|
||||
|
||||
if (debugMode) Debug.Log($"[Effect] {effect.name} (index {index})");
|
||||
@@ -594,13 +642,11 @@ namespace Colosseum.Skills
|
||||
// 공격 범위 시각화
|
||||
if (showAreaDebug)
|
||||
{
|
||||
effect.DrawDebugRange(gameObject, debugDrawDuration);
|
||||
effect.DrawDebugRange(gameObject, debugDrawDuration, currentGroundTargetPosition);
|
||||
}
|
||||
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride);
|
||||
effect.ExecuteOnCast(gameObject, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
|
||||
ApplyTriggeredAbnormalities(index, effects);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -684,6 +730,7 @@ namespace Colosseum.Skills
|
||||
currentTriggeredAbnormalities.Clear();
|
||||
currentTriggeredTargetsBuffer.Clear();
|
||||
currentTargetOverride = null;
|
||||
currentGroundTargetPosition = null;
|
||||
currentClipSequenceIndex = 0;
|
||||
currentRepeatCount = 1;
|
||||
currentIterationIndex = 0;
|
||||
@@ -709,7 +756,7 @@ namespace Colosseum.Skills
|
||||
if (effect == null || effect.TargetType == TargetType.Self)
|
||||
continue;
|
||||
|
||||
effect.CollectTargets(gameObject, currentTriggeredTargetsBuffer, currentTargetOverride);
|
||||
effect.CollectTargets(gameObject, currentTriggeredTargetsBuffer, currentTargetOverride, currentGroundTargetPosition);
|
||||
}
|
||||
|
||||
if (currentTriggeredTargetsBuffer.Count == 0)
|
||||
|
||||
Reference in New Issue
Block a user