实现的效果是UE运行后,有两个独立窗口,一个是蓝图创建添加到视口的(MainUI,带场景),一个是C++New 的SWindow(SecondUI,这种方式创建的窗口不能直接加载场景,但是可以用RenderTarget将主场景的画面渲染过来), 运行效果如下图:
一、c++创建新的窗口(这里用的是一个Actor类)
- 模块引用,在 .Build.cs中添加模块 "SlateCore", "Slate", "UMG"
- 头文件引用
#include "Blueprint/UserWidget.h"
#include "Widgets/SWindow.h"
#include "Kismet/GameplayStatics.h"
#include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h"
- 创建SWindow
NewWindowTemp = SNew(SWindow)
.AutoCenter(EAutoCenter::PrimaryWorkArea)
.ClientSize(ClientSize)
.SizingRule(ESizingRule::UserSized)
.CreateTitleBar(true)
.FocusWhenFirstShown(false)
.UseOSWindowBorder(true)
.UserResizeBorder(true)
.CreateTitleBar(true)
.SupportsTransparency(EWindowTransparency::PerWindow)
.InitialOpacity(1.0f)
.SupportsMaximize(true);TSharedRef<SWindow> NewWindow = NewWindowTemp.ToSharedRef();
注意 .ClientSize(FVector2D (1920,1080))的传值
- 我是UMG写的widget,所以需要t转SWidget(也可以直接用slate写),如果页面逻辑都是在蓝图Widget里面写的,可以把SecondWindowWidget暴露给蓝图,蓝图可以直接拿这个变量使用,做窗口之间的通讯。
.h
UPROPERTY(EditAnywhere, BlueprintReadOnly)
UUserWidget* SecondWindowWidget = nullptr;.cpp
UClass* WidgetClass = LoadClass<UUserWidget>(NULL, TEXT("/Game/UI/Widget_SecondUI.Widget_SecondUI_C"));
UUserWidget* UserWidget = nullptr;
TSharedPtr <SWidget> SlateWidget;
if (WidgetClass && GWorld->GetWorld())
{
UserWidget = CreateWidget<UUserWidget>(GWorld->GetWorld(), WidgetClass);
SecondWindowWidget = UserWidget;
}
if (UserWidget)
{
SlateWidget = UserWidget->TakeWidget();
}
这里要特别注意蓝图widget的名称格式是:name.name_C ("名称"+“.”+"名称"+“_C”),否则为空
不确定路径格式的可以鼠标悬浮在widget上,会有它的路径
- 窗口中添加内容并显示窗口
NewWindow->SetViewportSizeDrivenByWindow(true);
FSlateApplication::Get().AddWindow(NewWindow, true);
NewWindow->SetContent(SlateWidget.ToSharedRef());
NewWindow->ShowWindow();
NewWindow->SetWindowMode(EWindowMode::Windowed);NewWindow->SetOnWindowClosed(FOnWindowClosed::CreateLambda([=](const TSharedRef<SWindow>& WindowArg)
{
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
UKismetSystemLibrary::QuitGame(this, PlayerController, EQuitPreference::Quit, true);
}));
二、在新建的窗口中 用RenderTarget反射主场景的画面
- 创建一个RenderTarget
设置RenderTarget纹理的分辨率
- 创建一个Material,并编辑材质
将RenderTarget纹理作为输入连接到相应的节点或属性上
- 创建蓝图Actor,使用SceneCaptureComponent2D组件设置RenderTarget为捕捉组件的渲染目标,以实现实时反射或屏幕空间效果
- 将Actor放在场景中,调整要看到画面的视角
- 通过获取RenderTarget的引用,可以对其进行绘制、更新或擦除操作。这里是在蓝图中使用DrawMaterialToRenderTarget节点,将一个材质绘制到RenderTarget上。
实现效果就是第一张图