icon안동민 개발노트

물리 기반 조정 (중력, 충돌)


 언리얼 엔진의 강력한 물리 시스템을 활용하여 현실적이고 몰입감 있는 게임 환경을 만들 수 있습니다.

 이 절에서는 중력과 충돌 시스템의 세부적인 조정 방법을 살펴보겠습니다.

중력 조정

 전역 중력 스케일 조정

UWorld* World = GetWorld();
AWorldSettings* WorldSettings = World->GetWorldSettings();
WorldSettings->SetGravityZ(-980.0f); // 기본값의 2배

 사용자 정의 중력 필드 생성

ARadialForceActor* GravityField = GetWorld()->SpawnActor<ARadialForceActor>(Location, Rotation);
GravityField->ForceComponent->Radius = 1000.0f;
GravityField->ForceComponent->ForceStrength = -980.0f; // 음수 값은 끌어당기는 힘

충돌 시스템 설정

 충돌 프리셋 설정

  1. Project Settings > Collision로 이동
  2. New Object Channel 추가 (예 : "Player")
  3. Preset 설정
Player Preset:
- Block: WorldStatic, WorldDynamic, Pawn
- Overlap: Trigger
- Ignore: Vehicle

 복잡한 충돌 형상 처리

UStaticMeshComponent* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ComplexMesh"));
MeshComponent->SetCollisionProfileName(TEXT("BlockAllDynamic"));
MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComponent->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);

 트리거 볼륨 활용

UFUNCTION()
void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    // 트리거 로직
}
 
// 컴포넌트에 바인딩
TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnOverlapBegin);

물리 기반 이벤트 설정

 충돌 이벤트 처리

UFUNCTION()
void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
    float ImpactForce = NormalImpulse.Size();
    if (ImpactForce > DamageThreshold)
    {
        // 데미지 로직
    }
}
 
// 컴포넌트에 바인딩
MeshComponent->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);

다양한 환경에 따른 물리 조정

 저중력 환경

 달 표면 시뮬레이션

WorldSettings->SetGravityZ(-162.0f); // 지구 중력의 약 1/6

 수중 환경

 물의 저항을 시뮬레이션

void AMyCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    
    if (bIsUnderwater)
    {
        FVector Velocity = GetVelocity();
        FVector DragForce = -Velocity * WaterDragCoefficient;
        GetCharacterMovement()->AddForce(DragForce);
    }
}

성능 최적화를 위한 충돌 설정

 1. 단순화된 충돌 형상 사용

UBodySetup* BodySetup = MeshComponent->GetBodySetup();
BodySetup->CollisionTraceFlag = CTF_UseSimpleAsComplex;

 2. 충돌 채널 최적화

  • 불필요한 충돌 검사 제거를 위해 채널을 세분화하고 Ignore 설정 활용

 3. 물리 시뮬레이션 비활성화 영역 설정

APhysicsVolume* NoPhysicsVolume = GetWorld()->SpawnActor<APhysicsVolume>(Location, Rotation);
NoPhysicsVolume->bPhysicsOnContact = false;

물리 기반 퍼즐 및 메커니즘 구현

 균형 잡기 퍼즐 예시

void ABalancePuzzle::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    
    FVector RotationAxis = FVector::RightVector;
    float TiltAngle = FVector::DotProduct(GetActorUpVector(), FVector::UpVector);
    float RotationSpeed = (1.0f - TiltAngle) * MaxRotationSpeed;
    
    AddActorLocalRotation(RotationAxis * RotationSpeed * DeltaTime);
    
    if (TiltAngle < CriticalAngle)
    {
        OnPuzzleFailed();
    }
}

물리 기반 조정이 게임에 미치는 영향

 1. 게임플레이 다양성

  • 다양한 중력 환경으로 독특한 레벨 디자인 가능
  • 물리 기반 퍼즐로 창의적인 문제 해결 유도

 2. 현실감과 몰입도

  • 정교한 충돌 반응으로 실제 같은 상호작용 제공
  • 환경별 맞춤 물리 설정으로 다양한 분위기 연출

 3. 난이도 및 학습 곡선

  • 물리 법칙 기반 게임플레이로 직관적인 학습 가능
  • 물리 설정 조정으로 난이도 미세 조절 가능

 4. 최적화와 성능

  • 효율적인 충돌 설정으로 성능 향상
  • 복잡한 물리 연산의 적절한 사용으로 안정적인 프레임레이트 유지

 언리얼 엔진의 물리 시스템을 세밀하게 조정함으로써 개발자는 현실적이면서도 게임성이 뛰어난 환경을 만들 수 있습니다.

 중력과 충돌 시스템의 적절한 활용은 단순히 시각적인 효과를 넘어 게임의 핵심 메커니즘으로 작용할 수 있습니다.

 다양한 환경과 상황에 맞는 물리 설정을 통해 플레이어에게 항상 새롭고 흥미로운 경험을 제공할 수 있으며 이는 게임의 재미와 몰입도를 크게 향상시킵니다.