보간
9강. 보간
1. 이번 강의에서 해결할 문제
목표가 바뀌는 순간 적이 즉시 회전해 기계적으로 보입니다. AI 판단 주기는 낮게 유지하면서 화면에 보이는 회전만 매 프레임 부드럽게 갱신합니다.
2. 학습 목표
3. 핵심 개념
Lerp(A, B, α)는 두 값 사이 비율 α를 직접 정합니다. α=0은 A, α=1은 B입니다. 매 프레임 고정 α를 쓰면 프레임률에 따라 결과가 달라질 수 있습니다.
RInterpTo는 현재 회전, 목표 회전, DeltaSeconds와 InterpSpeed를 받아 목표에 가까워질수록 부드럽게 감속하는 회전을 만듭니다. 일정 각속도가 필요하면 RInterpConstantTo를 검토합니다.
4. 단계별 실습
C++ · 파일 경로: Source/TopDownSurvival/Enemies/MathAIEnemyCharacter.h
public:
void SetFacingTarget(AActor* NewTarget);
protected:
virtual void Tick(float DeltaSeconds) override;
UPROPERTY(EditDefaultsOnly, Category = "AI|Rotation",
meta = (ClampMin = "0.0"))
float RotationInterpSpeed = 6.0f;
private:
UPROPERTY()
TObjectPtr<AActor> FacingTarget;
C++ · 파일 경로: Source/TopDownSurvival/Enemies/MathAIEnemyCharacter.cpp
#include "AI/GameMathLibrary.h"
AMathAIEnemyCharacter::AMathAIEnemyCharacter()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
}
void AMathAIEnemyCharacter::SetFacingTarget(AActor* NewTarget)
{
FacingTarget = NewTarget;
SetActorTickEnabled(IsValid(FacingTarget));
}
void AMathAIEnemyCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (!IsValid(FacingTarget))
{
SetActorTickEnabled(false);
return;
}
const FRotator Desired = UGameMathLibrary::LookAtYaw(
GetActorLocation(), FacingTarget->GetActorLocation());
const FRotator Smoothed = FMath::RInterpTo(
GetActorRotation(), Desired, DeltaSeconds, RotationInterpSpeed);
SetActorRotation(Smoothed);
}
이 Tick은 현재 바라볼 목표가 있을 때 시각 회전만 처리합니다. 거리, Trace, 상태 전환과 MoveTo 요청은 AIController 또는 Behavior Tree의 제한된 주기로 실행합니다.
5. 코드와 수학·AI가 동작하는 이유
DeltaSeconds가 프레임 간 시간을 반영하므로 서로 다른 FPS에서도 비슷한 회전 감각을 만듭니다. 목표가 없을 때 Tick 자체를 꺼 비용을 줄입니다. 판단과 표현을 분리하면 AI는 0.25초마다 결정해도 회전은 부드럽게 보입니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
보간 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.