🧠 오늘의 핵심 정리
- 점프 애니메이션 Landed 꼬임 원인 파악: AddForce는 한 프레임 뒤에 적용되어 착지 판정이 먼저 돌아가 버림
- 해결 방식 : 점프 직후 일정 시간은 착지 검사(ground check) 타이밍을 뒤로 미룸(코루틴 대신 “검사 시점 지연”)
- 점프 연타 시 애니메이션 클립이 1f에 고정 →
anim.Play로 매번 0f부터 재생되게 처리 - 추가 구현 : 무적+부스트(
ShieldAndBoost), 회복(Heal), 자석 기능 - 게임 상태가 Playing일 때만 입력 반응 + 이동 X/Z 분리로 컨트롤 안정화
🎮 본캠프 37일차 : 점프 애니메이션 디버깅 + 아이템 효과(무적/힐/자석) 기반 만들기
오늘은… 점프 애니메이션이 또 말썽이었습니다. Landed bool로 “땅이면 true / 점프면 false”를 만들었는데, 점프를 눌러도 Landed가 다시 true로 돌아가면서 계속 달리기 애니메이션이 재생되는 이상한 상황이 발생했습니다. 처음엔 진짜 “내가 뭘 잘못했지?” 싶어서 머리가 아팠는데, 원인을 파고 들어가니까 생각보다 물리 타이밍 문제였더라고요.
🧩 점프 애니메이션 문제 1 : AddForce 직후에도 “아직 땅”으로 판정되는 이유
InputSystem 점프 메서드 안에서 isJumping = true를 켜고 AddForce(Impulse)로 점프를 시키는 구조였는데, 제가 몰랐던 게 하나 있었습니다.
유니티 물리는 AddForce를 걸어도 그 프레임에 바로 Rigidbody가 “위로 이동”하지 않고, 다음 물리 프레임에 반영된다는 점이었습니다.
그래서 점프를 누른 직후에도 FixedUpdate에서 땅 체크가 먼저 돌아버리고, 결과적으로 “아직 땅이다!”로 판단되어 Landed = true가 되어버린 거죠. (제가 임시로 Time.time 조건을 넣어둔 이유가 딱 이 문제 때문…)
처음엔 코루틴으로 “점프 후 0.9초 뒤에 Landed true”로 처리했는데, 이건 점프 높이/속도에 따라 착지 타이밍이 달라지는 단점이 너무 컸습니다. 그래서 두 번째 시도는 착지 검사 자체를 점프 직후엔 하지 않도록 검사 시점을 늦추는 방식으로 생각을 바꿨고, 덕분에 의도대로 애니메이션이 돌아가게 됐습니다.


🌀 점프 애니메이션 문제 2 : 점프 연타 시 클립이 1f에 고정되는 현상
두 번째 문제는 더 어이가 없었습니다. 애니메이터는 정상적으로 전이되는데, 점프를 연타하면 플레이어가 점프 애니메이션 마지막 프레임(클립 1f)에 박혀서 빠져나오질 못하는 현상이 생겼어요.
근데 해결은 의외로 간단했습니다. 점프를 누를 때마다 anim.Play를 이용해서 점프 클립을 0f부터 다시 시작하게 만들면, 연타로 꼬이더라도 매번 초기 프레임으로 돌아가면서 자연스럽게 재생되더라고요. 약간 꼼수 같긴 한데… 결과적으로 플레이 감각이 훨씬 좋아졌습니다. (와!!!)
⚡ 추가 작업 : 무적/부스트/힐/자석 효과 기반 만들기
점프 이슈 잡으면서, 아이템 효과도 같이 틀을 잡았습니다. 오늘 들어간 핵심은 “무적 상태에서는 피해/감속이 적용되지 않게” 가드를 넣고, 무적 동안 속도 부스트도 같이 주는 구조입니다.
PlayerCondition : 무적 가드 + 무적부스트
// PlayerCondition.cs
bool invincible; // 무적효과
public void Slow(float multiplier = 2f, float duration = 3f)
{
if (invincible) return;
playerController.ChangeSpeedTemporaily(multiplier, duration);
}
public void Damaged()
{
if (health <= 0 || invincible) return;
// ...
}
public void ShieldAndBoost(float multiplier = 2f, float duration = 3f) // 무적부스트
{
StartCoroutine(ShieldCoroutine(multiplier, duration));
}
private IEnumerator ShieldCoroutine(float multiplier, float duration)
{
float originalSpeed = playerController.moveSpeed;
playerController.moveSpeed *= multiplier;
```
invincible = true;
yield return new WaitForSeconds(duration);
invincible = false;
playerController.moveSpeed = originalSpeed;
```
}
Heal은 아직 WIP지만, 체력이 회복되면 앞으로 당겨져 있던 거대 로봇을 다시 뒤로 밀어내는 연출까지 같이 묶어주려고 해서 flag를 하나 더 두었습니다.
Heal : 체력 회복 + 몬스터 위치 복구
// PlayerCondition.cs
bool monsterForward;
public void Heal()
{
if (health <= 0 || health == 2) return;
health = 2;
```
if (monsterForward)
{
monsterForward = false;
StartCoroutine(MoveMonsterBackward(new Vector3(0, 0, -7.7f), 1.5f));
}
```
}
자석 기능도 구조만 먼저 잡았습니다. 지금은 magnetActive 플래그만 켜고 끄는 형태인데, 다음 단계에서 Item 쪽에서 타겟 Transform을 받아서 끌려오게 만들 예정입니다.
Magnet (WIP) : 일정 시간 magnetActive 유지
// PlayerCondition.cs
public bool magnetActive = false;
public void ActivateMagnet(float duration)
{
if (!magnetActive)
{
magnetActive = true;
StartCoroutine(MagnetCoroutine(duration));
}
}
private IEnumerator MagnetCoroutine(float duration)
{
// ItemBase.SetMagnetTarget(this.transform);
yield return new WaitForSeconds(duration);
magnetActive = false;
// ItemBase.ClearMagnetTarget();
}
🕹️ 조작 안정화 : Playing 상태에서만 입력되게 + 이동 X/Z 분리
마지막으로, 게임이 끝났거나 대기 상태에서도 입력이 먹는 게 좀 거슬려서 GameState가 Playing일 때만 좌/우/점프/슬라이드가 동작하도록 조건을 걸었습니다.
Input 가드 : Playing에서만 반응
// PlayerController.cs
public void OnMoveLeft(InputAction.CallbackContext context)
{
if (context.performed && currentLane > 0 && GameManager.Instance.CurState == GameState.Playing)
{
currentLane--;
targetPosition.x = (currentLane - 2) * laneDistance;
}
}
public void OnSlide(InputAction.CallbackContext context)
{
if (GameManager.Instance.CurState != GameState.Playing) return;
// ...
}
그리고 이동은 X축과 Z축을 분리해서 더 직관적으로 만들었습니다. (Z는 앞으로 계속 증가, X는 목표 lane으로 MoveTowards)
이동 X/Z 분리
// PlayerController.cs
float nextZ = transform.position.z + moveSpeed * Time.deltaTime;
float nextX = Mathf.MoveTowards(transform.position.x, targetPosition.x, moveSpeed * Time.deltaTime);
transform.position = new Vector3(nextX, transform.position.y, nextZ);
📌 오늘의 회고
오늘은 점프 애니메이션 하나 때문에 시작부터 머리가 깨질 뻔했는데, 원인이 “내 코드가 이상한 게 아니라 물리 타이밍”이라는 걸 알아내니까 오히려 마음이 좀 편해졌습니다. 특히 AddForce가 다음 프레임에 적용된다는 걸 이번에 제대로 배웠고, 앞으로는 애니메이션/물리 연결할 때 “검사 타이밍”을 더 신경 써야겠다고 느꼈습니다.
그리고 점프 연타로 클립이 1f에 박히는 문제도 anim.Play로 깔끔하게 정리해서 다행…! (이거 해결됐을 때 진짜 속이 시원했다)
🔜 내일 할 일
- 점프 애니메이션 Landed 판정 로직 최종 정리 (검사 지연 방식 안정화)
- Heal 완성 : 체력 회복 시 거대 로봇 위치/연출까지 자연스럽게 복구
'내일배움캠프 본캠프' 카테고리의 다른 글
| [내일배움캠프 39일차 TIL] 팀 프로젝트 발표 (0) | 2025.11.21 |
|---|---|
| [내일배움캠프 38일차 TIL] 펫 시스템 (0) | 2025.11.20 |
| [내일배움캠프 36일차 TIL] 몬스터 애니메이션 (0) | 2025.11.18 |
| [내일배움캠프 35일차 TIL] 플레이어 움직임 (0) | 2025.11.17 |
| [내일배움캠프 34일차 TIL] 3D팀 프로젝트 (0) | 2025.11.14 |