스킬 시스템에 루트 모션 지원 추가
- SkillData: useRootMotion, ignoreRootMotionY 설정 추가 - SkillController: 루트 모션 관련 프로퍼티 노출 - PlayerMovement: OnAnimatorMove로 스킬 애니메이션의 이동/회전 데이터 적용 - Y축 무시 옵션으로 중력 및 충돌 처리 유지 가능 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
30
.claude/commands/commit.md
Normal file
30
.claude/commands/commit.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Git Commit Workflow
|
||||
|
||||
변경된 파일들을 분석하고 git add 후 커밋 메시지를 작성한 뒤, 사용자 확인 후 커밋합니다.
|
||||
|
||||
## 작업 순서
|
||||
|
||||
1. `git status`로 변경된 파일 확인
|
||||
2. `git diff`로 변경 내용 분석
|
||||
3. `git log --oneline -5`로 최근 커밋 스타일 참고
|
||||
4. 변경 내용을 표로 정리해서 사용자에게 보여주기
|
||||
5. 커밋 메시지 초안 작성 후 사용자 확인 요청
|
||||
6. 확인되면 `git add` 후 `git commit` 실행
|
||||
7. `git status`로 커밋 완료 확인
|
||||
|
||||
## 커밋 메시지 형식
|
||||
|
||||
```
|
||||
[주제] 간결한 요약
|
||||
|
||||
- 변경 사항 1
|
||||
- 변경 사항 2
|
||||
- 변경 사항 3
|
||||
```
|
||||
|
||||
## 주의사항
|
||||
|
||||
- 한글로 커밋 메시지 작성
|
||||
- 변경 사항은 파일 단위가 아닌 기능/목적 단위로 정리
|
||||
- 사용자 승인 없이 커밋하지 않음
|
||||
- `.meta` 파일은 Unity 자동 생성이므로 내용 분석에서 제외 가능
|
||||
@@ -22,6 +22,7 @@ namespace Colosseum.Player
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private SkillController skillController;
|
||||
[SerializeField] private Animator animator;
|
||||
|
||||
private CharacterController characterController;
|
||||
private Vector3 velocity;
|
||||
@@ -64,6 +65,12 @@ namespace Colosseum.Player
|
||||
skillController = GetComponent<SkillController>();
|
||||
}
|
||||
|
||||
// Animator 참조
|
||||
if (animator == null)
|
||||
{
|
||||
animator = GetComponentInChildren<Animator>();
|
||||
}
|
||||
|
||||
// 스폰 포인트에서 위치 설정
|
||||
SetSpawnPosition();
|
||||
|
||||
@@ -174,11 +181,14 @@ namespace Colosseum.Player
|
||||
{
|
||||
if (characterController == null) return;
|
||||
|
||||
// 스킬 애니메이션 재생 중에는 이동 불가
|
||||
// 스킬 애니메이션 재생 중에는 이동 불가 (루트 모션은 OnAnimatorMove에서 처리)
|
||||
if (skillController != null && skillController.IsPlayingAnimation)
|
||||
{
|
||||
// 중력만 적용
|
||||
// 루트 모션을 사용하지 않는 경우 중력만 적용
|
||||
if (!skillController.UsesRootMotion)
|
||||
{
|
||||
characterController.Move(velocity * Time.deltaTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -248,5 +258,45 @@ namespace Colosseum.Player
|
||||
|
||||
return cameraRight * direction.x + cameraForward * direction.z;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 루트 모션 처리. 스킬 애니메이션 중에 애니메이션의 이동/회전 데이터를 적용합니다.
|
||||
/// </summary>
|
||||
private void OnAnimatorMove()
|
||||
{
|
||||
if (!IsOwner) return;
|
||||
if (animator == null || characterController == null) return;
|
||||
if (skillController == null || !skillController.IsPlayingAnimation) return;
|
||||
if (!skillController.UsesRootMotion) return;
|
||||
|
||||
// 루트 모션 이동 적용
|
||||
Vector3 deltaPosition = animator.deltaPosition;
|
||||
|
||||
// Y축 무시 설정 시 중력 유지
|
||||
if (skillController.IgnoreRootMotionY)
|
||||
{
|
||||
deltaPosition.y = 0f;
|
||||
characterController.Move(deltaPosition + velocity * Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
characterController.Move(deltaPosition);
|
||||
}
|
||||
|
||||
// 루트 모션 회전 적용
|
||||
if (animator.deltaRotation != Quaternion.identity)
|
||||
{
|
||||
transform.rotation *= animator.deltaRotation;
|
||||
}
|
||||
|
||||
// 착지 체크
|
||||
if (!wasGrounded && characterController.isGrounded && isJumping)
|
||||
{
|
||||
OnJumpEnd();
|
||||
}
|
||||
|
||||
wasGrounded = characterController.isGrounded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ namespace Colosseum.Skills
|
||||
|
||||
public bool IsExecutingSkill => currentSkill != null && !skillEndRequested;
|
||||
public bool IsPlayingAnimation => currentSkill != null;
|
||||
public bool UsesRootMotion => currentSkill != null && currentSkill.UseRootMotion;
|
||||
public bool IgnoreRootMotionY => currentSkill != null && currentSkill.IgnoreRootMotionY;
|
||||
public SkillData CurrentSkill => currentSkill;
|
||||
public Animator Animator => animator;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
|
||||
@@ -21,6 +21,12 @@ namespace Colosseum.Skills
|
||||
[Tooltip("종료 애니메이션 (선택)")]
|
||||
[SerializeField] private AnimationClip endClip;
|
||||
|
||||
[Header("루트 모션")]
|
||||
[Tooltip("애니메이션의 이동/회전 데이터를 캐릭터에 적용")]
|
||||
[SerializeField] private bool useRootMotion = false;
|
||||
[Tooltip("루트 모션 적용 시 Y축 이동 무시 (중력과 충돌)")]
|
||||
[SerializeField] private bool ignoreRootMotionY = true;
|
||||
|
||||
[Header("쿨타임 & 비용")]
|
||||
[Min(0f)] [SerializeField] private float cooldown = 1f;
|
||||
[Min(0f)] [SerializeField] private float manaCost = 0f;
|
||||
@@ -37,6 +43,8 @@ namespace Colosseum.Skills
|
||||
public AnimationClip EndClip => endClip;
|
||||
public float Cooldown => cooldown;
|
||||
public float ManaCost => manaCost;
|
||||
public bool UseRootMotion => useRootMotion;
|
||||
public bool IgnoreRootMotionY => ignoreRootMotionY;
|
||||
public IReadOnlyList<SkillEffect> Effects => effects;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user