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:
@@ -44,3 +44,8 @@ MonoBehaviour:
|
||||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
- Override: 0
|
||||
Prefab: {fileID: 1723466819897086856, guid: 10d6edea82296144e9092a6d839ceb79, type: 3}
|
||||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
|
||||
@@ -1485,6 +1485,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (6)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -2466,6 +2470,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (10)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -2967,6 +2975,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (12)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -3209,6 +3221,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -3565,6 +3581,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (14)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -3962,6 +3982,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (5)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -4038,6 +4062,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -4434,6 +4462,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (4)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -5338,6 +5370,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (3)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -5997,6 +6033,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (2)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -7733,6 +7773,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (9)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -7980,6 +8024,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (7)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -8732,6 +8780,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (15)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -9548,7 +9600,7 @@ GameObject:
|
||||
- component: {fileID: 1797510779}
|
||||
- component: {fileID: 1797510778}
|
||||
- component: {fileID: 1797510782}
|
||||
m_Layer: 0
|
||||
m_Layer: 7
|
||||
m_Name: Floor
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -10178,6 +10230,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (11)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -10368,6 +10424,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (8)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -10496,6 +10556,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: SM_Bld_Floor_Tile_03 (13)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1304813211487674122, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1824081129582740912, guid: bf62c127a7934334d9b955503391f574, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 0.01
|
||||
@@ -11353,12 +11417,12 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8818883032728065057, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3}
|
||||
propertyPath: registeredClips.Array.size
|
||||
value: 8
|
||||
value: 11
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8818883032728065057, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3}
|
||||
propertyPath: 'registeredClips.Array.data[7]'
|
||||
value:
|
||||
objectReference: {fileID: 7400000, guid: c8fdea7dee0c6f04bbd27fe565071682, type: 2}
|
||||
objectReference: {fileID: 7400000, guid: 23fdb289ddd6a8647bc2afcb0d698c9c, type: 2}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
%YAML 1.1
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
@@ -18,7 +18,7 @@ MonoBehaviour:
|
||||
baseStrength: 10
|
||||
baseDexterity: 10
|
||||
baseIntelligence: 10
|
||||
baseVitality: 10
|
||||
baseVitality: 1000
|
||||
baseWisdom: 10
|
||||
baseSpirit: 10
|
||||
moveSpeed: 5
|
||||
@@ -26,4 +26,3 @@ MonoBehaviour:
|
||||
aggroRange: 10
|
||||
attackRange: 2
|
||||
attackCooldown: 1
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 94f0a76cebcac2f4fb5daf1b675fd79f, type: 3}
|
||||
m_Name: Data_Skill_Player_\uC591\uC190_\uBAA8\uC544\uBCA0\uAE30
|
||||
m_Name: "Data_Skill_Player_\uC591\uC190_\uBAA8\uC544\uBCA0\uAE30"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.SkillData
|
||||
skillName: "\uBAA8\uC544\uBCA0\uAE30"
|
||||
description:
|
||||
@@ -18,7 +18,8 @@ MonoBehaviour:
|
||||
skillRole: 1
|
||||
activationType: 1
|
||||
baseTypes: 1
|
||||
animationClips: []
|
||||
animationClips:
|
||||
- {fileID: 7400000, guid: 581f9de1a3e502f4eb95b1e922117c5c, type: 2}
|
||||
animationSpeed: 1
|
||||
legacySkillClip: {fileID: 0}
|
||||
legacyEndClip: {fileID: 0}
|
||||
|
||||
@@ -18,7 +18,8 @@ MonoBehaviour:
|
||||
skillRole: 1
|
||||
activationType: 1
|
||||
baseTypes: 1
|
||||
animationClips: []
|
||||
animationClips:
|
||||
- {fileID: 7400000, guid: d8bb58f4f1cc36440896fec5c4002e59, type: 2}
|
||||
animationSpeed: 1
|
||||
legacySkillClip: {fileID: 0}
|
||||
legacyEndClip: {fileID: 0}
|
||||
|
||||
39
Assets/_Game/Data/Skills/Data_Skill_Player_한손_마법오름.asset
Normal file
39
Assets/_Game/Data/Skills/Data_Skill_Player_한손_마법오름.asset
Normal file
@@ -0,0 +1,39 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 94f0a76cebcac2f4fb5daf1b675fd79f, type: 3}
|
||||
m_Name: "Data_Skill_Player_\uD55C\uC190_\uB9C8\uBC95\uC624\uB984"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.SkillData
|
||||
skillName: "\uB9C8\uBC95 \uC624\uB984"
|
||||
description:
|
||||
icon: {fileID: 0}
|
||||
skillRole: 1
|
||||
activationType: 1
|
||||
baseTypes: 1
|
||||
animationClips:
|
||||
- {fileID: 7400000, guid: dc5e72498abe07149b02d93a308697db, type: 2}
|
||||
animationSpeed: 1
|
||||
legacySkillClip: {fileID: 0}
|
||||
legacyEndClip: {fileID: 0}
|
||||
useRootMotion: 0
|
||||
ignoreRootMotionY: 1
|
||||
jumpToTarget: 0
|
||||
blockMovementWhileCasting: 1
|
||||
blockJumpWhileCasting: 1
|
||||
blockOtherSkillsWhileCasting: 1
|
||||
allowedWeaponTraits: 8
|
||||
cooldown: 5
|
||||
manaCost: 12
|
||||
maxGemSlotCount: 2
|
||||
castStartEffects:
|
||||
- {fileID: 11400000, guid: f7a3b2c1d4e50968abcdef0123456789, type: 2}
|
||||
effects:
|
||||
- {fileID: 11400000, guid: 1a2b3c4d5e6f7890abcdef1234567890, type: 2}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b3c4d5e6f7890abcdef1234567890ab
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -18,7 +18,8 @@ MonoBehaviour:
|
||||
skillRole: 1
|
||||
activationType: 1
|
||||
baseTypes: 1
|
||||
animationClips: []
|
||||
animationClips:
|
||||
- {fileID: 7400000, guid: 53d4b641824bfd248ab6ba10ec9c4b00, type: 2}
|
||||
animationSpeed: 1
|
||||
legacySkillClip: {fileID: 0}
|
||||
legacyEndClip: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 58efb3c775496fa40b801b21127a011e, type: 3}
|
||||
m_Name: Data_SkillEffect_Player_\uC591\uC190_\uBAA8\uC544\uBCA0\uAE30_0_\uB370\uBBF8\uC9C0
|
||||
m_Name: "Data_SkillEffect_Player_\uC591\uC190_\uBAA8\uC544\uBCA0\uAE30_0_\uB370\uBBF8\uC9C0"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.DamageEffect
|
||||
targetType: 1
|
||||
targetTeam: 0
|
||||
@@ -19,6 +19,7 @@ MonoBehaviour:
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 4
|
||||
fanOriginDistance: 0
|
||||
fanRadius: 4
|
||||
|
||||
@@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 58efb3c775496fa40b801b21127a011e, type: 3}
|
||||
m_Name: Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uBC1C\uC0AC_0_\uB370\uBBF8\uC9C0
|
||||
m_Name: "Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uBC1C\uC0AC_0_\uB370\uBBF8\uC9C0"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.DamageEffect
|
||||
targetType: 0
|
||||
targetTeam: 0
|
||||
@@ -19,6 +19,7 @@ MonoBehaviour:
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 3
|
||||
fanOriginDistance: 1
|
||||
fanRadius: 3
|
||||
|
||||
@@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a3139ddf07cfe324fa692a88cd565e24, type: 3}
|
||||
m_Name: Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uBC1C\uC0AC_1_\uC2A4\uD3F0
|
||||
m_Name: "Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uBC1C\uC0AC_1_\uC2A4\uD3F0"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.SpawnEffect
|
||||
targetType: 0
|
||||
targetTeam: 0
|
||||
@@ -19,6 +19,7 @@ MonoBehaviour:
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 3
|
||||
fanOriginDistance: 1
|
||||
fanRadius: 3
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 58efb3c775496fa40b801b21127a011e, type: 3}
|
||||
m_Name: "Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uC624\uB984_0_\uB370\uBBF8\uC9C0"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.DamageEffect
|
||||
targetType: 1
|
||||
targetTeam: 0
|
||||
areaCenter: 2
|
||||
areaShape: 0
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 5
|
||||
fanOriginDistance: 0
|
||||
fanRadius: 3
|
||||
fanHalfAngle: 45
|
||||
baseDamage: 20
|
||||
damageType: 1
|
||||
statScaling: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a2b3c4d5e6f7890abcdef1234567890
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 69581e050479a094782d2ca9eb142fe4, type: 3}
|
||||
m_Name: "Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uC624\uB984_1_VFX"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.VfxEffect
|
||||
targetType: 0
|
||||
targetTeam: 0
|
||||
areaCenter: 0
|
||||
areaShape: 0
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 3
|
||||
fanOriginDistance: 1
|
||||
fanRadius: 3
|
||||
fanHalfAngle: 45
|
||||
vfxPrefab: {fileID: 1559779302510298, guid: 5d27eaf58f7dd214db0ed07333875450, type: 3}
|
||||
spawnLocation: 3
|
||||
offset: {x: 0, y: 0.1, z: 0}
|
||||
lifetime: 2
|
||||
parentToCaster: 0
|
||||
scaleMultiplier: 3
|
||||
autoPlay: 1
|
||||
loop: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7a3b2c1d4e50968abcdef0123456789
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -10,7 +10,7 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 58efb3c775496fa40b801b21127a011e, type: 3}
|
||||
m_Name: Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uD754\uB450\uB824\uAE30_0_\uB370\uBBF8\uC9C0
|
||||
m_Name: "Data_SkillEffect_Player_\uD55C\uC190_\uB9C8\uBC95\uD718\uB450\uB974\uAE30_0_\uB370\uBBF8\uC9C0"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.DamageEffect
|
||||
targetType: 1
|
||||
targetTeam: 0
|
||||
@@ -19,6 +19,7 @@ MonoBehaviour:
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
includeCasterInArea: 0
|
||||
areaRadius: 3
|
||||
fanOriginDistance: 0
|
||||
fanRadius: 3
|
||||
|
||||
32
Assets/_Game/Data/Weapons/Data_Weapon_완드.asset
Normal file
32
Assets/_Game/Data/Weapons/Data_Weapon_완드.asset
Normal file
@@ -0,0 +1,32 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52134ecd4c816f64888d34b2163e7af1, type: 3}
|
||||
m_Name: "Data_Weapon_\uC644\uB4DC"
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.Weapons.WeaponData
|
||||
weaponName: "\uC644\uB4DC"
|
||||
description:
|
||||
icon: {fileID: 21300000, guid: 70e07ab1b9f326b4bae30fe839d609ea, type: 3}
|
||||
weaponTrait: 9
|
||||
weaponSlot: 0
|
||||
weaponPrefab: {fileID: 1723466819897086856, guid: 10d6edea82296144e9092a6d839ceb79, type: 3}
|
||||
positionOffset: {x: 0, y: 0, z: 0}
|
||||
rotationOffset: {x: 0, y: 0, z: 0}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
strengthBonus: 0
|
||||
dexterityBonus: 0
|
||||
intelligenceBonus: 0
|
||||
vitalityBonus: 0
|
||||
wisdomBonus: 0
|
||||
spiritBonus: 0
|
||||
damageMultiplier: 1
|
||||
rangeMultiplier: 1
|
||||
manaCostMultiplier: 1
|
||||
8
Assets/_Game/Data/Weapons/Data_Weapon_완드.asset.meta
Normal file
8
Assets/_Game/Data/Weapons/Data_Weapon_완드.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73962a4faafaf144c85cd6fbd5208eee
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
146
Assets/_Game/Models/Model_Weapon_완드.prefab
Normal file
146
Assets/_Game/Models/Model_Weapon_완드.prefab
Normal file
@@ -0,0 +1,146 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &1957819133893439193
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -7511558181221131132, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: 'm_Materials.Array.data[0]'
|
||||
value:
|
||||
objectReference: {fileID: 2100000, guid: 3c5daeadc1128f649923562e4f21fa05, type: 2}
|
||||
- target: {fileID: 919132149155446097, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: "Model_Weapon_\uC644\uB4DC"
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 6580351274950044991}
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 2673001829014723907}
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: -5957069831907221976}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
--- !u!1 &1723466819897086856 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 8fbe33fca238e4b438c17b36142a5c76, type: 3}
|
||||
m_PrefabInstance: {fileID: 1957819133893439193}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!64 &6580351274950044991
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1723466819897086856}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 5
|
||||
m_Convex: 1
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: 2726609029788203913, guid: b2b3921eb0400ce48a9c6b1d0aa317a3, type: 2}
|
||||
--- !u!64 &2673001829014723907
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1723466819897086856}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 5
|
||||
m_Convex: 1
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: -2515574010167127856, guid: b2b3921eb0400ce48a9c6b1d0aa317a3, type: 2}
|
||||
--- !u!114 &-5957069831907221976
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1723466819897086856}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 0
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
AlwaysReplicateAsRoot: 0
|
||||
SynchronizeTransform: 1
|
||||
ActiveSceneSynchronization: 0
|
||||
SceneMigrationSynchronization: 1
|
||||
SpawnWithObservers: 1
|
||||
DontDestroyWithOwner: 0
|
||||
AutoObjectParentSync: 1
|
||||
SyncOwnerTransformWhenParented: 1
|
||||
AllowOwnerToParent: 0
|
||||
7
Assets/_Game/Models/Model_Weapon_완드.prefab.meta
Normal file
7
Assets/_Game/Models/Model_Weapon_완드.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10d6edea82296144e9092a6d839ceb79
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5059,35 +5059,35 @@ MonoBehaviour:
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
skillRegistry: {fileID: 11400000, guid: 1899abd2213d1374dac386c5c865eb16, type: 2}
|
||||
skillSlots:
|
||||
- {fileID: 11400000, guid: b7f09e0e899c8fc4bb2cc9204cc6eb4a, type: 2}
|
||||
- {fileID: 11400000, guid: b8c86399865e91144a3d6fcfddc04fd9, type: 2}
|
||||
- {fileID: 11400000, guid: 1020083ab98b8214f918fa2ab7c1a3a1, type: 2}
|
||||
- {fileID: 11400000, guid: a822c7e8c7cee5546ad594b582208e53, type: 2}
|
||||
- {fileID: 11400000, guid: 29e1ce0656471b54f84b18a773032a99, type: 2}
|
||||
- {fileID: 11400000, guid: 2ed15dca92a165046b6df17b28f64874, type: 2}
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: 11400000, guid: 2b3c4d5e6f7890abcdef1234567890ab, type: 2}
|
||||
- {fileID: 11400000, guid: a8f2a6b7c9d0e1f3a4b5c6d7e8a9f0b1, type: 2}
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- {fileID: 11400000, guid: 2ed15dca92a165046b6df17b28f64874, type: 2}
|
||||
skillLoadoutEntries:
|
||||
- baseSkill: {fileID: 11400000, guid: b7f09e0e899c8fc4bb2cc9204cc6eb4a, type: 2}
|
||||
- baseSkill: {fileID: 0}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- baseSkill: {fileID: 11400000, guid: b8c86399865e91144a3d6fcfddc04fd9, type: 2}
|
||||
- baseSkill: {fileID: 0}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- baseSkill: {fileID: 11400000, guid: 1020083ab98b8214f918fa2ab7c1a3a1, type: 2}
|
||||
- baseSkill: {fileID: 11400000, guid: 2b3c4d5e6f7890abcdef1234567890ab, type: 2}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- baseSkill: {fileID: 11400000, guid: a822c7e8c7cee5546ad594b582208e53, type: 2}
|
||||
- baseSkill: {fileID: 11400000, guid: a8f2a6b7c9d0e1f3a4b5c6d7e8a9f0b1, type: 2}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- baseSkill: {fileID: 11400000, guid: 29e1ce0656471b54f84b18a773032a99, type: 2}
|
||||
- baseSkill: {fileID: 0}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
- baseSkill: {fileID: 11400000, guid: 2ed15dca92a165046b6df17b28f64874, type: 2}
|
||||
- baseSkill: {fileID: 0}
|
||||
socketedGems:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
@@ -5107,6 +5107,11 @@ MonoBehaviour:
|
||||
lineOfSightBlockLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
groundTargetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 128
|
||||
groundTargetMaxRange: 20
|
||||
groundTargetIndicator: {fileID: 0}
|
||||
--- !u!114 &1242716222252539497
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5179,7 +5184,7 @@ MonoBehaviour:
|
||||
backName: Spine
|
||||
hipName: Hip
|
||||
twoHandedName: prop_r
|
||||
startingWeapon: {fileID: 11400000, guid: 646964ccbda84e947b97537d7f7813aa, type: 2}
|
||||
startingWeapon: {fileID: 11400000, guid: 73962a4faafaf144c85cd6fbd5208eee, type: 2}
|
||||
startingOffhandWeapon: {fileID: 0}
|
||||
registeredWeapons:
|
||||
- {fileID: 11400000, guid: 646964ccbda84e947b97537d7f7813aa, type: 2}
|
||||
|
||||
@@ -17,7 +17,7 @@ GameObject:
|
||||
- component: {fileID: 7983858810247897309}
|
||||
- component: {fileID: 238577235165339599}
|
||||
m_Layer: 0
|
||||
m_Name: Projectile_Basic
|
||||
m_Name: Prefab_Skill_ProjectileBasic
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -128,7 +128,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 897395779
|
||||
GlobalObjectIdHash: 1397402255
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
@@ -231,5 +231,7 @@ MonoBehaviour:
|
||||
lifetime: 5
|
||||
penetrate: 0
|
||||
maxPenetration: 1
|
||||
hitEffect: {fileID: 0}
|
||||
hitEffect: {fileID: 1876479836436568, guid: fe8a785dacf0f634da597527ea1b09a6, type: 3}
|
||||
hitEffectDuration: 2
|
||||
trailPrefab: {fileID: 1027031658262514, guid: add4c8cecb195fd4c89195f49353ebc9, type: 3}
|
||||
trailDuration: 0.3
|
||||
|
||||
8
Assets/_Game/Prefabs/VFX.meta
Normal file
8
Assets/_Game/Prefabs/VFX.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50eac4dcb8da52641bc316924c02fb75
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
87
Assets/_Game/Scripts/Player/GroundTargetIndicator.cs
Normal file
87
Assets/_Game/Scripts/Player/GroundTargetIndicator.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Colosseum.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// 지면 타겟팅 인디케이터.
|
||||
/// 마우스 커서 위치의 지면에 표시되는 반투명 범위 원입니다.
|
||||
/// </summary>
|
||||
public class GroundTargetIndicator : MonoBehaviour
|
||||
{
|
||||
[Header("설정")]
|
||||
[Min(0.1f)] [SerializeField] private float radius = 5f;
|
||||
[SerializeField] private Color indicatorColor = new Color(1f, 0.5f, 0f, 0.35f);
|
||||
|
||||
private GameObject indicatorObject;
|
||||
private Material indicatorMaterial;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
CreateIndicator();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void CreateIndicator()
|
||||
{
|
||||
// 얇은 실린더로 범위 원 생성
|
||||
indicatorObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||||
indicatorObject.name = "GroundTargetIndicator";
|
||||
indicatorObject.transform.SetParent(transform);
|
||||
indicatorObject.transform.localScale = new Vector3(radius * 2f, 0.02f, radius * 2f);
|
||||
|
||||
// Default 레이어(0) — 지면 레이캐스트에 걸리지 않도록 Ground 레이어와 분리
|
||||
indicatorObject.layer = 0;
|
||||
|
||||
// 콜라이더 제거 — 물리 간섭 방지
|
||||
Destroy(indicatorObject.GetComponent<Collider>());
|
||||
|
||||
// 반투명 Unlit 머티리얼
|
||||
indicatorMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
indicatorMaterial.color = indicatorColor;
|
||||
indicatorObject.GetComponent<MeshRenderer>().material = indicatorMaterial;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인디케이터를 표시합니다.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
if (indicatorObject != null)
|
||||
indicatorObject.SetActive(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인디케이터를 숨깁니다.
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
if (indicatorObject != null)
|
||||
indicatorObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인디케이터 위치를 갱신합니다.
|
||||
/// </summary>
|
||||
public void UpdatePosition(Vector3 groundPosition)
|
||||
{
|
||||
if (indicatorObject != null)
|
||||
indicatorObject.transform.position = groundPosition + Vector3.up * 0.05f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인디케이터 반경을 변경합니다.
|
||||
/// </summary>
|
||||
public void SetRadius(float newRadius)
|
||||
{
|
||||
radius = newRadius;
|
||||
if (indicatorObject != null)
|
||||
indicatorObject.transform.localScale = new Vector3(radius * 2f, 0.02f, radius * 2f);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (indicatorMaterial != null)
|
||||
Destroy(indicatorMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18816e6a80579d84baf9ab4ef148e9f3
|
||||
@@ -97,6 +97,8 @@ namespace Colosseum.Player
|
||||
[SerializeField] private LayerMask groundTargetLayers;
|
||||
[Tooltip("지면 타겟팅 최대 사거리")]
|
||||
[Min(1f)] [SerializeField] private float groundTargetMaxRange = 20f;
|
||||
[Tooltip("지면 타겟 인디케이터 (없으면 자동 생성)")]
|
||||
[SerializeField] private GroundTargetIndicator groundTargetIndicator;
|
||||
|
||||
private InputSystem_Actions inputActions;
|
||||
private bool gameplayInputEnabled = true;
|
||||
@@ -458,7 +460,7 @@ namespace Colosseum.Player
|
||||
/// 서버에 스킬 실행 요청
|
||||
/// </summary>
|
||||
[Rpc(SendTo.Server)]
|
||||
private void RequestSkillExecutionRpc(int slotIndex, ulong targetNetworkObjectId = 0, Vector3 groundTargetPosition = default)
|
||||
private void RequestSkillExecutionRpc(int slotIndex, ulong targetNetworkObjectId = 0, Vector3 groundTargetPosition = default, bool hasGroundTarget = false)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
|
||||
return;
|
||||
@@ -491,7 +493,7 @@ namespace Colosseum.Player
|
||||
}
|
||||
|
||||
// 지면 타겟 사거리 검증
|
||||
if (groundTargetPosition != default)
|
||||
if (hasGroundTarget)
|
||||
{
|
||||
float distance = Vector3.Distance(transform.position, groundTargetPosition);
|
||||
if (distance > groundTargetMaxRange)
|
||||
@@ -508,14 +510,14 @@ namespace Colosseum.Player
|
||||
}
|
||||
|
||||
// 모든 클라이언트에 스킬 실행 전파
|
||||
BroadcastSkillExecutionRpc(slotIndex, targetNetworkObjectId, groundTargetPosition);
|
||||
BroadcastSkillExecutionRpc(slotIndex, targetNetworkObjectId, groundTargetPosition, hasGroundTarget);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 클라이언트에 스킬 실행 전파
|
||||
/// </summary>
|
||||
[Rpc(SendTo.ClientsAndHost)]
|
||||
private void BroadcastSkillExecutionRpc(int slotIndex, ulong targetNetworkObjectId = 0, Vector3 groundTargetPosition = default)
|
||||
private void BroadcastSkillExecutionRpc(int slotIndex, ulong targetNetworkObjectId = 0, Vector3 groundTargetPosition = default, bool hasGroundTarget = false)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
|
||||
return;
|
||||
@@ -528,12 +530,13 @@ namespace Colosseum.Player
|
||||
GameObject targetOverride = ResolveTargetFromNetworkId(targetNetworkObjectId);
|
||||
|
||||
// 모든 클라이언트에서 스킬 실행 (애니메이션 포함)
|
||||
if (groundTargetPosition != default)
|
||||
if (hasGroundTarget)
|
||||
{
|
||||
skillController.ExecuteSkill(loadoutEntry, targetOverride, groundTargetPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[GroundTarget] Broadcast: hasGroundTarget=false (일반 시전)");
|
||||
skillController.ExecuteSkill(loadoutEntry, targetOverride);
|
||||
}
|
||||
}
|
||||
@@ -869,6 +872,14 @@ namespace Colosseum.Player
|
||||
{
|
||||
actionState = GetOrCreateActionState();
|
||||
}
|
||||
|
||||
// 인디케이터가 없으면 자동 생성
|
||||
if (groundTargetIndicator == null)
|
||||
{
|
||||
groundTargetIndicator = GetComponent<GroundTargetIndicator>();
|
||||
if (groundTargetIndicator == null)
|
||||
groundTargetIndicator = gameObject.AddComponent<GroundTargetIndicator>();
|
||||
}
|
||||
}
|
||||
|
||||
#region 지면 타게팅 (Ground Target)
|
||||
@@ -912,6 +923,10 @@ namespace Colosseum.Player
|
||||
{
|
||||
currentTargetingMode = TargetingMode.GroundTarget;
|
||||
pendingGroundTargetSlotIndex = slotIndex;
|
||||
|
||||
if (groundTargetIndicator != null)
|
||||
groundTargetIndicator.Show();
|
||||
|
||||
Debug.Log($"[GroundTarget] 타겟팅 모드 진입: 슬롯 {slotIndex}");
|
||||
}
|
||||
|
||||
@@ -925,6 +940,9 @@ namespace Colosseum.Player
|
||||
|
||||
currentTargetingMode = TargetingMode.None;
|
||||
pendingGroundTargetSlotIndex = -1;
|
||||
|
||||
if (groundTargetIndicator != null)
|
||||
groundTargetIndicator.Hide();
|
||||
Debug.Log("[GroundTarget] 타겟팅 모드 취소");
|
||||
}
|
||||
|
||||
@@ -948,7 +966,7 @@ namespace Colosseum.Player
|
||||
return false;
|
||||
}
|
||||
|
||||
Ray ray = mainCamera.ScreenPointToRay(new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, 0f));
|
||||
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, groundTargetMaxRange, groundTargetLayers))
|
||||
return false;
|
||||
@@ -975,6 +993,9 @@ namespace Colosseum.Player
|
||||
currentTargetingMode = TargetingMode.None;
|
||||
pendingGroundTargetSlotIndex = -1;
|
||||
|
||||
if (groundTargetIndicator != null)
|
||||
groundTargetIndicator.Hide();
|
||||
|
||||
// 캐릭터를 타겟 방향으로 회전
|
||||
Vector3 flatTargetPos = new Vector3(groundPosition.x, transform.position.y, groundPosition.z);
|
||||
if ((flatTargetPos - transform.position).sqrMagnitude > 0.01f)
|
||||
@@ -983,7 +1004,7 @@ namespace Colosseum.Player
|
||||
}
|
||||
|
||||
// 서버에 스킬 실행 요청
|
||||
RequestSkillExecutionRpc(slotIndex, 0, groundPosition);
|
||||
RequestSkillExecutionRpc(slotIndex, 0, groundPosition, true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -991,6 +1012,12 @@ namespace Colosseum.Player
|
||||
if (currentTargetingMode != TargetingMode.GroundTarget)
|
||||
return;
|
||||
|
||||
// 인디케이터 위치 실시간 갱신
|
||||
if (groundTargetIndicator != null && RaycastForGroundPosition(out Vector3 currentPos))
|
||||
{
|
||||
groundTargetIndicator.UpdatePosition(currentPos);
|
||||
}
|
||||
|
||||
// 좌클릭: 지면 타겟 확정
|
||||
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
|
||||
{
|
||||
@@ -1029,7 +1056,7 @@ namespace Colosseum.Player
|
||||
return null;
|
||||
}
|
||||
|
||||
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
|
||||
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
float maxDistance = allyTargetMaxRange > 0f ? allyTargetMaxRange : Mathf.Infinity;
|
||||
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, maxDistance, allyDetectionLayers))
|
||||
|
||||
122
Assets/_Game/Scripts/Skills/Effects/VfxEffect.cs
Normal file
122
Assets/_Game/Scripts/Skills/Effects/VfxEffect.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Colosseum.Skills.Effects
|
||||
{
|
||||
/// <summary>
|
||||
/// VFX 생성 효과.
|
||||
/// 지정된 위치에 파티클 프리팹을 생성하고, 생명주기 및 재생 옵션을 제어합니다.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "VfxEffect", menuName = "Colosseum/Skills/Effects/VFX")]
|
||||
public class VfxEffect : SkillEffect
|
||||
{
|
||||
[Header("VFX 설정")]
|
||||
[Tooltip("생성할 VFX 프리팹")]
|
||||
[SerializeField] private GameObject vfxPrefab;
|
||||
|
||||
[Header("위치 설정")]
|
||||
[Tooltip("VFX 생성 위치: Caster=시전자, CasterForward=시전자 정면, Target=대상 위치, GroundPoint=지면 타겟 위치")]
|
||||
[SerializeField] private VfxSpawnLocation spawnLocation = VfxSpawnLocation.Caster;
|
||||
[Tooltip("위치 오프셋")]
|
||||
[SerializeField] private Vector3 offset = Vector3.zero;
|
||||
|
||||
[Header("생명주기")]
|
||||
[Tooltip("VFX 자동 파괴 시간 (0이면 파괴하지 않음)")]
|
||||
[Min(0f)] [SerializeField] private float lifetime = 2f;
|
||||
[Tooltip("시전자에게 부모 설정 여부")]
|
||||
[SerializeField] private bool parentToCaster = false;
|
||||
[Tooltip("VFX 크기 배율")]
|
||||
[Min(0.01f)] [SerializeField] private float scaleMultiplier = 1f;
|
||||
|
||||
[Header("파티클 설정")]
|
||||
[Tooltip("ParticleSystem 자동 재생 여부 (false면 스폰만 하고 외부에서 제어)")]
|
||||
[SerializeField] private bool autoPlay = true;
|
||||
[Tooltip("ParticleSystem 루핑 여부")]
|
||||
[SerializeField] private bool loop = false;
|
||||
|
||||
/// <summary>
|
||||
/// VFX 효과는 순수 시각 효과이므로 모든 클라이언트에서 로컬 실행됩니다.
|
||||
/// </summary>
|
||||
public override bool IsVisualOnly => true;
|
||||
|
||||
private Vector3? groundPosition;
|
||||
|
||||
/// <summary>
|
||||
/// 지면 타겟 위치를 캡처하여 ApplyEffect에서 사용할 수 있도록 합니다.
|
||||
/// </summary>
|
||||
public override void ExecuteOnCast(GameObject caster, GameObject targetOverride = null, Vector3? groundPosition = null)
|
||||
{
|
||||
this.groundPosition = groundPosition;
|
||||
base.ExecuteOnCast(caster, targetOverride, groundPosition);
|
||||
this.groundPosition = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VFX 프리팹을 생성하고 파티클을 재생합니다.
|
||||
/// </summary>
|
||||
protected override void ApplyEffect(GameObject caster, GameObject target)
|
||||
{
|
||||
if (vfxPrefab == null || caster == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
Vector3 spawnPos = GetSpawnPosition(caster, target);
|
||||
Quaternion spawnRot = caster.transform.rotation;
|
||||
Transform parent = parentToCaster ? caster.transform : null;
|
||||
|
||||
// 비제네릭 Instantiate로 캐스팅 예외 방지
|
||||
GameObject instance = (GameObject)Object.Instantiate(vfxPrefab, spawnPos + offset, spawnRot, parent);
|
||||
|
||||
instance.transform.localScale *= scaleMultiplier;
|
||||
|
||||
if (parentToCaster)
|
||||
instance.transform.localPosition = offset;
|
||||
|
||||
if (autoPlay)
|
||||
{
|
||||
ParticleSystem[] particleSystems = instance.GetComponentsInChildren<ParticleSystem>(true);
|
||||
foreach (var ps in particleSystems)
|
||||
{
|
||||
var main = ps.main;
|
||||
main.loop = loop;
|
||||
|
||||
if (loop)
|
||||
main.stopAction = ParticleSystemStopAction.None;
|
||||
|
||||
ps.Clear(true);
|
||||
ps.Play(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (lifetime > 0f)
|
||||
Object.Destroy(instance, lifetime);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"[VfxEffect] VFX 생성 실패: {e.Message}\n{e.StackTrace}", this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// spawnLocation에 따른 VFX 생성 위치를 계산합니다.
|
||||
/// </summary>
|
||||
private Vector3 GetSpawnPosition(GameObject caster, GameObject target)
|
||||
{
|
||||
return spawnLocation switch
|
||||
{
|
||||
VfxSpawnLocation.Caster => caster.transform.position,
|
||||
VfxSpawnLocation.CasterForward => caster.transform.position + caster.transform.forward * 2f,
|
||||
VfxSpawnLocation.Target => target != null ? target.transform.position : caster.transform.position,
|
||||
VfxSpawnLocation.GroundPoint => groundPosition ?? caster.transform.position,
|
||||
_ => caster.transform.position
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum VfxSpawnLocation
|
||||
{
|
||||
Caster,
|
||||
CasterForward,
|
||||
Target,
|
||||
GroundPoint
|
||||
}
|
||||
}
|
||||
2
Assets/_Game/Scripts/Skills/Effects/VfxEffect.cs.meta
Normal file
2
Assets/_Game/Scripts/Skills/Effects/VfxEffect.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69581e050479a094782d2ca9eb142fe4
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,11 +22,18 @@ namespace Colosseum.Skills
|
||||
[SerializeField] private GameObject hitEffect;
|
||||
[SerializeField] private float hitEffectDuration = 2f;
|
||||
|
||||
[Header("트레일 이펙트")]
|
||||
[Tooltip("투사체 트레일 프리팹 (TrailRenderer가 포함된 프리팹). 미설정 시 트레일 없음.")]
|
||||
[SerializeField] private GameObject trailPrefab;
|
||||
[Tooltip("투사체 파괴 후 트레일이 남는 시간 (초)")]
|
||||
[Min(0.1f)] [SerializeField] private float trailDuration = 0.3f;
|
||||
|
||||
private GameObject caster;
|
||||
private SkillEffect sourceEffect;
|
||||
private int penetrationCount;
|
||||
private Rigidbody rb;
|
||||
private bool initialized;
|
||||
private GameObject trailInstance;
|
||||
|
||||
/// <summary>
|
||||
/// 투사체 초기화
|
||||
@@ -51,6 +58,17 @@ namespace Colosseum.Skills
|
||||
Physics.IgnoreCollision(mc, cc);
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// 트레일 생성 (서버/클라이언트 양쪽에서 실행)
|
||||
if (trailPrefab != null)
|
||||
{
|
||||
trailInstance = Instantiate(trailPrefab, transform);
|
||||
trailInstance.transform.localPosition = Vector3.zero;
|
||||
trailInstance.transform.localRotation = Quaternion.identity;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 서버에서만 수명 관리
|
||||
@@ -75,11 +93,12 @@ namespace Colosseum.Skills
|
||||
if (!sourceEffect.IsValidTarget(caster, other.gameObject))
|
||||
return;
|
||||
|
||||
// 충돌 이펙트 (서버에서 스폰 → 클라이언트에도 표시되려면 NetworkObject여야 함)
|
||||
// 충돌 이펙트 (서버 + 클라이언트 모두 표시)
|
||||
if (hitEffect != null)
|
||||
{
|
||||
var effect = Instantiate(hitEffect, transform.position, transform.rotation);
|
||||
Destroy(effect, hitEffectDuration);
|
||||
HitEffectClientRpc(transform.position, transform.rotation.eulerAngles);
|
||||
}
|
||||
|
||||
// 효과 적용
|
||||
@@ -96,6 +115,15 @@ namespace Colosseum.Skills
|
||||
private void ServerDespawn()
|
||||
{
|
||||
if (!IsServer || !IsSpawned) return;
|
||||
|
||||
// 트레일을 월드에 남겨서 자연스럽게 사라지게 함
|
||||
if (trailInstance != null)
|
||||
{
|
||||
trailInstance.transform.SetParent(null);
|
||||
Destroy(trailInstance, trailDuration);
|
||||
trailInstance = null;
|
||||
}
|
||||
|
||||
NetworkObject.Despawn(true);
|
||||
}
|
||||
|
||||
@@ -103,5 +131,18 @@ namespace Colosseum.Skills
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(direction.normalized);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 클라이언트에 충돌 이펙트 표시
|
||||
/// </summary>
|
||||
[Rpc(SendTo.NotServer)]
|
||||
private void HitEffectClientRpc(Vector3 position, Vector3 eulerAngles)
|
||||
{
|
||||
if (hitEffect != null)
|
||||
{
|
||||
var effect = Instantiate(hitEffect, position, Quaternion.Euler(eulerAngles));
|
||||
Destroy(effect, hitEffectDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ TagManager:
|
||||
- Water
|
||||
- UI
|
||||
- Enemy
|
||||
-
|
||||
- Ground
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user