[GAS] Aim Offset 트러블슈팅... 고개 하나 돌리는 데 4개의 버그를 만났다

2026. 2. 12. 18:10·Dev./UE 언리얼 엔진

TPS 게임에서 캐릭터가 카메라 방향을 따라 고개를 돌리는 건 너무나 익숙한 연출이다.

플레이어는 이 기능이 있는지조차 인식하지 못한다. 하지만 없으면 알아채기 쉽다.

 

“이 캐릭터 왜 이렇게 뻣뻣하지?”

 

Motion Matching 기반 애니메이션 시스템 위에 Aim Offset을 구현하는 과정에서 총 4개의 문제를 만났다.

이 글을 읽고 나면 다음을 얻게 된다.

  • Actor Rotation과 Root Bone Rotation이 왜 다른지, 그리고 언제 어떤 것을 써야 하는지
  • 각도 보간(Interpolation)에서 흔히 저지르는 수학적 실수와 해결법
  • AnimGraph에서 노드 배치 순서가 결과에 미치는 영향
  • 멀티플레이 환경에서 GetController()가 실패하는 이유와 대안
  • 애니메이션 스레드 안전성을 위한 캐싱 패턴


1. 문제 정의 — 4개의 증상

Aim Offset을 GS_SeekerAnimInstance 클래스에 C++로 구현했다. Get_AOValue() 함수가 카메라와 캐릭터 사이의 회전 차이를 계산하고, Enable_AO() 함수가 활성화 조건을 판단하는 구조다. 

* Aim Offset : 카메라 시선 방향에 따라 캐릭터의 상체, 특히 고개를 회전시키는 기법

 

기본 틀을 완성하고 실행했을 때, 다음 4가지 증상이 순차적으로 발견되었다.

증상 재현 조건
⚠️ 정면 오프셋 카메라가 정면을 향하고 있는데 고개가 이미 오른쪽으로 약 90도 돌아가 있다 게임 시작 직후, 어떤 입력도 하지 않은 상태
⚠️ 끊김 마우스를 빠르게 움직이면 고개가 끊기며 즉시 목표 각도로 순간이동한다 마우스를 좌우로 빠르게 휘두를 때
⚠️ 공격 후 고정 공격 몽타주 재생 후 Idle 상태로 복귀하면 고개가 굳어서 전혀 움직이지 않는다 공격 → 정지 → 마우스 회전
⚠️ 멀티플레이 미동작 로컬에서는 정상이지만, 다른 클라이언트 화면에서 내 캐릭터의 고개가 전혀 움직이지 않는다 멀티플레이 세션에서 타 플레이어 관점

2. 원인 분석 — 왜 이렇게 동작했는가

우선 모션 매칭에 구현되어 있는 기존 로직을 봐보자.

Simple Additive Lean

해석
이 Apply Mesh Space Additive 노드는 1D Blendspace 노드를 포즈 입력으로 사용하여 캐릭터 횡가속도에 기반해 메시에 좌우 기울기를 적용합니다. 횡가속도는 Get_LeanAmount 함수를 통해 계산됩니다. 이 포즈는 이후 모든 이동 애니메이션에 가산적으로 적용됩니다.
Arc animation coverage가 추가되면, Arc 동작 중 캐릭터에 과도한 기울기가 적용되지 않도록 이 가산적 포즈 적용 방식을 조정해야 합니다.

캐릭터가 달릴 때 몸을 자연스럽게 기울이는 '린(Lean)' 시스템에 대한 설명이다.

전력 질주를 하다가 갑자기 방향을 틀면 몸이 그쪽으로 쏠린다. 

 

그 자연스러운 움직임을 표현해주는 장치인데, 나중에 캐릭터가 아예 대각선으로 뛰는 전용 동작(아크)을 추가하면 몸이 너무 많이 꺾일 수 있으니 그때 가서 수치를 좀 깎아주라는 의미이다.

* 대각선으로 뛰는 모션은 아마 이미 몸을 틀면서 뛸텐데, 이 때 Apply Mesh Space Additive를 추가 적용하면 과하게 기울어질테니 다듬어라...

Apply Mesh Space Additive 노드를 쓰는 이유는?
이 노드는 "기존 애니메이션 위에 살짝 얹는다"는 개념이다.
- 달리기 애니메이션이 따로 있고, 그 위에 '기울기' 정보만 더하기(+) 하는 방식.
- 이렇게 하면 걷기, 뛰기, 뒤로 걷기 등 어떤 이동 애니메이션에서도 이 기울기 효과가 공통적으로 적용된다.

Simple Aim Offset

해석
이 Apply Mesh Space Additive 노드는 카메라와 캐릭터가 설정된 임계값 내에서 정렬될 때 캐릭터가 카메라의 향하는 방향을 바라보게 합니다. 이 임계값은 Enable_AO 함수에서 정의됩니다. 캐릭터의 추가 조준 포즈는 BlendSpace 내에 포함되어 있으며, 이 BlendSpace는 Get_AOValue 함수를 사용하여 캐릭터의 회전과 카메라 회전 간의 델타를 기반으로 축을 결정합니다.

이 예제 설정은 또한 블렌드 곡선을 지원하는 고급 관성 블렌딩 노드인 데드 블렌딩 노드를 사용합니다. 이는 블렌딩 시 팝 현상 없이 조준 오프셋을 재설정할 수 있도록 하기 위함입니다. 이 설정은 블렌딩이 항상 부드럽게 이루어지도록 보장합니다. 그렇지 않으면 오프셋으로 블렌딩하는 동시에 블렌딩 아웃하는 경우 블렌딩 문제가 발생할 수 있습니다.

하체는 가만히 있고 상체(고개)만 카메라 방향(조준점)으로 부드럽게 회전하게 만드는 기술에 대한 설명이다.

  • 동작 원리: 캐릭터의 회전값과 카메라의 회전값 차이(Delta)를 Get_AOValue 함수로 계산.
  • 데이터 활용: 계산된 값을 BS_Neutral_AO_Stand 같은 블렌드스페이스에 입력하여, 캐릭터가 위/아래/좌/우 중 어디를 쳐다볼지 결정.
  • Dead Blending (데드 블렌딩): UE5에서 권장되는 고급 관성 블렌딩 기술. 조준 상태를 끄거나 켤 때 포즈가 툭툭 끊기는 '팝(Popping)' 현상을 방지하여 부드럽게 연결해준다.

 


우선은 모션 매칭 AO 에셋을 리타게팅하여 에셋을 만들어두자.

Lean 모션 에셋
Aim Offset 모션 에셋 : 메시 스페이스 블렌딩을 활성화


2.1. 정면 오프셋: 메시(Mesh)의 숨겨진 -90도 회전

원본 코드는 Aim Offset의 기준 회전값으로 루트 본(Root Bone)의 월드 회전을 사용했다.

// ❌ 원본 코드 (문제 발생)
const FRotator RootRot = ChooserInputObject->RootTransform.Rotator();
const FRotator DeltaRot = UKismetMathLibrary::NormalizedDeltaRotator(ControllerRot, RootRot);

언리얼 엔진에서 캐릭터 메시는 블루프린트 뷰포트에서 기본적으로 Z축 기준 -90도 회전되어 배치된다.
3D 모델링 소프트웨어에서 캐릭터의 "정면"이 Y축을 향하도록 제작하는 경우가 많은데, 언리얼 엔진의 "정면"은 X축이기 때문이다. 이 차이를 보정하기 위해 메시 컴포넌트의 Rotation을 -90도로 설정하는 것이 표준이다.

 

문제는 이 -90도가 루트 본의 월드 좌표에 그대로 반영된다는 점이다.

따라서 캐릭터의 Actor가 Yaw 0도(정면)를 향하고 있어도, 루트 본은 Yaw -90도를 가리킨다.

컨트롤러가 정면(Yaw 0도)을 바라볼 때 계산되는 Delta는 0 - (-90) = +90이다.

정면을 보고 있는데 시스템은 "오른쪽으로 90도 돌아가 있다"고 판단한 것이다.

💡 핵심 원리: 화면에 보이는 캐릭터의 "몸통 방향"과 루트 본의 "수학적 방향"은 다를 수 있다. Aim Offset처럼 방향 차이를 계산하는 시스템에서는 항상 Actor Rotation(메시 오프셋이 반영되지 않은 순수한 캐릭터 방향)을 기준으로 삼아야 한다.

2.2. 끊김: 보간 없는 즉시 반영

원본 코드에서는 매 프레임 계산된 Delta 값을 곧바로 캐시 변수에 저장했다.

// ❌ 원본 코드 (보간 없음)
CachedAOValue = Get_AOValue_Internal(); // 매 프레임 즉시 반영

마우스가 한 프레임 만에 큰 각도를 이동하면, 캐릭터의 고개도 한 프레임 만에 그 각도로 이동한다. 실제 사람이라면 관성이 있어서 부드럽게 따라오겠지만, 코드에는 그런 관성이 없다.


2.3. 공격 후 고정: 너무 엄격한 활성화 조건

Enable_AO_Internal() 함수가 RotationMode == ERotationMode::Strafe 조건만을 검사했다.

// ❌ 원본 코드 (조건이 너무 엄격)
bool UGS_SeekerAnimInstance::Enable_AO_Internal()
{
    // Strafe 모드가 아니면 무조건 false
    return (ChooserInputObject->RotationMode == ERotationMode::Strafe);
}

공격 몽타주(Montage, 특정 시점에 강제로 재생하는 일회성 애니메이션)가 끝나고 캐릭터가 정지 상태로 복귀하는 과정에서, 내부적으로 RotationMode가 Strafe가 아닌 다른 상태로 잠시 전이되는 경우가 있다. 이때 AO가 꺼지고, 다시 켜지는 조건을 충족하지 못해 고개가 굳어버린 것이다.

 

추가로, AnimGraph 내에서 Aim Offset 노드의 배치 위치도 문제였다. 공격 몽타주를 출력하는 Slot 노드가 AO 노드보다 뒤에 위치해 있으면, 몽타주가 AO 결과를 완전히 덮어쓴다. 몽타주의 블렌드 아웃(서서히 사라지는 구간)이 끝나기 전까지는 AO가 보이지 않게 된다.


2.4. 멀티플레이 미동작: GetController()의 네트워크 한계

// ❌ 원본 코드 (네트워크 비안전)
if (AController* Controller = CachedOwnerCharacter->GetController())
{
    const FRotator ControllerRot = Controller->GetControlRotation();
    // ...
}

언리얼 엔진의 네트워크에서 Controller는 해당 캐릭터를 직접 조종하는 클라이언트와 서버에만 존재한다.

다른 클라이언트의 화면에 보이는 내 캐릭터는 Simulated Proxy(서버가 보내준 데이터를 재현하는 복제본)로서 Controller가 nullptr이다.

 

GetController()가 nullptr을 반환하면 if문 안에 진입하지 못하고,

AO 값은 FVector2D::ZeroVector가 되어 고개가 정면에 고정된다.

네트워크 역할 GetController() GetBaseAimRotation()
Autonomous Proxy (내 캐릭터) ✅ 유효 ✅ 유효
Simulated Proxy (남에게 보이는 내 캐릭터) ❌ nullptr ✅ 유효 (리플리케이션됨)
Authority (서버) ✅ 유효 ✅ 유효

 


3. 해결 과정

3.1. 기준 회전값 변경: Root Bone → Actor Rotation → BaseAimRotation

1차 수정에서는 기준을 RootTransform에서 GetActorRotation()으로 변경하여 메시 -90도 오프셋 문제를 해결했다.

2차 수정에서는 시선 회전값을 가져오는 방법도 GetControlRotation()에서 GetBaseAimRotation()으로 변경하여 네트워크 문제까지 해결했다.

// ✅ 최종 코드
FVector2D UGS_SeekerAnimInstance::Get_AOValue_Internal()
{
    FVector2D AO = FVector2D::ZeroVector;

    if (CachedOwnerCharacter)
    {
        // GetBaseAimRotation(): 엔진이 네트워크를 통해 자동 동기화하는 조준 방향.
        // Autonomous Proxy든 Simulated Proxy든 동일하게 유효한 값을 반환한다.
        const FRotator AimRot = CachedOwnerCharacter->GetBaseAimRotation();

        // GetActorRotation(): 메시의 본 회전이 아닌, 캐릭터 자체의 순수한 방향.
        // 메시가 -90도 회전되어 있어도 이 값에는 영향을 주지 않는다.
        const FRotator ActorRot = CachedOwnerCharacter->GetActorRotation();

        const FRotator DeltaRot = UKismetMathLibrary::NormalizedDeltaRotator(AimRot, ActorRot);

        // Pitch(상하 각도)를 BlendSpace 범위에 맞게 매핑한다.
        const float PitchMin = -80.0f;
        const float PitchMax = 60.0f;
        AO.X = FMath::GetMappedRangeValueClamped(
            FVector2D(PitchMin, PitchMax), FVector2D(-100.0f, 100.0f), DeltaRot.Pitch);

        AO.Y = DeltaRot.Yaw;
    }
    return AO;
}

GetBaseAimRotation()함수는 내부적으로 "Controller가 있으면 ControlRotation을 반환하고, 없으면 리플리케이션된 RemoteViewPitch 등을 조합하여 반환한다"는 로직을 이미 포함하고 있다. 네트워크 분기를 개발자가 직접 작성할 필요가 없다.


3.2. 각도 보간: 선형 보간의 함정과 최단 경로 회전

단순히 FMath::Vector2DInterpTo를 적용하면 Pitch(상하)는 문제없지만,

Yaw(좌우)에서 결함이 발생한다. 각도는 원형(Circular)이기 때문이다.

 

예를 들어 고개가 현재 -170도를 향하고 있고,

목표가 +170도일 때 선형 보간은 -170 → -100 → 0 → +100 → +170으로 340도를 빙 돌아간다.

실제로는 -170 → -180(=+180) → +170으로 20도만 움직이면 된다.

 

FMath::RInterpTo가 FRotator 전체를 대상으로 하기 때문에 FVector2D에 담긴 Pitch/Yaw 각각에 대해 적용하기 어렵다. FindDeltaAngleDegrees + 수동 보간 조합이 가장 유연하다.

// ✅ 최종 코드: NativeUpdateAnimation 내부의 보간 처리

const FVector2D TargetAO = Get_AOValue_Internal();
const float AOInterpSpeed = 15.0f;

// Pitch(상하)는 -90~+90 범위이므로 경계를 넘지 않는다. 선형 보간으로 충분하다.
CachedAOValue.X = FMath::FInterpTo(CachedAOValue.X, TargetAO.X, DeltaSeconds, AOInterpSpeed);

// Yaw(좌우)는 -180~+180 범위이며 경계를 넘을 수 있다.
// FindDeltaAngleDegrees: 두 각도 사이의 최단 거리(Signed)를 반환한다.
// 예) 현재 -170, 목표 +170 → Delta = -20 (시계 반대 방향으로 20도)
const float DeltaYaw = FMath::FindDeltaAngleDegrees(CachedAOValue.Y, TargetAO.Y);
const float YawStep = DeltaYaw * FMath::Clamp(DeltaSeconds * AOInterpSpeed, 0.0f, 1.0f);

// NormalizeAxis: 결과를 -180~+180 범위로 정리한다.
CachedAOValue.Y = FRotator::NormalizeAxis(CachedAOValue.Y + YawStep);

3.3. 활성화 조건 완화: 상태 기반 → 다중 조건 기반

기존의 단일 조건(Strafe 모드)을 복수의 OR 조건으로 확장했다.

// ✅ 최종 코드
bool UGS_SeekerAnimInstance::Enable_AO_Internal()
{
    if (!ChooserInputObject) return false;

    // 몽타주 재생 중에도 고개는 돌아가야 한다.
    const bool bIsMontagePlaying = IsAnyMontagePlaying();

    // 속도가 매우 낮으면 상태값이 뭐든 사실상 정지 상태다.
    const bool bIsAlmostStationary = (ChooserInputObject->Speed2D < 10.0f);

    // 기존 조건: 명시적 Idle이거나 Strafe 모드
    const bool bIsIdle = (ChooserInputObject->MovementState == EMovementState::Idle);
    const bool bIsStrafing = (ChooserInputObject->RotationMode == ERotationMode::Strafe);

    // 넷 중 하나라도 해당하면 AO를 활성화한다.
    if (bIsMontagePlaying || bIsAlmostStationary || bIsIdle || bIsStrafing)
    {
        return FMath::Abs(Get_AOValue_Internal().X) < 90.0f;
    }

    return false;
}
왜 이렇게 조건을 넓게 열었는가?
Aim Offset은 시각적 폴리싱(Polish) 기능이다. 너무 엄격한 조건으로 꺼지는 것보다, 조금 넓게 켜져 있는 것이 플레이어 경험에 좋을 거 같다고 생각했다. 과도한 각도(Pitch ±90도 이상)에서만 차단하면 부자연스러운 목 꺾임도 방지할 수 있다.

3.4. AnimGraph 노드 배치 순서 변경

코드 수정만으로는 “공격 후 고정” 문제가 완전히 해결되지 않았다. AnimGraph의 노드 연결 순서를 변경해야 했다.

변경 전 구조

  • 이 구조에서는 AO 노드가 MMBase 노드 이후에 있다.
  • 몽타주가 재생되면 Slot이 모든 포즈(AO 포함)를 덮어쓴다.
변경 후 구조

AO 노드를 앞으로 옮겼다. 고개 회전이 항상 적용된다.

 

추가로, 기존에 Blend Poses by bool 노드로 AO 적용 여부를 제어하던 방식을 제거하고, Apply Mesh Space Additive 노드의 Alpha 핀에 bCachedEnableAO 변수를 직접 연결했다.

➡️ True/False 포즈에 같은 입력을 넣고 있던 불필요한 노드를 줄여 그래프를 간결하게 만들었다.


3.5. 캐싱 패턴 적용: Lean Amount 포함

Get_LeanAmount() 함수도 동일한 캐싱 패턴으로 리팩토링했다.

// ✅ 최종 코드: NativeUpdateAnimation 내부
// NativeUpdateAnimation은 Game Thread에서 실행된다.
// 여기서 모든 "무거운 계산"을 마치고, 결과만 멤버 변수에 저장한다.

void UGS_SeekerAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
    // ... (캐릭터/컴포넌트 유효성 검증) ...

    if (CachedOwnerCharacter && CachedMovementComponent)
    {
        // Lean 값 계산 및 캐싱 (보간 포함)
        const float TargetLean = CalculateRelativeAccelerationAmount();
        CachedLeanAmount = FMath::FInterpTo(CachedLeanAmount, TargetLean, DeltaSeconds, 10.0f);

        // AO 값 계산 및 캐싱 (각도 보간 포함)
        const FVector2D TargetAO = Get_AOValue_Internal();
        // ... (Pitch/Yaw 보간 로직) ...

        // AO 활성화 조건 캐싱
        bCachedEnableAO = Enable_AO_Internal();
    }
}

// AnimGraph의 Worker Thread에서 호출되는 함수들.
// 이 함수들은 어떤 계산도 하지 않고, 저장된 값만 반환한다.
float UGS_SeekerAnimInstance::Get_LeanAmount()
{
    return CachedLeanAmount;
}

FVector2D UGS_SeekerAnimInstance::Get_AOValue()
{
    return CachedAOValue;
}

NativeUpdateAnimation()은 Game Thread에서 매 프레임 한 번 호출된다.

이 안에서 Movement Component, Controller 등 외부 객체에 접근하여 모든 계산을 끝내고 결과를 멤버 변수에 저장한다.

 

AnimGraph에서 BlueprintThreadSafe로 표시된 함수들(Get_AOValue, Get_LeanAmount)은 Worker Thread에서 호출되며, 이미 저장된 값을 꺼내기만 한다. 외부 객체에 접근하지 않으므로 스레드 경합(Race Condition)이 발생하지 않는다.

애니메이션 시스템은 멀티스레드로 돌아간다.
무거운 계산이나 외부 데이터 접근은 미리 다 해놓고(Caching),
애니메이션 그래프는 아주 가벼운 변수만 읽게 하는 것이 성능과 안정성의 핵심이다...!

 

 


4. 결과 및 개선 효과

Before / After 비교

항목 Before After
정면 조준 시 고개 방향 오른쪽으로 약 90도 틀어짐 정확히 정면을 향함
마우스 빠른 이동 시 고개가 ‘탁’ 하고 순간이동 부드럽게 따라옴 (InterpSpeed 조절 가능)
공격 후 Idle에서 AO 고개가 굳어서 미동작 즉시 정상 작동
180도 경계 회전 시 반대 방향으로 340도 빙 돌아감 최단 경로 20도로 자연스럽게 회전
멀티플레이 타 클라이언트 고개 미동작 (Controller == nullptr) 정상 동작 (BaseAimRotation 리플리케이션)
스레드 안전성 Worker Thread에서 외부 컴포넌트 직접 접근 Game Thread에서 캐싱 후 읽기 전용
AnimGraph 구조 불필요한 Blend Poses by bool 노드 존재 Alpha 핀 직결, 노드 1개 제거

유지보수 관점

보간 속도(AOInterpSpeed, LeanInterpSpeed)를 변수로 분리해 두었기 때문에,

향후 캐릭터별로 다른 고개 반응 속도를 적용하거나, 런타임에 동적으로 조절하는 것이 간단하다.

 

Enable_AO_Internal()의 조건도 OR 기반으로 열어두었으므로,

새로운 상태(예: 조준경 사용 중, 탈것 탑승 중)를 추가할 때 기존 로직을 건드리지 않고 조건만 추가하면 된다.


5. 학습 포인트

🔹Actor Rotation ≠ Root Bone Rotation.

언리얼 엔진에서 방향 차이를 계산할 때는 메시의 본이 아닌 Actor의 회전을 기준으로 삼는다.

블루프린트에서 메시 컴포넌트에 적용된 회전 오프셋은 본에 전파되지만 Actor에는 전파되지 않는다.

 

🔹각도는 숫자가 아니라 원이다.

-180도와 +180도는 같은 지점이다.

각도 값을 보간할 때는 반드시 FindDeltaAngleDegrees나 RInterpTo 같은 각도 전용 함수를 사용한다.

단순 선형 보간(FInterpTo, Lerp)은 경계에서 예기치 않은 회전을 만든다.

 

🔹GetController()는 로컬 전용이다.

멀티플레이 환경에서 다른 클라이언트에 보이는 캐릭터(Simulated Proxy)에게는 Controller가 없다.

시선 방향이 필요하면 GetBaseAimRotation()을 사용한다. 이 함수는 네트워크 역할에 관계없이 유효한 값을 반환한다.

 

🔹AnimGraph의 노드 순서는 레이어 순서다.

- 왼쪽(Left): 가장 기본이 되는 동작 (걷기, 뛰기, 대기)
- 오른쪽(Right): 나중에 덧칠해지는 수정 사항 (공격, 피격, 고개 돌리기, IK 발바닥 맞추기)

 

그래서 IK(발바닥 위치 보정)나 Aim Offset(시선 처리) 같은 '보정' 기능은 항상 그래프의 가장 오른쪽 끝(Output Pose 바로 앞)에 배치해야 한다. 그래야 이전의 어떤 동작(걷기, 공격, 점프)이 오더라도 마지막에 예쁘게 다듬어서 내보낼 수 있다!

 

🔹계산은 Game Thread, 읽기는 Worker Thread.

UE5의 애니메이션 시스템은 멀티스레드로 동작한다. 외부 컴포넌트 접근이 필요한 계산은 NativeUpdateAnimation()에서 마치고, BlueprintThreadSafe 함수에서는 캐싱된 값만 반환한다. 이것이 언리얼 엔진 애니메이션 프로그래밍의 기본 패턴이다.

'Dev. > UE 언리얼 엔진' 카테고리의 다른 글

UE5 Motion Matching 2편 :: Offset Root Bone, Warping, IK, Aim Offset  (1) 2026.03.13
UE5 Motion Matching 1편 :: 모든 캐릭터가 이동 시스템을 공유하는 구조  (2) 2026.03.12
UE5 :: 에셋 데이터 작업, 파이썬으로 자동화하기 (PSS 추출, 입력)  (1) 2026.02.10
언리얼 엔진5 :: 모션 매칭(Motion Matching)에 대해서  (0) 2026.02.10
[GAS] 모션매칭 SandboxCharacter를 MyCharacter로 전환하기  (0) 2026.02.07
'Dev./UE 언리얼 엔진' 카테고리의 다른 글
  • UE5 Motion Matching 2편 :: Offset Root Bone, Warping, IK, Aim Offset
  • UE5 Motion Matching 1편 :: 모든 캐릭터가 이동 시스템을 공유하는 구조
  • UE5 :: 에셋 데이터 작업, 파이썬으로 자동화하기 (PSS 추출, 입력)
  • 언리얼 엔진5 :: 모션 매칭(Motion Matching)에 대해서
raindrovvv
raindrovvv
raindrovvv 님의 블로그 입니다.
  • raindrovvv
    raindrovvv 님의 블로그
    raindrovvv
  • 전체
    오늘
    어제
    • 분류 전체보기 (170) N
      • Dev. (163) N
        • AI 인공지능 (27)
        • UE 언리얼 엔진 (81) N
        • Unity 유니티 (0)
        • Wwise 와이즈 (7)
        • 게임 네트워크 (8)
        • 그래픽스 Graphics (22)
        • 프로젝트 (8)
        • 기타 개발 관련 (10)
      • Computer Science (0)
        • 하드웨어 HW (0)
        • 소프트웨어 SW (0)
        • 통신 (0)
        • 데이터 (0)
      • 블로그 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    devlog
    바이브코딩
    TA
    unrealengine
    인디게임
    생산성
    AI
    게임개발
    트러블슈팅
    그래픽스
    언리얼엔진
    네트워크
    깃
    Unreal
    Wwise
    Git
    에이전트
    dev
    언리얼
    UE
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
raindrovvv
[GAS] Aim Offset 트러블슈팅... 고개 하나 돌리는 데 4개의 버그를 만났다
상단으로

티스토리툴바