게임 콘텐츠를 담는 가상공간이며 가상의 공간에 시간과 물리법칙을 부여한다. 그리고 가상공간에 적용할 여러 기능들을 설정한다.
가상세계를 구성하는 3차원 영역을 의미한다. 게임 콘텐츠를 구성하는 물체는 월드 영역 어딘가에 반드시 존재해야 하는데, 이를 위해 트랜스폼 Transform 이라는 구조체를 제공한다. 공간의 기본단위는 cm 이다.
가상의 공간에서 흐르는 시간이다. 가상의 세계에서의 시간은 초단위로 현실세계와 동일하게 흘러가지만, 시간을 멈추거나 느리게 혹은 빠르게 흘러가도록 시간의 스케일을 조절할 수 있다.
GetWorld()->GetDeltaSeconds() // DeltaTimeSeconds 가져오기
GetWorld()->GetTimeSeconds() // 게임 시작후 현재까지 경과된 게임시간
GetWorld()->GetUnpausedTimeSeconds() // 게임시작후 게임을 중지한 시간을 제외한 시간
GetWorld()->GetRealTimeSeconds() // 게임시작후 현재까지 경과된 현실세계의 시간
GetWorld()->GetAudioTimeSeconds() // 사용자가 게임을 중지한 시간을 제외한 현실 세계의 경과 시간
TimerManager 는 UWorld 클래스를 통해 얻을 수 있고,
Actor 는 월드에 속한다.
Actor 는 현재 자신이 속한 월드에 대한 참조를 GetWorld( ) 를 통해 얻을 수 있다.
void AAcotr :: BeginPlay()
{
Super::BeginPlay();
GetWorld()->GetTimerManager();
}
FTimerHandle WaitHandle;
float WaitTime; //시간을 설정하고
GetWorld()->GetTimerManager().SetTimer(WaitHandle, FTimerDelegate::CreateLambda([&]()
{
// 여기에 코드를 치면 된다.
}), WaitTime, false); //반복도 여기서 추가 변수를 선언해 설정가능
/*
주의사항
[&] 대신 [=] 로 외부 변수 복사 캡쳐를 사용하는것도 고려해야 한다.
만약 멤버변수를 참조 캡쳐 한다면 문제가 없을 수 있지만,
로컬변수를 참조한다면, 타이머 함수가 불려지는 시점에는 참조하려던 변수가 해지 되어
Null 참조 에러가 발 수 있다는 점
*/
GetWorld()->GetTimerManager().SetTimer(WaitHandle, FTimerDelegate::CreateLambda([=]()
{
// 여기에 코드를 치면 된다.
}), WaitTime, false); //반복도 여기서 추가 변수를 선언해 설정가능
월드 공간에 배치된 물체에 작용하는 물리적인 환경이다. 대표적인 물리환경으로 중력을 들 수 있다. 공간에 배치된 물체가 월드로부터 물리적인 영향을 받으려면 Collision 정보가 있어야 한다.
엔진이 제공하는 시각적인 기능. 빛과 이에 반응하는 Material 로 구성되며, 언리얼 엔진은 현실세계와 유사하게 동작하도록 물리기반 렌더링 ( Physically Based Rendering ) 시스템을 사용한다.
World 와 Level 의 차이점이 뭘까..
클래스 파생
: 월드는 맵이나 샌드박스 ( Actor 나 Component 가 존재할 수 있고, 렌더링 될 수 있는) 의 최상위 개체입니다. World 는 PersistentLevel 이 될수도 있고 ( 볼륨과 블루프린트 함수를 통해 Load / Unload 되는 StreamingLevel 모음), World Composition 으로 구성된 레벨의 모음이 될 수도 있다.
The World is the top level object representing a map or a sandbox in which Actors and Components will exist and be rendered. A World can be a single Persistent Level with an optional list of streaming levels that are loaded and unloaded via volumes and blueprint functions or it can be a collection of levels organized with a World Composition. In a standalone game, generally only a single World exists except during seamless area transitions when both a destination and current world exists. In the editor many Worlds exist: The level being edited, each PIE instance, each editor tool which has an interactive rendered viewport, and many more.
: 레벨 개체입니다 레벨의 Actor list, BSP Information 및 brush list을 포함합니다. 모든 레벨은 World를 Outer 로 갖고 있으며, World 는 PersistentLevel (지속 레벨)로 사용될 수 있습니다. 그러나 레벨이 OwningWorld에서 스트리밍되면 해당 레벨이 속한 월드를 나타냅니다. 레벨은 액터(조명, 볼륨, 메시 인스턴스 등)의 모음입니다. World 에 여러 Level 을 load 또는 unload 하여, streaming experience 를 만들 수 있다.
: 스트리밍에 필요한 데이터를 캡슐화하고 레벨이 메모리에서 스트리밍되어야 하는 경우에 대한 인터페이스를 제공하는 컨테이너 객체의 추상 기본 클래스
User unreal engine 에서 world 와 level 의 개념에 대해서 설명해줘, 차이점도 ChatGPT Unreal Engine에서 World와 Level은 게임 개발에서 매우 중요한 개념입니다. World는 게임에서의 전체 환경을 나타냅니다. 이는 여러 개의 Level로 구성될 수 있으며, 일반적으로 게임에서는 하나의 World에 여러 개의 Level이 포함됩니다. 이는 게임의 대규모 환경을 분할하여 작업할 수 있도록 하며, 게임의 성능과 개발 효율성을 향상시키는 데 도움이 됩니다. Level은 World에서 독립적인 공간입니다. 하나의 Level은 맵, 스테이지 또는 레벨로 불리며, 단일 씬 또는 여러 씬으로 구성될 수 있습니다. 일반적으로 레벨은 게임의 일부를 나타내며, 특정 게임 오브젝트, 캐릭터, 물리적 세계 및 환경을 포함합니다. 두 개념의 주요 차이점은 Level이 World의 일부라는 것입니다. 다시 말해, Level은 World의 하위 요소입니다. World는 게임에서 전체적인 공간을 나타내는 반면, Level은 World 안에서 특정 공간을 구성합니다. 또한, Level은 다른 Level과 독립적으로 로드되고 언로드될 수 있습니다. 예를 들어, 게임에서 새로운 지역으로 이동할 때, 현재 Level은 언로드되고 새로운 Level이 로드됩니다. 이를 통해 게임에서 부드러운 전환과 더 높은 성능을 구현할 수 있습니다. 즉, World와 Level은 게임 개발에서 중요한 개념으로, 게임의 대규모 환경을 효율적으로 작업하고 게임 플레이어가 흥미로운 경험을 하도록 구성하는 데 필수적입니다. User world 는 여러개가 구성될 수 있나? ChatGPT 네, World는 여러 개의 Level로 구성될 수 있습니다. 게임에서는 대개 하나의 World에 여러 개의 Level이 포함되어 있으며, 각 Level은 World 안에서 독립적인 공간으로 구성됩니다. 이를 통해 게임 환경을 분할하여 작업하고, 게임 플레이어가 흥미로운 경험을 하도록 구성하는 데 도움이 됩니다. 또한, 각 Level은 고유한 환경과 기능을 가지고 있으며, 게임에서 이동하거나 로드되고 언로드될 때 Level 간에 부드러운 전환을 제공할 수 있습니다. User Level A 와 Level B 가 있다면, A 에서 B 로 이동하는것은 월드 A 에서 월드 B 로 이동하는것과 같은것이네? ChatGPT Level A와 Level B가 하나의 World 안에 있다면, Level A에서 Level B로 이동하는 것은 World A에서 World B로 이동하는 것과 같은 개념입니다. 하지만 Level은 World의 일부분으로 구성되기 때문에, Level 간 이동은 보통 World 간 이동보다 더 빠르고 부드러운 전환이 가능합니다. 예를 들어, Level 간 이동은 기존 Level을 언로드하고 새로운 Level을 로드하는 방식으로 이루어질 수 있습니다. 따라서, 게임에서 Level 간 이동은 게임의 성능과 사용자 경험을 향상시키는 중요한 역할을 합니다. User world 는 persistance level 과 대응한다고 볼 수 있나? ChatGPT 일반적으로, "persistent level"은 Unreal Engine 4에서 사용되는 용어이며, "World"와 일치하는 개념입니다. 즉, "persistent level"은 게임에서 지속적으로 존재하는 Level을 나타냅니다. 이 Level은 게임 플레이어가 월드를 이동하거나 게임을 재시작할 때도 유지되는 것을 의미합니다. 따라서, "persistent level"은 World의 일부분으로 간주될 수 있으며, World는 하나 이상의 "persistent level"을 포함할 수 있습니다. 또한, 게임에서 다른 Level을 로드하고 언로드하면서도 "persistent level"은 게임의 일부분으로 지속되므로, 게임에서 중요한 역할을 합니다. 따라서, "persistent level"과 World는 유사한 개념으로 볼 수 있습니다. 하지만, "persistent level"은 일반적으로 Unreal Engine 4에서만 사용되는 용어이고, 다른 게임 엔진에서는 다른 용어를 사용할 수도 있습니다.
어떻게 보면 렌더링 될 객체의 집합이라고도 할 수 있을까. 3D 공간상에 배치될수 있는 객체 액터들의 집합 3D 공간상에 배치된다는 이야기는 카메라에 보여진다는 것이고 카메라, 즉, 화면에 영향을 줄 수 있는 객체들의 집합 이라고도 할 수 있을까. ULevelStreamingDynamic 은 동적으로 할당된 레벨 ( 액터들의 집합 )???? 인걸까
void UMyGameInstance::LoadLevel(TSoftObjectPtr<UWorld> levelObj)
{
UWorld* World = GetWorld(); // persistant 레벨 을 말하는거다, 메인레벨, 현재 띄어져 있는 레벨을 UWorld* 에 저장
ULevelStreamingDynamic* LevelStreamingToLaod = NewObject<ULevelStreamingDynamic>(World); // ULevelStreamingDynamic 을 생성할때 World 가 없으면 에러 발생
LevelStreamingToLaod->SetWorldAsset(LevelObj.Get());
// 스트리밍 레벨중, 원하는 레벨을 찾아서 로드 하는 코드
ULevelStreaming* FoundLevel = nullptr; // 비교레벨
for (ULevelStreaming* StreamingLevel : World->GetStreamingLevels())
{
if (StreamingLevel->GetWorldAssetPackageFName() == LevelStreamingToLoad->GetWorldAssetPackageFName())
{
FoundLevel = StreamingLevel;
break;
}
}
if (FoundLevel)
{
FoundLevel->SetShouldBeVisible(true);
FoundLevel->SetShouldBeLoaded(true);
}
}
UWorld* World = GetWorld();
// 레벨 로드
{
FLatentActionInfo LatentInfo;
UGameplayStatics::LoadStreamLevel(this, FName(*LevelPath), false, true, LatentInfo); // 레벨 로드
}
// 레벨 언로드
{
FTimerHandle WaitHandle;
float WaitTime = 5.0f;
World->GetTimerManager().SetTimer(WaitHandle, FTimerDelegate::CreateLambda([&]() {
FLatentActionInfo LatentInfo2;
UGameplayStatics::UnloadStreamLevel(this, FName(TEXT("LV_TestLevel1")), LatentInfo2, true); // 레벨 언로드
}), WaitTime, false);
}
FString LevelPath = TEXT("LevelPath");
FStreamableManager StreamableManager;
FSoftObjectPath LevelToLoad(LevelPath);
StreamableManager.RequestAsyncLoad(LevelToLoad, [&]() {
ULevelStreaming* LoadedLevel = UGameplayStatics::GetStreamingLevel(WorldContextActor, FName(TEXT("/Game/ProjectContent/Level/LV_TestLevel1")));
if (LoadedLevel)
{
LoadedLevel->SetShouldBeVisible(true);
LoadedLevel->SetShouldBeLoaded(true);
UE_LOG(LogTemp, Warning, TEXT("Level Loaded: %s"), *LevelPath);
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to load level: %s"), *LevelPath);
}
});
// #include "World.h"
class ENGINE_API UWorld final : public UObject , public FNetworkNotify
{
// ...
// 시간 관련
class FTimerManager* TimerManager;
inline FTimerManager& GetTimerManager() const
/**
* Returns the current Game Mode instance, which is always valid during gameplay on the server.
* This will only return a valid pointer on the server. Will always return null on a client.
*/
AGameModeBase* GetAuthGameMode() const { return AuthorityGameMode; }
/** Returns the current GameState instance. */
AGameStateBase* GetGameState() const { return GameState; }
}