Project_WL/Assets/WL/Combat/Weapon/WLWeaponGlowFx.cs

114 lines
6.9 KiB
C#
Raw Permalink Normal View History

// ─────────────────────────────────────────────────────────────────────────────
// WLWeaponGlowFx.cs — 무기 흰 빛 덧그림 도우미 (#916 · 2026-10-17)
//
// 해머 각성(WLHammerQuake #912)과 같은 방식: 소켓 아래 무기 메시마다 같은 메시를 쓰는 자식을 만들어 WL/WeaponGlow 재질(가산 · 테두리)을 씌우고,
// 세기 · 색 · 몸통 덮기 · 테두리를 렌더러별 프로퍼티 블록으로 쓴다(재질 인스턴스 0). End 에서 자식을 지운다.
// 🔴 Debug.LogError 금지(원본 팝업).
// ─────────────────────────────────────────────────────────────────────────────
using System.Collections.Generic;
using UnityEngine;
namespace WL.Combat.Weapon
{
public sealed class WLWeaponGlowFx
{
static readonly Dictionary<string, Material> s_mats = new Dictionary<string, Material>();
static readonly int kGlow = Shader.PropertyToID("_Glow"), kColor = Shader.PropertyToID("_GlowColor"),
WL #958 PD 지시 6건(테스트 씬 편의 · 대검 · 비수) + 궤적 이펙트 Play 간 막힘 수정 - ① 숫자 키 1~9 · 0 = 그 번호 무기로 즉시 교체(WLSkillTestHarness.SelectWeapon · 번호 = O/P 순환과 같은 종류 순 · 화면 목록) · 이 씬에서 등급 치트 끔 - ② 모든 무기 각성 상태(WLTestScene.AllAwakened → 무기 기술 · 연계 · 파츠 스킬 칸 해금 등급 무시) · 자동 스킬 끔(ManualSkills → PCActor 자동 시전 · WL_TryAutoSkillNow · 파츠 스킬 자동 시전) — Q/E 치트키로만 · 실측 해머 8 s 공격 427 프레임 · 스킬 진입 0 · E = 대지 분쇄 발동 - ③ 대검 주력 모으기 = 검 빛 손잡이 금색 → 칼끝 노랑 축 그라데이션(WL/WeaponGlow _GlowColor2 · _GradAxis · _GradLen · WLWeaponGlowFx 5인자 Set) + 모으기 입자 수명색 노랑 계열(TintGradient · 어두운 층 제외) · 파란 호 = 모으기 사본 루트 ChargePath 렌더러 끔(chargeFxHide) - ④ 대검 각성 회오리 흰 뭉개짐 = WL_Fx_BladeStormTornado 의 HS 재질 _Emission 5(블룸 없는 화면에서 흰색 포화 · 층별 끄기로 확정) → wraps layers 로 몸통 _Emission 0.7 + 푸른 회색 · 회전 줄무늬 2.5 · 바닥 고리 1.8(프로퍼티 블록) - ⑤ 비수 3타 = 이펙트와 같은 반시계 1080°/s 한 바퀴(−360°/0.333 s) · 팔라딘 클립 자체 시계 300°/0.18 s 회전을 덮어씀(WLSwingExtras yaw 덮기 · 끝 0.12 s 섞기) · 실측 엉덩이 각이 코드 각을 그대로 따라감 - ⑥ 비수 주력 = 양손 작은 사본 끔 · 대상 쪽 공격 범위 × 0.5 자리에 1개(폭 = 범위 × 1.6) · 실측 거리 0.50 · 범위 1.00 · 배율 0.304 - 발견 수정: WLImpactFx.s_swingAt(같은 PC·단계 궤적 0.3 s 묶음)가 도메인 리로드 꺼짐으로 Play 사이에 남아 새 Play 의 궤적 이펙트 · 비수 3타 회전이 막힘(실측 swing +0 · spins +0) → Play 시작마다 비움 · 연속 Play 2회 확인(swing +6 · spins +3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 04:05:18 +00:00
kFill = Shader.PropertyToID("_Fill"), kRim = Shader.PropertyToID("_RimPower"),
kColor2 = Shader.PropertyToID("_GlowColor2"), kAxis = Shader.PropertyToID("_GradAxis"), kLen = Shader.PropertyToID("_GradLen"); // #958 그라데이션
readonly List<GameObject> _gos = new List<GameObject>();
readonly List<Renderer> _rs = new List<Renderer>();
WL #958 PD 지시 6건(테스트 씬 편의 · 대검 · 비수) + 궤적 이펙트 Play 간 막힘 수정 - ① 숫자 키 1~9 · 0 = 그 번호 무기로 즉시 교체(WLSkillTestHarness.SelectWeapon · 번호 = O/P 순환과 같은 종류 순 · 화면 목록) · 이 씬에서 등급 치트 끔 - ② 모든 무기 각성 상태(WLTestScene.AllAwakened → 무기 기술 · 연계 · 파츠 스킬 칸 해금 등급 무시) · 자동 스킬 끔(ManualSkills → PCActor 자동 시전 · WL_TryAutoSkillNow · 파츠 스킬 자동 시전) — Q/E 치트키로만 · 실측 해머 8 s 공격 427 프레임 · 스킬 진입 0 · E = 대지 분쇄 발동 - ③ 대검 주력 모으기 = 검 빛 손잡이 금색 → 칼끝 노랑 축 그라데이션(WL/WeaponGlow _GlowColor2 · _GradAxis · _GradLen · WLWeaponGlowFx 5인자 Set) + 모으기 입자 수명색 노랑 계열(TintGradient · 어두운 층 제외) · 파란 호 = 모으기 사본 루트 ChargePath 렌더러 끔(chargeFxHide) - ④ 대검 각성 회오리 흰 뭉개짐 = WL_Fx_BladeStormTornado 의 HS 재질 _Emission 5(블룸 없는 화면에서 흰색 포화 · 층별 끄기로 확정) → wraps layers 로 몸통 _Emission 0.7 + 푸른 회색 · 회전 줄무늬 2.5 · 바닥 고리 1.8(프로퍼티 블록) - ⑤ 비수 3타 = 이펙트와 같은 반시계 1080°/s 한 바퀴(−360°/0.333 s) · 팔라딘 클립 자체 시계 300°/0.18 s 회전을 덮어씀(WLSwingExtras yaw 덮기 · 끝 0.12 s 섞기) · 실측 엉덩이 각이 코드 각을 그대로 따라감 - ⑥ 비수 주력 = 양손 작은 사본 끔 · 대상 쪽 공격 범위 × 0.5 자리에 1개(폭 = 범위 × 1.6) · 실측 거리 0.50 · 범위 1.00 · 배율 0.304 - 발견 수정: WLImpactFx.s_swingAt(같은 PC·단계 궤적 0.3 s 묶음)가 도메인 리로드 꺼짐으로 Play 사이에 남아 새 Play 의 궤적 이펙트 · 비수 3타 회전이 막힘(실측 swing +0 · spins +0) → Play 시작마다 비움 · 연속 Play 2회 확인(swing +6 · spins +3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 04:05:18 +00:00
readonly List<Vector4> _axis = new List<Vector4>(); // #958 렌더러별 그라데이션 축(오브젝트 공간 · w = 손잡이 끝 투영)
readonly List<float> _len = new List<float>(); // 1 / (칼끝 − 손잡이 투영)
MaterialPropertyBlock _mpb;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void Reset() { s_mats.Clear(); }
public bool Active { get { return _rs.Count > 0; } }
/// <summary>socket 아래 켜진 MeshRenderer 마다 덧그림 자식을 만든다 — 만든 수.</summary>
public int Begin(Transform socket, string materialPath)
{
End();
if (socket == null || string.IsNullOrEmpty(materialPath)) return 0;
Material mat;
if (!s_mats.TryGetValue(materialPath, out mat)) { mat = Resources.Load<Material>(materialPath); s_mats[materialPath] = mat; }
if (mat == null) return 0;
foreach (var mf in socket.GetComponentsInChildren<MeshFilter>(false))
{
var mr = mf.GetComponent<MeshRenderer>();
if (mr == null || !mr.enabled || mf.sharedMesh == null || mf.name == "[WL] Glow") continue;
var go = new GameObject("[WL] Glow") { layer = mf.gameObject.layer };
go.transform.SetParent(mf.transform, false);
go.AddComponent<MeshFilter>().sharedMesh = mf.sharedMesh;
var r = go.AddComponent<MeshRenderer>();
var mats = new Material[Mathf.Max(1, mf.sharedMesh.subMeshCount)];
for (int i = 0; i < mats.Length; i++) mats[i] = mat;
r.sharedMaterials = mats; r.enabled = false;
r.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; r.receiveShadows = false;
r.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off; r.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
_gos.Add(go); _rs.Add(r);
WL #958 PD 지시 6건(테스트 씬 편의 · 대검 · 비수) + 궤적 이펙트 Play 간 막힘 수정 - ① 숫자 키 1~9 · 0 = 그 번호 무기로 즉시 교체(WLSkillTestHarness.SelectWeapon · 번호 = O/P 순환과 같은 종류 순 · 화면 목록) · 이 씬에서 등급 치트 끔 - ② 모든 무기 각성 상태(WLTestScene.AllAwakened → 무기 기술 · 연계 · 파츠 스킬 칸 해금 등급 무시) · 자동 스킬 끔(ManualSkills → PCActor 자동 시전 · WL_TryAutoSkillNow · 파츠 스킬 자동 시전) — Q/E 치트키로만 · 실측 해머 8 s 공격 427 프레임 · 스킬 진입 0 · E = 대지 분쇄 발동 - ③ 대검 주력 모으기 = 검 빛 손잡이 금색 → 칼끝 노랑 축 그라데이션(WL/WeaponGlow _GlowColor2 · _GradAxis · _GradLen · WLWeaponGlowFx 5인자 Set) + 모으기 입자 수명색 노랑 계열(TintGradient · 어두운 층 제외) · 파란 호 = 모으기 사본 루트 ChargePath 렌더러 끔(chargeFxHide) - ④ 대검 각성 회오리 흰 뭉개짐 = WL_Fx_BladeStormTornado 의 HS 재질 _Emission 5(블룸 없는 화면에서 흰색 포화 · 층별 끄기로 확정) → wraps layers 로 몸통 _Emission 0.7 + 푸른 회색 · 회전 줄무늬 2.5 · 바닥 고리 1.8(프로퍼티 블록) - ⑤ 비수 3타 = 이펙트와 같은 반시계 1080°/s 한 바퀴(−360°/0.333 s) · 팔라딘 클립 자체 시계 300°/0.18 s 회전을 덮어씀(WLSwingExtras yaw 덮기 · 끝 0.12 s 섞기) · 실측 엉덩이 각이 코드 각을 그대로 따라감 - ⑥ 비수 주력 = 양손 작은 사본 끔 · 대상 쪽 공격 범위 × 0.5 자리에 1개(폭 = 범위 × 1.6) · 실측 거리 0.50 · 범위 1.00 · 배율 0.304 - 발견 수정: WLImpactFx.s_swingAt(같은 PC·단계 궤적 0.3 s 묶음)가 도메인 리로드 꺼짐으로 Play 사이에 남아 새 Play 의 궤적 이펙트 · 비수 3타 회전이 막힘(실측 swing +0 · spins +0) → Play 시작마다 비움 · 연속 Play 2회 확인(swing +6 · spins +3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 04:05:18 +00:00
// #958 그라데이션 축 = 메시 경계의 가장 긴 축 · 방향 = 소켓(손잡이) 쪽 끝 → 먼 끝(칼끝)
var b = mf.sharedMesh.bounds; var s = b.size;
Vector3 ax = s.x >= s.y && s.x >= s.z ? Vector3.right : (s.y >= s.z ? Vector3.up : Vector3.forward);
float lo = Vector3.Dot(b.min, ax), hi = Vector3.Dot(b.max, ax);
float sock = Vector3.Dot(mf.transform.InverseTransformPoint(socket.position), ax);
if (Mathf.Abs(sock - hi) < Mathf.Abs(sock - lo)) { ax = -ax; float t = lo; lo = -hi; hi = -t; }
_axis.Add(new Vector4(ax.x, ax.y, ax.z, lo)); _len.Add(hi - lo > 1e-4f ? 1f / (hi - lo) : 0f);
}
return _rs.Count;
}
WL #958 PD 지시 6건(테스트 씬 편의 · 대검 · 비수) + 궤적 이펙트 Play 간 막힘 수정 - ① 숫자 키 1~9 · 0 = 그 번호 무기로 즉시 교체(WLSkillTestHarness.SelectWeapon · 번호 = O/P 순환과 같은 종류 순 · 화면 목록) · 이 씬에서 등급 치트 끔 - ② 모든 무기 각성 상태(WLTestScene.AllAwakened → 무기 기술 · 연계 · 파츠 스킬 칸 해금 등급 무시) · 자동 스킬 끔(ManualSkills → PCActor 자동 시전 · WL_TryAutoSkillNow · 파츠 스킬 자동 시전) — Q/E 치트키로만 · 실측 해머 8 s 공격 427 프레임 · 스킬 진입 0 · E = 대지 분쇄 발동 - ③ 대검 주력 모으기 = 검 빛 손잡이 금색 → 칼끝 노랑 축 그라데이션(WL/WeaponGlow _GlowColor2 · _GradAxis · _GradLen · WLWeaponGlowFx 5인자 Set) + 모으기 입자 수명색 노랑 계열(TintGradient · 어두운 층 제외) · 파란 호 = 모으기 사본 루트 ChargePath 렌더러 끔(chargeFxHide) - ④ 대검 각성 회오리 흰 뭉개짐 = WL_Fx_BladeStormTornado 의 HS 재질 _Emission 5(블룸 없는 화면에서 흰색 포화 · 층별 끄기로 확정) → wraps layers 로 몸통 _Emission 0.7 + 푸른 회색 · 회전 줄무늬 2.5 · 바닥 고리 1.8(프로퍼티 블록) - ⑤ 비수 3타 = 이펙트와 같은 반시계 1080°/s 한 바퀴(−360°/0.333 s) · 팔라딘 클립 자체 시계 300°/0.18 s 회전을 덮어씀(WLSwingExtras yaw 덮기 · 끝 0.12 s 섞기) · 실측 엉덩이 각이 코드 각을 그대로 따라감 - ⑥ 비수 주력 = 양손 작은 사본 끔 · 대상 쪽 공격 범위 × 0.5 자리에 1개(폭 = 범위 × 1.6) · 실측 거리 0.50 · 범위 1.00 · 배율 0.304 - 발견 수정: WLImpactFx.s_swingAt(같은 PC·단계 궤적 0.3 s 묶음)가 도메인 리로드 꺼짐으로 Play 사이에 남아 새 Play 의 궤적 이펙트 · 비수 3타 회전이 막힘(실측 swing +0 · spins +0) → Play 시작마다 비움 · 연속 Play 2회 확인(swing +6 · spins +3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 04:05:18 +00:00
/// <summary>#958 손잡이 color → 칼끝 color2 그라데이션(WL/WeaponGlow 의 _GlowColor2 · _GradAxis · _GradLen).</summary>
public void Set(float glow, Color color, Color color2, float fill, float rimPower)
{
if (_rs.Count == 0) return;
if (_mpb == null) _mpb = new MaterialPropertyBlock();
for (int i = 0; i < _rs.Count; i++)
{
var r = _rs[i]; if (r == null) continue;
r.enabled = glow > 0.001f;
_mpb.Clear(); _mpb.SetFloat(kGlow, glow); _mpb.SetColor(kColor, color); _mpb.SetFloat(kFill, fill); _mpb.SetFloat(kRim, rimPower);
_mpb.SetColor(kColor2, color2); _mpb.SetVector(kAxis, i < _axis.Count ? _axis[i] : Vector4.zero); _mpb.SetFloat(kLen, i < _len.Count ? _len[i] : 0f);
r.SetPropertyBlock(_mpb);
}
}
public void Set(float glow, Color color, float fill, float rimPower)
{
if (_rs.Count == 0) return;
if (_mpb == null) _mpb = new MaterialPropertyBlock();
for (int i = 0; i < _rs.Count; i++)
{
var r = _rs[i]; if (r == null) continue;
r.enabled = glow > 0.001f;
_mpb.Clear(); _mpb.SetFloat(kGlow, glow); _mpb.SetColor(kColor, color); _mpb.SetFloat(kFill, fill); _mpb.SetFloat(kRim, rimPower);
r.SetPropertyBlock(_mpb);
}
}
public void End()
{
for (int i = 0; i < _gos.Count; i++) if (_gos[i] != null) Object.Destroy(_gos[i]);
WL #958 PD 지시 6건(테스트 씬 편의 · 대검 · 비수) + 궤적 이펙트 Play 간 막힘 수정 - ① 숫자 키 1~9 · 0 = 그 번호 무기로 즉시 교체(WLSkillTestHarness.SelectWeapon · 번호 = O/P 순환과 같은 종류 순 · 화면 목록) · 이 씬에서 등급 치트 끔 - ② 모든 무기 각성 상태(WLTestScene.AllAwakened → 무기 기술 · 연계 · 파츠 스킬 칸 해금 등급 무시) · 자동 스킬 끔(ManualSkills → PCActor 자동 시전 · WL_TryAutoSkillNow · 파츠 스킬 자동 시전) — Q/E 치트키로만 · 실측 해머 8 s 공격 427 프레임 · 스킬 진입 0 · E = 대지 분쇄 발동 - ③ 대검 주력 모으기 = 검 빛 손잡이 금색 → 칼끝 노랑 축 그라데이션(WL/WeaponGlow _GlowColor2 · _GradAxis · _GradLen · WLWeaponGlowFx 5인자 Set) + 모으기 입자 수명색 노랑 계열(TintGradient · 어두운 층 제외) · 파란 호 = 모으기 사본 루트 ChargePath 렌더러 끔(chargeFxHide) - ④ 대검 각성 회오리 흰 뭉개짐 = WL_Fx_BladeStormTornado 의 HS 재질 _Emission 5(블룸 없는 화면에서 흰색 포화 · 층별 끄기로 확정) → wraps layers 로 몸통 _Emission 0.7 + 푸른 회색 · 회전 줄무늬 2.5 · 바닥 고리 1.8(프로퍼티 블록) - ⑤ 비수 3타 = 이펙트와 같은 반시계 1080°/s 한 바퀴(−360°/0.333 s) · 팔라딘 클립 자체 시계 300°/0.18 s 회전을 덮어씀(WLSwingExtras yaw 덮기 · 끝 0.12 s 섞기) · 실측 엉덩이 각이 코드 각을 그대로 따라감 - ⑥ 비수 주력 = 양손 작은 사본 끔 · 대상 쪽 공격 범위 × 0.5 자리에 1개(폭 = 범위 × 1.6) · 실측 거리 0.50 · 범위 1.00 · 배율 0.304 - 발견 수정: WLImpactFx.s_swingAt(같은 PC·단계 궤적 0.3 s 묶음)가 도메인 리로드 꺼짐으로 Play 사이에 남아 새 Play 의 궤적 이펙트 · 비수 3타 회전이 막힘(실측 swing +0 · spins +0) → Play 시작마다 비움 · 연속 Play 2회 확인(swing +6 · spins +3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 04:05:18 +00:00
_gos.Clear(); _rs.Clear(); _axis.Clear(); _len.Clear();
}
/// <summary>socket 아래 가장 큰 메시의 경계 중심(socket 로컬) — 무기 가운데. 없으면 원점.</summary>
public static Vector3 CenterLocal(Transform socket)
{
if (socket == null) return Vector3.zero;
Vector3 best = Vector3.zero; float bestSize = -1f;
foreach (var mf in socket.GetComponentsInChildren<MeshFilter>(false))
{
var mr = mf.GetComponent<MeshRenderer>(); var mesh = mf.sharedMesh;
if (mr == null || !mr.enabled || mesh == null || mf.name == "[WL] Glow") continue;
float size = mesh.bounds.size.sqrMagnitude;
if (size > bestSize) { bestSize = size; best = socket.InverseTransformPoint(mf.transform.TransformPoint(mesh.bounds.center)); }
}
return best;
}
}
}