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

82 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ─────────────────────────────────────────────────────────────────────────────
// WLOrbFloat.cs — 오브 무기(맹약 · Res_Addr/Weapon/Orb.prefab)를 손 위에 띄운다 (#944 · 2026-10-19)
//
// PD 원문: 「오브(손에 빛나는 원형 이펙트)의 크기를 눈에 띄게 5개[배] 키워줘」 · 레퍼런스 = 펼친 손바닥 위에 빛나는 고리가 떠서 천천히 흔들림
// 「아트 컨셉은 무시해도 되며 오브의 위치 및 동작 형태만 참고할 것」
// ■ 원리 — 무기는 PCActor.Make_Weapon(Addressables 콜백)으로 손 소켓 자식에 붙고, WLWeaponFitter 가 LateUpdate 소켓 스캔으로 새 자식을 1회 보정한다.
// 그 자리(Fit 직후)에서 이름이 weaponNames 에 든 무기에 이 컴포넌트를 1회 붙인다(훅 1줄). 이 컴포넌트는 LateUpdate(애니메이터 뒤)마다
// 월드 위치 = 소켓 위치 + 위 hoverHeight + 흔들림(sin) · 회전 = 월드 위 축 spin · 크기 = 보정된 크기 × scaleMul 로 둔다.
// ■ 값 = Resources/WL/WLOrbFloat.json (C45) · enabled 0 = 아무것도 안 함 · 🔴 Debug.LogError 금지(원본 ErrorLogHook 팝업)
// ─────────────────────────────────────────────────────────────────────────────
using UnityEngine;
namespace WL.Combat.Weapon
{
[System.Serializable]
public class WLOrbFloatJson
{
public int enabled = 1;
public string[] weaponNames = new[] { "Orb" }; // 소켓 자식 이름 앞부분(프리팹 이름 · "(Clone)" 무시)
public float scaleMul = 5f; // 보정된 크기 × 배수
public float hoverHeight = 0.25f; // 소켓(손) 위 m
public float forward = 0f; // 소켓 기준 PC 정면 쪽 m
public float bobAmp = 0.04f; // 상하 흔들림 진폭 m
public float bobHz = 1.0f; // 흔들림 주기(초당)
public float spinDegPerSec = 40f; // 월드 위 축 회전
public float tiltDeg = 0f; // 고리를 눕히는 각(0 = 프리팹 그대로)
public string note = "";
}
public static class WLOrbFloatSettings
{
public const string ResourcesPath = "WL/WLOrbFloat";
static WLOrbFloatJson s_cfg; static bool s_loaded;
public static WLOrbFloatJson Cfg { get { if (!s_loaded) Load(); return s_cfg; } }
public static void Reload() { s_loaded = false; }
static void Load()
{
s_loaded = true;
try { var ta = Resources.Load<TextAsset>(ResourcesPath); s_cfg = ta != null ? JsonUtility.FromJson<WLOrbFloatJson>(ta.text) : null; }
catch (System.Exception ex) { WLOrbFloat.LastLog = "설정 읽기 실패 — " + ex.Message; s_cfg = null; }
if (s_cfg == null) s_cfg = new WLOrbFloatJson { enabled = 0 };
}
}
/// <summary>손 소켓 자식(오브)에 붙어 손 위에 띄운다. WLWeaponFitter 훅 1줄 → TryAttach.</summary>
public sealed class WLOrbFloat : MonoBehaviour
{
public static int Attached, Frames; public static string LastLog = "";
Transform _socket, _pc; Vector3 _baseScale; float _t0, _spin;
public static bool TryAttach(Transform weapon)
{
try
{
var c = WLOrbFloatSettings.Cfg; if (c == null || c.enabled == 0 || weapon == null) return false;
string n = weapon.name; bool hit = false;
if (c.weaponNames != null) for (int i = 0; i < c.weaponNames.Length; i++) if (!string.IsNullOrEmpty(c.weaponNames[i]) && n.StartsWith(c.weaponNames[i])) { hit = true; break; }
if (!hit) return false;
var f = weapon.GetComponent<WLOrbFloat>(); if (f != null) return true;
f = weapon.gameObject.AddComponent<WLOrbFloat>();
f._socket = weapon.parent; f._pc = f._socket != null ? f._socket.root : null; f._baseScale = weapon.localScale; f._t0 = Time.time;
weapon.localScale = f._baseScale * Mathf.Max(0.01f, c.scaleMul);
Attached++; LastLog = "오브 부착 " + n + " 소켓=" + (f._socket != null ? f._socket.name : "-") + " 크기 ×" + c.scaleMul + " 높이 " + c.hoverHeight;
return true;
}
catch (System.Exception ex) { LastLog = "오브 부착 실패 — " + ex.Message; return false; }
}
void LateUpdate()
{
var c = WLOrbFloatSettings.Cfg; if (c == null || c.enabled == 0 || _socket == null) return;
float t = Time.time - _t0;
Vector3 fwd = _pc != null ? _pc.forward : Vector3.forward; fwd.y = 0f; if (fwd.sqrMagnitude < 1e-4f) fwd = Vector3.forward; fwd.Normalize();
Vector3 pos = _socket.position + Vector3.up * (c.hoverHeight + Mathf.Sin(t * c.bobHz * Mathf.PI * 2f) * c.bobAmp) + fwd * c.forward;
_spin += c.spinDegPerSec * Time.deltaTime;
var rot = Quaternion.AngleAxis(_spin, Vector3.up) * Quaternion.Euler(c.tiltDeg, 0f, 0f);
transform.SetPositionAndRotation(pos, rot);
Frames++;
}
}
}