实现的效果是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上。

实现效果就是第一张图

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐