Skip to content

Commit dc1213b

Browse files
committed
[commit] 迭代文档
1 parent d997527 commit dc1213b

30 files changed

Lines changed: 524 additions & 253 deletions

Docs/04-UnrealEngine/0.基础编程.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)