109 lines
5.5 KiB
C#
109 lines
5.5 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// WLSkillYaw.cs — 스킬 동작 상태 동안 보이는 몸(엉덩이 뼈)을 위 축으로 일정 각만큼 돌려 공격 대상 쪽에 맞춘다 (#974 · 2026-10-23)
|
|
//
|
|
// PD 원문: 「한손검 주력 스킬 시 회전할 때 공격 대상의 방향과 일치하도록 수정해줘 (현재는 공격 투사체 방향보다 더 회전하고 있어.)」
|
|
// ■ 실측(#974 진단 Play · 974_probe Spin): 검기 분출 동작 energyslash(월광 클립 combo09_3)는 몸을 한 바퀴 반 돌리고,
|
|
// 검기를 쏘는 순간(정규화 0.41~0.45) 몸이 대상 · 검기 방향과 어긋난다(PC 루트 · 검기는 대상 쪽 · 어긋난 각 = 규칙 yaw 의 근거 · JSON 메모)
|
|
// ■ 처리 = 규칙 상태(지금 상태 또는 넘어가는 중인 다음 상태)일 때 LateUpdate(애니메이션 평가 뒤)에서 엉덩이 뼈를 PC 루트 둘레 위 축으로 yaw° —
|
|
// 들어갈 때 blendIn · 나갈 때 blendOut 초에 걸쳐 · 애니메이터가 매 프레임 뼈를 다시 쓰므로 누적 없음 · 루트 · 판정 · 투사체 방향 · 카메라는 그대로(보이는 몸만)
|
|
// (WLImpactFx 비수 3타 회전 #956 과 같은 방식)
|
|
// ■ 값 = Resources/WL/WLSkillYaw.json (C45) · 끄기 = enabled 0
|
|
// 🔴 Debug.LogError 금지(원본 ErrorLogHook 팝업).
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
using UnityEngine;
|
|
|
|
namespace WL.Combat.Weapon
|
|
{
|
|
[System.Serializable]
|
|
public class WLSkillYawRule
|
|
{
|
|
public string state = ""; // 애니메이터 0층 상태 이름(예: energyslash)
|
|
public float yaw; // 보이는 몸을 돌릴 각(°) · + = 위에서 볼 때 시계 방향
|
|
public float blendIn = 0.08f, blendOut = 0.15f;
|
|
public string note = "";
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class WLSkillYawJson
|
|
{
|
|
public int enabled = 1;
|
|
public WLSkillYawRule[] rules = new WLSkillYawRule[0];
|
|
public string note = "";
|
|
}
|
|
|
|
public static class WLSkillYaw
|
|
{
|
|
public const string ResourcesPath = "WL/WLSkillYaw";
|
|
public static int Frames;
|
|
public static float LastYaw;
|
|
public static string LastLog = "";
|
|
|
|
static WLSkillYawJson s_cfg;
|
|
static GameObject s_runner;
|
|
|
|
internal static WLSkillYawJson Cfg
|
|
{
|
|
get
|
|
{
|
|
if (s_cfg != null) return s_cfg;
|
|
s_cfg = new WLSkillYawJson();
|
|
var ta = Resources.Load<TextAsset>(ResourcesPath);
|
|
if (ta == null) { LastLog = "설정 없음 " + ResourcesPath; return s_cfg; }
|
|
try { JsonUtility.FromJsonOverwrite(ta.text, s_cfg); } catch (System.Exception ex) { LastLog = "설정 파싱 실패 — " + ex.Message; }
|
|
return s_cfg;
|
|
}
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
static void Boot()
|
|
{
|
|
s_cfg = null;
|
|
if (Cfg.enabled == 0 || s_runner != null) return;
|
|
s_runner = new GameObject("[WL974] SkillYaw");
|
|
s_runner.hideFlags = HideFlags.HideAndDontSave;
|
|
Object.DontDestroyOnLoad(s_runner);
|
|
s_runner.AddComponent<WLSkillYawRunner>();
|
|
}
|
|
|
|
internal static WLSkillYawRule Match(AnimatorStateInfo st)
|
|
{
|
|
var rules = Cfg.rules;
|
|
if (rules == null) return null;
|
|
for (int i = 0; i < rules.Length; i++) { var r = rules[i]; if (r != null && !string.IsNullOrEmpty(r.state) && st.IsName(r.state)) return r; }
|
|
return null;
|
|
}
|
|
}
|
|
|
|
[DefaultExecutionOrder(-100)] // 손 · 무기를 따라가는 궤적 · 이펙트(LateUpdate)보다 먼저 몸을 돌린다
|
|
internal sealed class WLSkillYawRunner : MonoBehaviour
|
|
{
|
|
float _w;
|
|
WLSkillYawRule _rule;
|
|
|
|
void LateUpdate()
|
|
{
|
|
try
|
|
{
|
|
if (WLSkillYaw.Cfg.enabled == 0) return;
|
|
var pc = MyValue.MyPC as PCActor;
|
|
if (pc == null || pc.m_animation == null || !pc.m_animation.isHuman) { _w = 0f; _rule = null; return; }
|
|
var an = pc.m_animation;
|
|
var hit = WLSkillYaw.Match(an.GetCurrentAnimatorStateInfo(0));
|
|
if (hit == null && an.IsInTransition(0)) hit = WLSkillYaw.Match(an.GetNextAnimatorStateInfo(0));
|
|
if (hit != null) _rule = hit;
|
|
if (_rule == null) return;
|
|
float target = hit != null ? 1f : 0f;
|
|
float dur = target > _w ? _rule.blendIn : _rule.blendOut;
|
|
_w = Mathf.MoveTowards(_w, target, Time.deltaTime / Mathf.Max(0.01f, dur));
|
|
if (_w <= 0f) { _rule = null; WLSkillYaw.LastYaw = 0f; return; }
|
|
var hips = an.GetBoneTransform(HumanBodyBones.Hips);
|
|
if (hips == null) return;
|
|
float d = _rule.yaw * _w;
|
|
hips.RotateAround(pc.transform.position, pc.transform.up, d);
|
|
WLSkillYaw.Frames++; WLSkillYaw.LastYaw = d;
|
|
}
|
|
catch (System.Exception ex) { WLSkillYaw.LastLog = "회전 실패 — " + ex.Message; _w = 0f; _rule = null; }
|
|
}
|
|
}
|
|
}
|