WL #979 PD 지시 3건 — ① 시위 화살 = Stylized Shoot & Hit Vol.2 FX_Shoot_Arrow 의 화살 메시 층(강철 촉 · 붉은 깃 · 정적 메시 · 납작한 면 위로) · 길이 1.0 m · 굵기 1.2 배(WLNockArrow widthMul 신설 · 근접 촬영 = 촉이 활 앞으로) ② 비수 기본 스킬 지면 흔적 끔 = Skill_BrutalSlash 의 Crater · Slash Cracks(검은 균열) · Flying(지면에 남던 어두운 조각 · 1.1 s 뒤 유일하게 보이던 층) 렌더러만 끔(중첩 프리팹 덮어쓰기 · 원본 팩 무수정 · 실측 보이는 입자 층 0) — 수리검 교체는 「Master Stylized Projectile」 팩이 프로젝트에 없어 PD 답 대기 ③ 맹약 각성 블랙홀 = 원본 밝은 이펙트 렌더러 끔(hideOriginal · 0/46) + 검은 코어(GabrielAguiar BlackHole01_Purple 사본 1.8 배) + 범위 가장자리에서 빨려 드는 어두운 줄기(반지름 = 범위) + 폭파 전 0.5 s 응축(0.15 배 · collapseTo) + 보라 폭발(WL_Impact_Explosion 보라 사본 0.8 배) — 실측 끌어당김 1.60 m/0.6 s(#978 밀기 끔 확인) · 다단 10 · 폭파 명중 1 · 콘솔 오류 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-10-24 23:42:46 +09:00
parent 129b570ec8
commit 620d26339c
12 changed files with 108675 additions and 105 deletions

View File

@ -96,6 +96,11 @@ PrefabInstance:
propertyPath: InitialModule.startColor.maxColor.r propertyPath: InitialModule.startColor.maxColor.r
value: 0.17 value: 0.17
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 5349603988218628028, guid: 8a02c4042c68dd244abad8cf394dab42,
type: 3}
propertyPath: m_Enabled
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6424247364373830703, guid: 8a02c4042c68dd244abad8cf394dab42, - target: {fileID: 6424247364373830703, guid: 8a02c4042c68dd244abad8cf394dab42,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -146,6 +151,11 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z propertyPath: m_LocalEulerAnglesHint.z
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6877057326494895805, guid: 8a02c4042c68dd244abad8cf394dab42,
type: 3}
propertyPath: m_Enabled
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6877057326494895805, guid: 8a02c4042c68dd244abad8cf394dab42, - target: {fileID: 6877057326494895805, guid: 8a02c4042c68dd244abad8cf394dab42,
type: 3} type: 3}
propertyPath: 'm_Materials.Array.data[0]' propertyPath: 'm_Materials.Array.data[0]'
@ -298,6 +308,11 @@ PrefabInstance:
propertyPath: m_Materials.Array.size propertyPath: m_Materials.Array.size
value: 1 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 199315809523895524, guid: 911d39b31e356794d971139c547d1e61,
type: 3}
propertyPath: m_Enabled
value: 0
objectReference: {fileID: 0}
- target: {fileID: 199315809523895524, guid: 911d39b31e356794d971139c547d1e61, - target: {fileID: 199315809523895524, guid: 911d39b31e356794d971139c547d1e61,
type: 3} type: 3}
propertyPath: m_Materials.Array.size propertyPath: m_Materials.Array.size

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e25d2bbee21f2ec4bb8a2de24cc2dd0c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9f8d4c8d062ad2a4ca86b3bedfab4200
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ab10618ad722f174483debd3e2330b78
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -9,6 +9,8 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 7561437168075404599} - component: {fileID: 7561437168075404599}
- component: {fileID: 5000598711597329870}
- component: {fileID: 8676850869351012184}
m_Layer: 0 m_Layer: 0
m_Name: Arrow m_Name: Arrow
m_TagString: Untagged m_TagString: Untagged
@ -24,14 +26,70 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1265659647065410780} m_GameObject: {fileID: 1265659647065410780}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalRotation: {x: -0.5, y: 0.5, z: 0.5, w: 0.5}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children: []
- {fileID: 318284294933426198}
m_Father: {fileID: 3384687383004869994} m_Father: {fileID: 3384687383004869994}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &5000598711597329870
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1265659647065410780}
m_Mesh: {fileID: -7929139438592967118, guid: 59b6e6294096bc94d9a3082a1c983de1, type: 3}
--- !u!23 &8676850869351012184
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1265659647065410780}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 1c76f8eaedd15eb4cb62be97153d2d7e, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &2286313539756212851 --- !u!1 &2286313539756212851
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -64,93 +122,3 @@ Transform:
- {fileID: 7561437168075404599} - {fileID: 7561437168075404599}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &6890858917390786345
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 318284294933426198}
- component: {fileID: 1665685135880975955}
- component: {fileID: 2144548526970463019}
m_Layer: 0
m_Name: default
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &318284294933426198
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6890858917390786345}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7561437168075404599}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &1665685135880975955
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6890858917390786345}
m_Mesh: {fileID: 4300000, guid: 72c6fc7515b706e428efc3f4b09cdd41, type: 3}
--- !u!23 &2144548526970463019
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6890858917390786345}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 7878d691a75f3824ea21373040595c51, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}

View File

@ -4,8 +4,24 @@
"pullMinDist": 0.4, "pullMinDist": 0.4,
"explodeDelay": 0.5, "explodeDelay": 0.5,
"explodeDamageMul": 5.0, "explodeDamageMul": 5.0,
"explodeFx": "WL/Impact/WL_Impact_Explosion", "explodeFx": "WL/Fx/WL_Fx_BlackHoleBurst",
"explodeFxScale": 0.5, "explodeFxScale": 0.8,
"explodeFxLife": 2.0, "explodeFxLife": 2.0,
"hideOriginal": 1,
"lifeFx": [
{
"path": "WL/Fx/WL_Fx_BlackHole",
"scale": 1.8,
"perRange": 0.0
},
{
"path": "WL/Fx/WL_Fx_BlackHoleSuck",
"scale": 1.0,
"perRange": 1.0
}
],
"lifeFxFade": 0.25,
"collapseTo": 0.15,
"note_979": "#979 PD 「블랙홀의 색상이 너무 밝아서 블랙홀 컨셉이 아닌 느낌이야. 네가 좀 더 블렉홀 처럼 색상이나 연출을 개선할 수 있을까?」 — 블랙홀 동안 원본(밝은 보라 고리 · 흰 섬광 · 번개) 렌더러 끔(hideOriginal) · 중심 = 검은 코어 WL_Fx_BlackHole(GabrielAguiar UniqueProjectilesVol_2 vfx_Projectile_BlackHole01_Purple 사본 · 검은 원판 + 보라 소용돌이 · 1.8 배) · 범위 가장자리에서 중심으로 빨려 드는 어두운 보라 줄기 WL_Fx_BlackHoleSuck(반지름 = 범위 · 0.8 s · 초당 60) · 폭파 직전 0.5 s 응축(코어 · 줄기 0.15 배까지 줄어듦 collapseTo) → 폭파 = WL_Impact_Explosion 보라 사본 WL_Fx_BlackHoleBurst 0.8 배(PM 값 = 배율 · 색 · 응축)",
"note": "#978 PD 「오브 각성 스킬이 발동되면, 해당 위치로 몬스터들이 블랙홀과 같이 빨려들어가며 다단 히트 피해를 받고, 폭파할 때 강력한 피해 1회가 발동되면 좋겠어.」 — 원본 Skill_BlackHole(수명 · 범위 · 간격 · 각성 단계 · 기절 = 원본 계산값) 넘겨받음 · 빨려 들어감 3 m/s(중심 0.4 m 까지) · 다단 = 원본 간격마다 원본 피해 · 폭파 = 0.5 s 뒤 피해 배율 5 배 1회 + 폭발 WL_Impact_Explosion 0.5 배(PM 값 = 끌어당김 속도 · 폭파 배율 · 이펙트)" "note": "#978 PD 「오브 각성 스킬이 발동되면, 해당 위치로 몬스터들이 블랙홀과 같이 빨려들어가며 다단 히트 피해를 받고, 폭파할 때 강력한 피해 1회가 발동되면 좋겠어.」 — 원본 Skill_BlackHole(수명 · 범위 · 간격 · 각성 단계 · 기절 = 원본 계산값) 넘겨받음 · 빨려 들어감 3 m/s(중심 0.4 m 까지) · 다단 = 원본 간격마다 원본 피해 · 폭파 = 0.5 s 뒤 피해 배율 5 배 1회 + 폭발 WL_Impact_Explosion 0.5 배(PM 값 = 끌어당김 속도 · 폭파 배율 · 이펙트)"
} }

View File

@ -1,15 +1,35 @@
{ {
"enabled": 1, "enabled": 1,
"classes": [ 10402 ], "classes": [
10402
],
"prefab": "WL/Fx/WL_NockArrow", "prefab": "WL/Fx/WL_NockArrow",
"lengthMeters": 0.55, "lengthMeters": 1.0,
"widthMul": 1.2,
"nockOffset": 0.0, "nockOffset": 0.0,
"rules": [ "rules": [
{ "state": "attack", "from": 0.20, "to": 0.56 }, {
{ "state": "Bow_Attack2", "from": 0.20, "to": 0.56 }, "state": "attack",
{ "state": "Bow_Attack3", "from": 0.20, "to": 0.92 }, "from": 0.2,
{ "state": "Bow_Skill4_Push", "from": 0.16, "to": 0.48 } "to": 0.56
},
{
"state": "Bow_Attack2",
"from": 0.2,
"to": 0.56
},
{
"state": "Bow_Attack3",
"from": 0.2,
"to": 0.92
},
{
"state": "Bow_Skill4_Push",
"from": 0.16,
"to": 0.48
}
], ],
"note_979": "#979 PD 「여전히 화살처럼 보이지 않아. \"Stylized Shoot & Hit Vol.2\" 에셋의 FX_Shoot_Arrow이펙트에 있는 화살을 쓰면 어떨까?」 — 화살 = FX_Shoot_Arrow 의 화살 메시 층(FX_Shoot&HItVol2_Arrow_projectile · Arrow 메시 · Mat_fx_Shoot&HitVol2_Modeling · 강철 촉 · 붉은 깃)을 정적 메시로(979_arrow.cs · 원본 팩 무수정) · 납작한 면을 위로 눕힘(roll 90 = 위 카메라에서 실처럼 보이던 것) · 길이 0.55 → 1.0 m(촉이 활 앞으로 나오게 · 0.6 · 0.8 m 는 촉이 활 손잡이에 머물고 몸통은 큰 머리 · 팔에 가림 = Play 근접 촬영) · 굵기 배율 widthMul 1.2(PM 값)",
"note_978": "#978 PD 「활의 공격 시 넣어달라고 요청한 화살이 화살처럼 보이지 않고 마치 실같아. 좀 더 화살처럼 생긴 오브젝트를 찾아봐」 — 화살 모델 = ResWork Elven Weapons Elven_Arrow_02(강철 촉 · 붉은 깃 · 폭/길이 0.137 = 이전 기본 화살 메시 0.047 의 약 3 배 · 978_nockarrow2.cs 로 WL_NockArrow 덮어씀 · 원본 무수정) · 길이 0.55 m 그대로", "note_978": "#978 PD 「활의 공격 시 넣어달라고 요청한 화살이 화살처럼 보이지 않고 마치 실같아. 좀 더 화살처럼 생긴 오브젝트를 찾아봐」 — 화살 모델 = ResWork Elven Weapons Elven_Arrow_02(강철 촉 · 붉은 깃 · 폭/길이 0.137 = 이전 기본 화살 메시 0.047 의 약 3 배 · 978_nockarrow2.cs 로 WL_NockArrow 덮어씀 · 원본 무수정) · 길이 0.55 m 그대로",
"note": "#977 PD 「활 시위를 당길 때 화살 오브젝트가 보이게 해줘.(보유중인 리소스 중 화살을 찾아볼 것)」 — 화살 = 기본 화살 투사체 Projectile_10402 의 PP_Theme_10_Arrow_003 메시 사본(WL_NockArrow) · 꼬리 = 오른손 · 촉 = 왼손(활) 쪽 · 길이 0.55 m(PM 값) · 보이는 구간 = 상태별 정규화(시위를 잡은 뒤 ~ 놓는 순간): 1 · 2타 BowShot 0.20~0.56(#967 놓는 순간 0.56) · 3타 FR_Bow3 0.20~0.92(Projectile 0.92) · 4타 Bow_Skill4_Push 0.16~0.48(Projectile 0.48 · 두 손 거리 편집 모드 실측) · 주력 · 멀티샷 모으기도 같은 attack 상태(0.30~0.56)라 함께" "note": "#977 PD 「활 시위를 당길 때 화살 오브젝트가 보이게 해줘.(보유중인 리소스 중 화살을 찾아볼 것)」 — 화살 = 기본 화살 투사체 Projectile_10402 의 PP_Theme_10_Arrow_003 메시 사본(WL_NockArrow) · 꼬리 = 오른손 · 촉 = 왼손(활) 쪽 · 길이 0.55 m(PM 값) · 보이는 구간 = 상태별 정규화(시위를 잡은 뒤 ~ 놓는 순간): 1 · 2타 BowShot 0.20~0.56(#967 놓는 순간 0.56) · 3타 FR_Bow3 0.20~0.92(Projectile 0.92) · 4타 Bow_Skill4_Push 0.16~0.48(Projectile 0.48 · 두 손 거리 편집 모드 실측) · 주력 · 멀티샷 모으기도 같은 attack 상태(0.30~0.56)라 함께"
} }

View File

@ -5,6 +5,8 @@
// ■ 원본(Skill_BlackHole.Co_BlackHole): 수명 동안 간격마다 범위 안 적 Attract + 피해 → 0.5 초 뒤 같은 피해 1회(+ 각성 2단계 기절) // ■ 원본(Skill_BlackHole.Co_BlackHole): 수명 동안 간격마다 범위 안 적 Attract + 피해 → 0.5 초 뒤 같은 피해 1회(+ 각성 2단계 기절)
// ■ WL — 원본 Set 끝 훅 1줄(Take)이 넘겨받는다: 매 프레임 범위 안 적을 중심 쪽으로 pullSpeed(m/s)로 끌어당김(pullMinDist 까지 · 길찾기 에이전트면 Move) · // ■ WL — 원본 Set 끝 훅 1줄(Take)이 넘겨받는다: 매 프레임 범위 안 적을 중심 쪽으로 pullSpeed(m/s)로 끌어당김(pullMinDist 까지 · 길찾기 에이전트면 Move) ·
// 원본 간격마다 원본 투사체 피해(ProcessCollider = 피격 반응 · 이펙트 그대로) · 수명 + explodeDelay 뒤 폭파 = 피해 배율 explodeDamageMul 로 1회 + 폭발 이펙트 + 원본 기절 // 원본 간격마다 원본 투사체 피해(ProcessCollider = 피격 반응 · 이펙트 그대로) · 수명 + explodeDelay 뒤 폭파 = 피해 배율 explodeDamageMul 로 1회 + 폭발 이펙트 + 원본 기절
// ■ #979 PD 「블랙홀의 색상이 너무 밝아서 블랙홀 컨셉이 아닌 느낌이야」 — 블랙홀 동안 원본 렌더러를 끄고(hideOriginal) 검은 코어(GA BlackHole01 사본) ·
// 가장자리에서 중심으로 빨려 드는 줄기(범위 배율)를 띄우고(lifeFx) 폭파 = 보라 폭발 사본(explodeFx)
// ■ 값 = Resources/WL/WLBlackHole.json (C45) · enabled 0 = 원본 그대로 // ■ 값 = Resources/WL/WLBlackHole.json (C45) · enabled 0 = 원본 그대로
// 🔴 Debug.LogError 금지(원본 팝업). // 🔴 Debug.LogError 금지(원본 팝업).
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
@ -14,6 +16,9 @@ using UnityEngine;
namespace WL.Combat.Weapon namespace WL.Combat.Weapon
{ {
[System.Serializable]
public class WLBlackHoleFx { public string path = ""; public float scale = 1f, perRange = 0f; } // 배율 = scale × (perRange > 0 ? 범위 × perRange : 1)
[System.Serializable] [System.Serializable]
public class WLBlackHoleJson public class WLBlackHoleJson
{ {
@ -22,6 +27,10 @@ namespace WL.Combat.Weapon
public float explodeDelay = 0.5f, explodeDamageMul = 5f; public float explodeDelay = 0.5f, explodeDamageMul = 5f;
public string explodeFx = "WL/Impact/WL_Impact_Explosion"; public string explodeFx = "WL/Impact/WL_Impact_Explosion";
public float explodeFxScale = 0.5f, explodeFxLife = 2f; public float explodeFxScale = 0.5f, explodeFxLife = 2f;
public int hideOriginal = 0; // #979 1 = 블랙홀 동안 원본 이펙트 렌더러를 끔(끝나 풀로 돌아갈 때 되살림)
public WLBlackHoleFx[] lifeFx = new WLBlackHoleFx[0]; // #979 블랙홀 동안 중심에 띄울 WL 이펙트(검은 코어 · 빨려 드는 줄기)
public float lifeFxFade = 0.25f; // 폭파 때 방출을 멈춘 뒤 지우기까지(s)
public float collapseTo = 1f; // #979 폭파 전 explodeDelay 동안 블랙홀 이펙트가 이 배율까지 줄어듦(응축 → 폭발 · 1 = 그대로)
public string note = ""; public string note = "";
} }
@ -62,11 +71,42 @@ namespace WL.Combat.Weapon
internal sealed class WLBlackHoleRunner : MonoBehaviour internal sealed class WLBlackHoleRunner : MonoBehaviour
{ {
readonly List<Renderer> _hidden = new List<Renderer>(); readonly List<GameObject> _fx = new List<GameObject>();
public void Begin(ProjectileBase pb, ProjectileData pd, float range, float life, float gap, float stun, WLBlackHoleJson c) public void Begin(ProjectileBase pb, ProjectileData pd, float range, float life, float gap, float stun, WLBlackHoleJson c)
{ {
StopAllCoroutines(); StartCoroutine(Run(pb, pd, range, life, gap, stun, c)); StopAllCoroutines(); EndLifeFx(0f); RestoreOriginal(); StartCoroutine(Run(pb, pd, range, life, gap, stun, c));
} }
void HideOriginal(ProjectileBase pb) { foreach (var r in pb.GetComponentsInChildren<Renderer>(true)) if (r.enabled) { r.enabled = false; _hidden.Add(r); } }
void RestoreOriginal() { foreach (var r in _hidden) if (r != null) r.enabled = true; _hidden.Clear(); }
void SpawnLifeFx(WLBlackHoleJson c, Vector3 center, float range)
{
if (c.lifeFx == null) return;
foreach (var f in c.lifeFx)
{
if (f == null || string.IsNullOrEmpty(f.path)) continue;
var p = Resources.Load<GameObject>(f.path); if (p == null) { WLBlackHole.LastLog = "블랙홀 이펙트 없음 " + f.path; continue; }
var g = Instantiate(p, center, Quaternion.identity); g.transform.localScale = p.transform.localScale * (f.scale * (f.perRange > 0f ? range * f.perRange : 1f));
foreach (var ps in g.GetComponentsInChildren<ParticleSystem>(true)) { var m = ps.main; m.scalingMode = ParticleSystemScalingMode.Hierarchy; }
_fx.Add(g);
}
}
void EndLifeFx(float fade)
{
foreach (var g in _fx)
{
if (g == null) continue;
foreach (var ps in g.GetComponentsInChildren<ParticleSystem>(true)) ps.Stop(true, ParticleSystemStopBehavior.StopEmitting);
Destroy(g, Mathf.Max(0f, fade));
}
_fx.Clear();
}
void OnDisable() { EndLifeFx(0f); RestoreOriginal(); } // 풀로 돌아갈 때 원본 렌더러를 되살려 다음 사용(enabled 0 포함)에 그대로
static List<Actor> Enemies(ProjectileData pd, Vector3 center, float range) static List<Actor> Enemies(ProjectileData pd, Vector3 center, float range)
{ {
var res = new List<Actor>(); var info = ActorInfo.Ins; if (info == null || DSUtil.CheckNull(pd.shooter)) return res; var res = new List<Actor>(); var info = ActorInfo.Ins; if (info == null || DSUtil.CheckNull(pd.shooter)) return res;
@ -85,6 +125,8 @@ namespace WL.Combat.Weapon
IEnumerator Run(ProjectileBase pb, ProjectileData pd, float range, float life, float gap, float stun, WLBlackHoleJson c) IEnumerator Run(ProjectileBase pb, ProjectileData pd, float range, float life, float gap, float stun, WLBlackHoleJson c)
{ {
Vector3 center = pb.transform.position; float t0 = Time.time, nextTick = 0f, pulled = 0f; Vector3 center = pb.transform.position; float t0 = Time.time, nextTick = 0f, pulled = 0f;
if (c.hideOriginal != 0) HideOriginal(pb); // #979 PD 「블랙홀 색이 너무 밝아」 — 원본(밝은 보라 · 흰 섬광)을 끄고 WL 검은 코어 · 빨려 드는 줄기로
SpawnLifeFx(c, center, range);
while (Time.time - t0 < life) while (Time.time - t0 < life)
{ {
float t = Time.time - t0, step = c.pullSpeed * Time.deltaTime; float t = Time.time - t0, step = c.pullSpeed * Time.deltaTime;
@ -99,7 +141,17 @@ namespace WL.Combat.Weapon
if (t >= nextTick) { nextTick += gap; WLBlackHole.Ticks++; WLBlackHole.TickHits += HitAll(pb, Enemies(pd, center, range)); } if (t >= nextTick) { nextTick += gap; WLBlackHole.Ticks++; WLBlackHole.TickHits += HitAll(pb, Enemies(pd, center, range)); }
yield return null; yield return null;
} }
if (c.explodeDelay > 0f) yield return new WaitForSeconds(c.explodeDelay); if (c.explodeDelay > 0f) // 응축 — 코어 · 줄기가 collapseTo 배까지 줄어든 뒤 폭파
{
var s0 = new List<Vector3>(); foreach (var g in _fx) s0.Add(g != null ? g.transform.localScale : Vector3.one);
for (float t = 0f; t < c.explodeDelay; t += Time.deltaTime)
{
float k = Mathf.Lerp(1f, c.collapseTo, t / c.explodeDelay);
for (int i = 0; i < _fx.Count; i++) if (_fx[i] != null) _fx[i].transform.localScale = s0[i] * k;
yield return null;
}
}
EndLifeFx(c.lifeFxFade);
// 폭파 — 피해 배율을 잠시 올려 1회 · 기절 · 폭발 이펙트 // 폭파 — 피해 배율을 잠시 올려 1회 · 기절 · 폭발 이펙트
var targets = Enemies(pd, center, range); float mul0 = pd.AddDmgPercent; var targets = Enemies(pd, center, range); float mul0 = pd.AddDmgPercent;
pd.AddDmgPercent = mul0 * Mathf.Max(1f, c.explodeDamageMul); pd.AddDmgPercent = mul0 * Mathf.Max(1f, c.explodeDamageMul);

View File

@ -2,7 +2,7 @@
// WLNockArrow.cs — 활 시위를 당기는 동안 화살(기본 화살 투사체와 같은 메시)을 당기는 손 ~ 활 사이에 보인다 (#977 · 2026-10-24) // WLNockArrow.cs — 활 시위를 당기는 동안 화살(기본 화살 투사체와 같은 메시)을 당기는 손 ~ 활 사이에 보인다 (#977 · 2026-10-24)
// //
// PD 원문: 「활 시위를 당길 때 화살 오브젝트가 보이게 해줘.(보유중인 리소스 중 화살을 찾아볼 것)」 // PD 원문: 「활 시위를 당길 때 화살 오브젝트가 보이게 해줘.(보유중인 리소스 중 화살을 찾아볼 것)」
// ■ 화살 = Resources/WL/Fx/WL_NockArrow(Projectile_10402 의 PP_Theme_10_Arrow_003 메시 사본 · 루트 +Z = 촉) // ■ 화살 = Resources/WL/Fx/WL_NockArrow(루트 +Z = 촉 · #979 = Stylized Shoot & Hit Vol.2 FX_Shoot_Arrow 의 화살 메시 층을 정적 메시로 · 납작한 면을 위로 눕힘)
// ■ 활 직업(classes)의 애니메이터 상태가 규칙(state · 정규화 from~to = 시위를 당겨 놓기 전까지)에 들면 매 LateUpdate(IK 뒤)에 // ■ 활 직업(classes)의 애니메이터 상태가 규칙(state · 정규화 from~to = 시위를 당겨 놓기 전까지)에 들면 매 LateUpdate(IK 뒤)에
// 꼬리 = 오른손 · 촉 방향 = 왼손(활 잡은 손) 쪽 · 길이 lengthMeters 로 놓고, 아니면 숨긴다 · 스킬 러너(WLRapidShot)도 같은 attack 상태라 함께 // 꼬리 = 오른손 · 촉 방향 = 왼손(활 잡은 손) 쪽 · 길이 lengthMeters 로 놓고, 아니면 숨긴다 · 스킬 러너(WLRapidShot)도 같은 attack 상태라 함께
// ■ 값 = Resources/WL/WLNockArrow.json (C45) · 끄기 = enabled 0 // ■ 값 = Resources/WL/WLNockArrow.json (C45) · 끄기 = enabled 0
@ -22,6 +22,7 @@ namespace WL.Combat.Weapon
public int[] classes = new int[0]; public int[] classes = new int[0];
public string prefab = "WL/Fx/WL_NockArrow"; public string prefab = "WL/Fx/WL_NockArrow";
public float lengthMeters = 0.55f; // 보이는 화살 길이(m) public float lengthMeters = 0.55f; // 보이는 화살 길이(m)
public float widthMul = 1f; // #979 굵기(촉 · 깃 폭) 배율 — 길이와 따로(위 카메라에서 실처럼 보이지 않게)
public float nockOffset = 0f; // 꼬리를 오른손에서 촉 쪽으로 더 미는 거리(m) public float nockOffset = 0f; // 꼬리를 오른손에서 촉 쪽으로 더 미는 거리(m)
public WLNockArrowRule[] rules = new WLNockArrowRule[0]; public WLNockArrowRule[] rules = new WLNockArrowRule[0];
public string note = ""; public string note = "";
@ -83,7 +84,7 @@ namespace WL.Combat.Weapon
else else
{ {
float s = c.lengthMeters / Mathf.Max(1e-3f, _len); var rot = Quaternion.LookRotation(d.normalized); float s = c.lengthMeters / Mathf.Max(1e-3f, _len); var rot = Quaternion.LookRotation(d.normalized);
var t = _arrow.transform; t.localScale = Vector3.one * s; t.rotation = rot; var t = _arrow.transform; t.localScale = new Vector3(s * c.widthMul, s * c.widthMul, s); t.rotation = rot;
t.position = rh.position + rot * new Vector3(0f, 0f, c.nockOffset - _tailZ * s); // 꼬리(_tailZ) = 오른손 t.position = rh.position + rot * new Vector3(0f, 0f, c.nockOffset - _tailZ * s); // 꼬리(_tailZ) = 오른손
WLNockArrow.ShownFrames++; WLNockArrow.ShownFrames++;
} }