82 lines
5.4 KiB
C#
82 lines
5.4 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
||
// 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++;
|
||
}
|
||
}
|
||
}
|