icon안동민 개발노트

물리 시뮬레이션 성능 조정


 언리얼 엔진의 물리 시뮬레이션은 게임의 현실감과 상호작용성을 크게 향상시키지만, 동시에 상당한 계산 리소스를 요구합니다.

 이 절에서는 물리 시뮬레이션의 성능을 최적화하고 조정하는 다양한 방법을 살펴보겠습니다.

물리 시뮬레이션 서브스테핑 설정

 서브스테핑은 프레임 간 물리 계산의 정확도를 높이는 기법입니다.

UWorld* World = GetWorld();
FPhysScene* PhysScene = World->GetPhysicsScene();
 
FPhysSubstepSetup SubstepSetup;
SubstepSetup.MaxSubstepCount = 2;
SubstepSetup.MaxSubstepDeltaTime = 1.0f / 60.0f;
SubstepSetup.MaxSubstepImpactFraction = 0.5f;
 
PhysScene->SetSubsteppingParams(SubstepSetup);

LOD(Level of Detail) 시스템을 활용한 물리 최적화

 거리에 따른 물리 시뮬레이션 복잡도 조절

void APhysicsActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
 
    float DistanceToCamera = (GetActorLocation() - CameraLocation).Size();
    
    if (DistanceToCamera < NearDistance)
    {
        SetDetailedPhysics();
    }
    else if (DistanceToCamera < FarDistance)
    {
        SetSimplifiedPhysics();
    }
    else
    {
        DisablePhysics();
    }
}
 
void APhysicsActor::SetDetailedPhysics()
{
    // 고품질 물리 설정
    MeshComponent->SetSimulatePhysics(true);
    MeshComponent->SetEnableGravity(true);
    MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
}
 
void APhysicsActor::SetSimplifiedPhysics()
{
    // 간소화된 물리 설정
    MeshComponent->SetSimulatePhysics(true);
    MeshComponent->SetEnableGravity(true);
    MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}
 
void APhysicsActor::DisablePhysics()
{
    // 물리 비활성화
    MeshComponent->SetSimulatePhysics(false);
    MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

비동기 물리 시뮬레이션 구현

 물리 연산을 별도의 스레드에서 처리

UWorld* World = GetWorld();
World->bAsyncPhysicsTickEnabled = true;
World->AsyncPhysicsThreadSettings.MaxPhysicsTaskTime = 0.016f; // 16ms

물리 객체의 슬립 상태 관리

 불필요한 연산 방지를 위한 슬립 상태 관리

UPrimitiveComponent* PrimComponent = GetComponentByClass<UPrimitiveComponent>();
if (PrimComponent)
{
    PrimComponent->PutRigidBodyToSleep();
    PrimComponent->SetEnableGravity(false);
}
 
// 필요할 때 깨우기
void AWakeUpActor::WakeUp()
{
    UPrimitiveComponent* PrimComponent = GetComponentByClass<UPrimitiveComponent>();
    if (PrimComponent)
    {
        PrimComponent->WakeRigidBody();
        PrimComponent->SetEnableGravity(true);
    }
}

충돌 필터링 최적화

 불필요한 충돌 검사 제거

UPrimitiveComponent* PrimComponent = GetComponentByClass<UPrimitiveComponent>();
if (PrimComponent)
{
    PrimComponent->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore);
    PrimComponent->SetCollisionResponseToChannel(ECC_Vehicle, ECR_Ignore);
}

물리 프록시 메시 활용

 복잡한 메시의 물리 연산 간소화

UStaticMeshComponent* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetSimulatePhysics(true);
 
// 간소화된 콜리전 메시 설정
UBodySetup* BodySetup = MeshComponent->GetBodySetup();
BodySetup->CollisionTraceFlag = CTF_UseSimpleAsComplex;

대규모 물리 시뮬레이션 시나리오 관리

 파괴 가능한 환경 최적화

void ADestructibleEnvironment::OptimizePhysics()
{
    TArray<AActor*> FoundActors;
    UGameplayStatics::GetAllActorsOfClass(GetWorld(), ADestructibleActor::StaticClass(), FoundActors);
 
    for (AActor* Actor : FoundActors)
    {
        ADestructibleActor* DestructibleActor = Cast<ADestructibleActor>(Actor);
        if (DestructibleActor)
        {
            // 작은 파편은 물리 시뮬레이션에서 제외
            DestructibleActor->GetDestructibleComponent()->SetSimulatePhysics(false);
            DestructibleActor->GetDestructibleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        }
    }
}

모바일 및 VR 플랫폼을 위한 물리 최적화

 모바일 최적화 예시

#if PLATFORM_ANDROID || PLATFORM_IOS
    // 모바일 플랫폼에서의 물리 설정
    UPhysicsSettings* PhysicsSettings = UPhysicsSettings::Get();
    PhysicsSettings->bSimulateSkeletalMeshOnDedicatedServer = false;
    PhysicsSettings->bDisableActiveActors = true;
    PhysicsSettings->bEnableStabilization = true;
#endif

 VR 최적화

// VR에서의 물리 업데이트 빈도 조절
UWorld* World = GetWorld();
World->bAsyncPhysicsTickEnabled = true;
World->AsyncPhysicsTickRate = 120; // 120Hz 물리 업데이트

프로파일링 도구를 활용한 성능 병목 지점 식별

 언리얼 인사이트 활용

  1. 'Window > Developer Tools > Session Frontend' 열기
  2. 'Unreal Insights' 탭 선택
  3. 'Physics' 섹션에서 물리 연산 시간 및 병목 지점 분석

 코드 기반 프로파일링

SCOPE_CYCLE_COUNTER(STAT_PhysicsSimulation);
 
// 물리 시뮬레이션 코드
 
// 로그 출력
UE_LOG(LogTemp, Warning, TEXT("Physics Simulation Time: %f"), FPlatformTime::Seconds() - StartTime);

물리 시뮬레이션 품질과 성능 균형

  1. 중요도 기반 최적화
  • 플레이어 근처의 객체에 대해 고품질 물리 적용
  • 원거리 객체는 간소화된 물리 또는 애니메이션으로 대체
  1. 동적 품질 조정
void APhysicsManager::AdjustPhysicsQuality()
{
    float CurrentFPS = GetWorld()->GetDeltaSeconds();
    if (CurrentFPS < TargetFPS)
    {
        LowerPhysicsQuality();
    }
    else if (CurrentFPS > TargetFPS + Threshold)
    {
        IncreasePhysicsQuality();
    }
}
  1. 물리 객체 풀링
class FPhysicsObjectPool
{
public:
    AActor* GetOrCreatePhysicsObject()
    {
        if (Pool.Num() > 0)
        {
            return Pool.Pop();
        }
        return World->SpawnActor<APhysicsActor>(PhysicsActorClass);
    }
 
    void ReturnToPool(AActor* Actor)
    {
        Actor->SetActorHiddenInGame(true);
        Actor->SetActorEnableCollision(false);
        Pool.Push(Actor);
    }
 
private:
    TArray<AActor*> Pool;
};

 언리얼 엔진의 물리 시뮬레이션 성능을 최적화하는 것은 고품질의 게임플레이 경험을 유지하면서 리소스 사용을 효율적으로 관리하는 중요한 과정입니다. 서브스테핑 설정을 통해 물리 계산의 정확도를 높이고, LOD 시스템을 활용하여 거리에 따라 물리 복잡도를 조절함으로써 전체적인 성능을 개선할 수 있습니다.

 비동기 물리 시뮬레이션은 멀티코어 시스템에서 특히 유용하며, 메인 게임 스레드의 부하를 줄여 전반적인 게임 성능을 향상시킬 수 있습니다. 물리 객체의 슬립 상태 관리와 충돌 필터링 최적화는 불필요한 연산을 줄이는 데 효과적입니다.

 대규모 물리 시뮬레이션 시나리오에서는 객체 풀링, 간소화된 물리 프록시 사용, 그리고 중요도 기반의 시뮬레이션 관리가 중요합니다. 특히 파괴 가능한 환경이나 다수의 상호작용 객체가 있는 경우, 이러한 최적화 기법들이 큰 효과를 발휘합니다.

 모바일 및 VR 플랫폼에서는 하드웨어 제한을 고려한 추가적인 최적화가 필요합니다. 물리 업데이트 빈도 조절, 간소화된 충돌 체크, 그리고 플랫폼 특화 설정 등을 통해 성능을 개선할 수 있습니다.

 프로파일링 도구의 활용은 성능 최적화 과정에서 핵심적입니다. 언리얼 인사이트나 코드 기반 프로파일링을 통해 정확한 병목 지점을 식별하고, 이를 바탕으로 targeted optimization을 수행할 수 있습니다.

 물리 시뮬레이션의 품질과 성능 사이의 균형을 맞추는 것은 지속적인 과제입니다. 중요도 기반 최적화, 동적 품질 조정, 그리고 물리 객체 풀링 등의 기법을 통해 최적의 균형점을 찾을 수 있습니다. 이는 게임의 전반적인 품질을 유지하면서도 다양한 하드웨어에서 원활한 실행을 가능케 합니다.

 결론적으로, 물리 시뮬레이션 성능 최적화는 기술적 지식과 창의적 문제 해결 능력이 요구되는 복잡한 과정입니다. 다양한 최적화 기법을 상황에 맞게 적절히 조합하고 적용함으로써, 높은 품질의 물리 시뮬레이션을 효율적으로 구현할 수 있습니다. 이는 궁극적으로 더욱 몰입감 있고 반응성 높은 게임 경험을 플레이어에게 제공하는 데 기여할 것입니다.