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:
@@ -45,14 +45,21 @@ namespace Colosseum.Skills
|
||||
public float FanRadius => fanRadius;
|
||||
public float FanHalfAngle => fanHalfAngle;
|
||||
public bool IncludeCasterInArea => includeCasterInArea;
|
||||
public AreaCenterType AreaCenter => areaCenter;
|
||||
|
||||
/// <summary>
|
||||
/// 이 효과가 순수 시각 효과인지 확인합니다.
|
||||
/// true이면 서버 가드를 무시하고 모든 클라이언트에서 로컬 실행됩니다.
|
||||
/// </summary>
|
||||
public virtual bool IsVisualOnly => false;
|
||||
|
||||
/// <summary>
|
||||
/// 스킬 시전 시 호출
|
||||
/// </summary>
|
||||
public void ExecuteOnCast(GameObject caster, GameObject targetOverride = null)
|
||||
public virtual void ExecuteOnCast(GameObject caster, GameObject targetOverride = null, Vector3? groundPosition = null)
|
||||
{
|
||||
List<GameObject> targets = new List<GameObject>();
|
||||
CollectTargets(caster, targets, targetOverride);
|
||||
CollectTargets(caster, targets, targetOverride, groundPosition);
|
||||
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
@@ -64,7 +71,7 @@ namespace Colosseum.Skills
|
||||
/// 현재 효과가 영향을 줄 대상 목록을 수집합니다.
|
||||
/// 젬의 적중 이상상태 적용 등에서 동일한 타겟 해석을 재사용하기 위한 경로입니다.
|
||||
/// </summary>
|
||||
public void CollectTargets(GameObject caster, List<GameObject> destination, GameObject targetOverride = null)
|
||||
public void CollectTargets(GameObject caster, List<GameObject> destination, GameObject targetOverride = null, Vector3? groundPosition = null)
|
||||
{
|
||||
if (caster == null || destination == null)
|
||||
return;
|
||||
@@ -76,7 +83,7 @@ namespace Colosseum.Skills
|
||||
break;
|
||||
|
||||
case TargetType.Area:
|
||||
CollectAreaTargets(caster, destination);
|
||||
CollectAreaTargets(caster, destination, groundPosition);
|
||||
break;
|
||||
|
||||
case TargetType.SingleAlly:
|
||||
@@ -135,9 +142,9 @@ namespace Colosseum.Skills
|
||||
};
|
||||
}
|
||||
|
||||
private void CollectAreaTargets(GameObject caster, List<GameObject> destination)
|
||||
private void CollectAreaTargets(GameObject caster, List<GameObject> destination, Vector3? groundPosition = null)
|
||||
{
|
||||
Vector3 center = GetAreaCenter(caster);
|
||||
Vector3 center = GetAreaCenter(caster, groundPosition);
|
||||
Collider[] hits = Physics.OverlapSphere(center, Mathf.Max(areaRadius, fanRadius), targetLayers);
|
||||
foreach (var hit in hits)
|
||||
{
|
||||
@@ -189,7 +196,7 @@ namespace Colosseum.Skills
|
||||
return angle <= fanHalfAngle;
|
||||
}
|
||||
|
||||
private Vector3 GetAreaCenter(GameObject caster)
|
||||
private Vector3 GetAreaCenter(GameObject caster, Vector3? groundPosition = null)
|
||||
{
|
||||
if (caster == null) return Vector3.zero;
|
||||
|
||||
@@ -197,6 +204,7 @@ namespace Colosseum.Skills
|
||||
{
|
||||
AreaCenterType.Caster => caster.transform.position,
|
||||
AreaCenterType.CasterForward => caster.transform.position + caster.transform.forward * areaRadius,
|
||||
AreaCenterType.GroundPoint => groundPosition ?? caster.transform.position,
|
||||
_ => caster.transform.position
|
||||
};
|
||||
}
|
||||
@@ -205,7 +213,7 @@ namespace Colosseum.Skills
|
||||
/// <summary>
|
||||
/// 공격 범위 시각화 (런타임 디버그용)
|
||||
/// </summary>
|
||||
public void DrawDebugRange(GameObject caster, float duration = 1f)
|
||||
public void DrawDebugRange(GameObject caster, float duration = 1f, Vector3? groundPosition = null)
|
||||
{
|
||||
if (targetType != TargetType.Area) return;
|
||||
|
||||
@@ -214,12 +222,15 @@ namespace Colosseum.Skills
|
||||
|
||||
if (areaShape == AreaShapeType.Sphere)
|
||||
{
|
||||
Vector3 center = GetAreaCenter(caster);
|
||||
Vector3 center = GetAreaCenter(caster, groundPosition);
|
||||
DebugDrawSphere(center, areaRadius, Color.red, duration);
|
||||
}
|
||||
else if (areaShape == AreaShapeType.Fan)
|
||||
{
|
||||
DebugDrawFan(casterPos, forward, fanOriginDistance, fanRadius, fanHalfAngle, Color.red, duration);
|
||||
Vector3 center = GetAreaCenter(caster, groundPosition);
|
||||
DebugDrawFan(center, groundPosition.HasValue && areaCenter == AreaCenterType.GroundPoint
|
||||
? (center - casterPos).normalized
|
||||
: forward, fanOriginDistance, fanRadius, fanHalfAngle, Color.red, duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +307,8 @@ namespace Colosseum.Skills
|
||||
public enum AreaCenterType
|
||||
{
|
||||
Caster,
|
||||
CasterForward
|
||||
CasterForward,
|
||||
GroundPoint // 지면 지점 타겟팅 (Ground Target)
|
||||
}
|
||||
|
||||
public enum AreaShapeType
|
||||
|
||||
Reference in New Issue
Block a user