Files
MyCharacterAgent/Assets/02_Scripts/Character/ICharacterMotion.cs
2026-09-01 21:36:23 +09:00

62 lines
2.6 KiB
C#

using UnityEngine;
/// <summary>
/// 캐릭터가 지을 수 있는 몸짓.
///
/// <see cref="ClimbState"/> 와 일부러 분리했다. ClimbState 는 "몸이 어디에 있는가"이고
/// 이쪽은 "어떻게 보이는가"다. 서 있는 상태 하나에도 그냥 서기 / 걸터앉기 / 눕기가
/// 있으므로 일대일로 묶으면 이동 로직에 표현이 섞여 들어간다.
/// </summary>
public enum CharacterMotionKind
{
Idle, // 서서 대기
Fall, // 떨어지는 중
Walk, // 걷는 중
Jump, // 다른 발판으로 뛰어오르는 중
Sit, // 발판에 걸터앉기
LieDown, // 눕기
}
/// <summary>
/// 우클릭 메뉴에 나올 포즈 하나. 표시 이름과 가림 여부를 함께 들고 다닌다.
///
/// 예전에는 "메뉴에 넣을 포즈 목록"과 "가려야 할 포즈 목록"을 따로 뒀는데,
/// 둘을 손으로 맞춰야 했고 어긋나면(가림 목록에만 있고 메뉴 목록엔 없으면)
/// 그 포즈에 도달할 방법이 없어 조용히 아무 일도 안 일어났다.
/// 한 곳에 묶으면 그 상태 자체가 만들어질 수 없다.
/// </summary>
[System.Serializable]
public struct PoseOption
{
[Tooltip("어떤 몸짓인지")]
public CharacterMotionKind kind;
[Tooltip("메뉴에 표시할 이름. 비우면 기본 이름을 쓴다")]
public string label;
[Tooltip("켜면 이 포즈일 때 발판 아래를 가린다 — 캐릭터가 창 뒤에 있는 것처럼 보인다. " +
"예: 창 밑에서 머리만 내미는 포즈")]
public bool hideBehindPlatform;
}
/// <summary>
/// 캐릭터 몸짓을 재생하는 계층의 창구.
///
/// 왜 인터페이스로 두는가:
/// 지금은 Unity Animator + Humanoid FBX 클립으로 간다. 전환(CrossFade)과 레이어를
/// 공짜로 얻을 수 있어서다. 하지만 나중에 "사용자가 자기 모션(.vrma)을 넣게 하고 싶다"가
/// 되면 VRM Animation 로더를 하나 더 붙이게 된다. 그때 이 인터페이스만 다시 구현하면
/// WindowClimber 와 상위 로직은 손대지 않는다. IChatBackend 와 같은 이유다.
///
/// 참고: .vrma 는 Vrm10Runtime.VrmAnimation 하나에 통째로 물리는 구조라
/// 크로스페이드가 없다. 그쪽으로 갈 때는 전환 처리를 구현체가 직접 해야 한다.
/// </summary>
public interface ICharacterMotion
{
/// <summary>재생할 준비가 됐는지. 클립이나 컨트롤러가 없으면 false.</summary>
bool IsReady { get; }
/// <summary>해당 몸짓으로 넘어간다. 같은 것을 다시 줘도 안전하다.</summary>
void Play(CharacterMotionKind kind);
}