@@ -538,6 +538,40 @@ FUNCTION_NON_NULL_RETURN_START
538538
539539- **可以通过UClass来创建对象** :`NewObject<UCustomObject>()`等价于`NewObject<UObject>(GetTransientPackage(), UCustomObject::StaticClass())`
540540
541+ 通常,我们在虚幻引擎中接触到的绝大部分对象,它都是一个**UObject**,在代码层面,要创建任意的UObject,我们一般会使用这种方式:
542+
543+ ``` c++
544+ UObject* MyObject = NewObject<UObject>();
545+
546+ UTexture2D* MyTexture = NewObject<UTexture2D>();
547+
548+ UBlueprint* MyBlueprint = NewObject<UBlueprint>();
549+
550+ UStaticMesh* MyStaticMesh = NewObject<UStaticMesh>();
551+
552+ UNiagaraSystem* MyNiagaraSystem = NewObject<UNiagaraSystem>();
553+
554+ AActor* MyActor = NewObject<AActor>();
555+
556+ UStaticMeshComponent* MyStaticMeshComponent = NewObject<StaticMeshComponent>();
557+
558+ UWorld* World = NewObject<UWorld>();
559+
560+ ...
561+ ```
562+
563+ 这些语句在虚幻中并没有语法上的错误,它是可以编译通过的。
564+
565+ 但熟悉虚幻的小伙伴可能比较清楚,如果直接这样去创建对象,虽然确实能创建成功,但它的某些机制很有可能不能正常工作,因为那些类型伴随着特定的构造数据和逻辑,而引擎往往会将它包裹成新的接口,比如:
566+
567+ - 使用 ` UWorld::CreateWorld(...) ` 构造 UWolrd
568+ - 使用 ` UWorld::SpawnActor( ... ) ` 在对应世界中创建Actor
569+ - 使用` FKismetEditorUtilities::CreateBlueprint(...) ` 在编辑器下创建蓝图(UBlueprint)
570+ - 在Actor的构造函数中使用` UObject::CreateDefaultSubobject(...) ` 来创建隶属于当前Actor的组件结构
571+ - ...
572+
573+ 因此如果使用` NewObject() ` 创建的对象某些机制不能正常工作,很有可能引擎封装了特定的构造逻辑,如果没找到,可以试着寻找那些初始化和注册的逻辑,然后手动执行它。
574+
541575### 销毁
542576
543577除了UObject对象的创建,它的销毁,即生命周期的管理,也非常重要。
@@ -1379,6 +1413,131 @@ UObject* LoadedAsset = LoadObject<UObject>(nullptr,TEXT("/Game/CustomPackage.Cus
13791413- [ 知乎 - 海狗大人 | UEGamePlay框架:Pawn,Controller,APlayerState] ( https://zhuanlan.zhihu.com/p/16087843925 )
13801414- [ 知乎 - 海狗大人 | UEGamePlay框架:GameMode,GameState] ( https://zhuanlan.zhihu.com/p/16089018768 )
13811415
1416+ 当我们了解了这些结构体系之后,也就可以尝试去写一些大胆的代码,比如这是一段离线渲染静态模型的示例:
1417+
1418+ ``` c++
1419+ void Render (UStaticMesh* StaticMesh, FString OutFileName, FTransform CameraTransform, int32 InResolution)
1420+ {
1421+ EWorldType::Type WorldType = EWorldType::Editor;
1422+ UWorld* World = UWorld::CreateWorld(WorldType, false, "RenderWorld"); // 手动创建UWorld
1423+
1424+ UWorld* LastWorld = GWorld;
1425+ GWorld = World;
1426+
1427+ FWorldContext& EditorContext = GEditor->GetEditorWorldContext();
1428+ EditorContext.SetCurrentWorld(World); // Sky Light 的更新依赖于 GEgnine 的 Tick,它需要保证 GWorld == EditorContext.World()
1429+
1430+ const FURL URL;
1431+ World->InitializeActorsForPlay(URL);
1432+ World->BeginPlay(); // 手动执行UWorld的开始事件
1433+
1434+ FakeEngineTick(World, 0.03f);
1435+
1436+ AStaticMeshActor* Actor = World->SpawnActor<AStaticMeshActor>();
1437+ UStaticMeshComponent* StaticMeshComp = Actor->GetStaticMeshComponent();
1438+
1439+ ASkyAtmosphere* SkyAtmosphereActor = World->SpawnActor<ASkyAtmosphere>();
1440+ AExponentialHeightFog* ExponentialHeightFogActor = World->SpawnActor<AExponentialHeightFog>();
1441+
1442+ ADirectionalLight* DirectionalLightActor = World->SpawnActor<ADirectionalLight>();
1443+ UDirectionalLightComponent* DirectionalLightComponent = DirectionalLightActor->GetComponent();
1444+ DirectionalLightComponent->SetIntensity(12);
1445+
1446+ ASkyLight* SkyLightActor = World->SpawnActor<ASkyLight>();
1447+ USkyLightComponent* SkyLightComponent = SkyLightActor->GetLightComponent();
1448+ SkyLightComponent->SetMobility(EComponentMobility::Movable);
1449+ SkyLightComponent->bLowerHemisphereIsBlack = false;
1450+ SkyLightComponent->SetIntensity(2);
1451+ SkyLightComponent->RecaptureSky(); // 请求刷新天光
1452+
1453+ FakeEngineTick(World, 0.03f); // 执行等待渲染更新的Tick完成
1454+
1455+ UTextureRenderTarget2D* RenderTarget = NewObject<UTextureRenderTarget2D>(); // 初始化RT的数据
1456+ RenderTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA16f;
1457+ RenderTarget->InitAutoFormat(InResolution, InResolution);
1458+ RenderTarget->UpdateResourceImmediate(true);
1459+
1460+ FakeEngineTick(World, 0.03f); // 等待RT的资源提交
1461+
1462+ ETextureRenderTargetFormat RenderTargetFormat = RenderTarget->RenderTargetFormat;
1463+ FTextureRenderTargetResource* RenderTargetResource = RenderTarget->GameThread_GetRenderTargetResource();
1464+
1465+ ASceneCapture2D* SceneCaptureActor = World->SpawnActor<ASceneCapture2D>();
1466+ USceneCaptureComponent2D* SceneCaptureComp = SceneCaptureActor->GetCaptureComponent2D();
1467+ SceneCaptureComp->TextureTarget = RenderTarget;
1468+ SceneCaptureComp->bCaptureEveryFrame = false;
1469+ SceneCaptureComp->bOverride_CustomNearClippingPlane = true;
1470+ SceneCaptureComp->CustomNearClippingPlane = 0.01f;
1471+ SceneCaptureComp->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR;
1472+ SceneCaptureComp->ShowFlagSettings.Add(FEngineShowFlagsSetting{ TEXT("DistanceFieldAO"), false });
1473+ SceneCaptureComp->SetShowFlagSettings(SceneCaptureComp->ShowFlagSettings);
1474+
1475+ FakeEngineTick(World); // 等待SceneCapture的状态更新
1476+
1477+ SceneCaptureActor->SetActorTransform(CameraTransform); // 执行捕获
1478+ SceneCaptureComp->CaptureScene();
1479+
1480+ TArray<FLinearColor> Colors;
1481+ FReadSurfaceDataFlags ReadPixelFlags(RCM_MinMax);
1482+ FIntRect IntRegion(0, 0, RenderTarget->SizeX, RenderTarget->SizeY);
1483+ RenderTargetResource->ReadLinearColorPixels(Colors, ReadPixelFlags, IntRegion);
1484+
1485+ FImageView ImageView(Colors.GetData(), RenderTarget->SizeX, RenderTarget->SizeY);
1486+ FImageUtils::SaveImageByExtension(*OutFileName, ImageView); // 保存图像
1487+
1488+ World->DestroyWorld(false); // 还原状态
1489+ GEngine->DestroyWorldContext(World);
1490+ GWorld = LastWorld;
1491+ }
1492+
1493+ // 手动执行引擎的Tick更新
1494+ static void FakeEngineTick(UWorld* InWorld, float InDelta = 0.03f)
1495+ FApp::SetDeltaTime(InDelta);
1496+
1497+ GEngine->EmitDynamicResolutionEvent(EDynamicResolutionStateEvent::EndFrame);
1498+ GEngine->Tick(InDelta, false); // 其中包含了当前World的更新
1499+
1500+ FSlateApplication::Get().PumpMessages();
1501+ FSlateApplication::Get().Tick();
1502+
1503+ GFrameCounter++;
1504+
1505+ bool bIsTicking = FSlateApplication::Get().IsTicking();
1506+ if (!bIsTicking && GIsRHIInitialized) {
1507+ if (FSceneInterface* Scene = InWorld->Scene) {
1508+ ENQUEUE_RENDER_COMMAND(BeginFrame)([](FRHICommandListImmediate& RHICmdList) {
1509+ GFrameNumberRenderThread++;
1510+ GFrameCounterRenderThread++;
1511+ FCoreDelegates::OnBeginFrameRT.Broadcast();
1512+ });
1513+
1514+ ENQUEUE_RENDER_COMMAND(EndFrame)([](FRHICommandListImmediate& RHICmdList) {
1515+ FCoreDelegates::OnEndFrameRT.Broadcast();
1516+ RHICmdList.EndFrame();
1517+ });
1518+ FlushRenderingCommands();
1519+ }
1520+ ENQUEUE_RENDER_COMMAND(VirtualTextureScalability_Release)([](FRHICommandList& RHICmdList) {
1521+ GetRendererModule().ReleaseVirtualTexturePendingResources();
1522+ });
1523+ }
1524+
1525+ FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
1526+
1527+ FSlateApplication::Get().GetRenderer()->Sync();
1528+
1529+ FThreadManager::Get().Tick();
1530+
1531+ FTSTicker::GetCoreTicker().Tick(InDelta);
1532+
1533+ GEngine->TickDeferredCommands();
1534+
1535+ GEngine->EmitDynamicResolutionEvent(EDynamicResolutionStateEvent::EndFrame);
1536+
1537+ FAssetCompilingManager::Get().FinishAllCompilation();
1538+ }
1539+ ```
1540+
13821541## 其他
13831542
13841543### 委托
0 commit comments