3.2 关卡编辑器模式(EdMode):场景交互工具

EdMode 的定位

需要「在视口里点击、拖拽、框选,配合自定义渲染」,就要 EdMode——「关卡编辑器模式」(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/level-editor-modes-in-unreal-e-4b5a)。官方的建模工具、笔刷、PCG 编辑器、样条工具都是它。EdMode 给你三个能力:

  1. 模式工具栏 UI(左侧 Modes 面板里出现你的工具)
  2. 输入捕获:鼠标点击/移动/键盘事件
  3. 视口绘制:HUD、提示线、gizmo

最小骨架

// ① 模式类
class FMyEditorMode : public FEdMode
{
    virtual void Enter() override;          // 进入模式(显示 UI、初始化状态)
    virtual void Exit() override;           // 退出(清理)
    virtual bool InputKey(...) override;    // 鼠标/键盘事件
    virtual void Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI) override;  // 视口绘制
};

注册(模块 StartupModule):

FEditorModeRegistry::Get().RegisterMode<FMyEditorMode>(
    FMyEditorMode::EM_MyMode, FText::FromString("我的工具"),
    FSlateIcon(), true);

常用交互:鼠标点击选点

bool FMyEditorMode::InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event)
{
    if (Key == EKeys::LeftMouseButton && Event == IE_Pressed)
    {
        // 屏幕坐标 → 世界射线
        FSceneView View = ...;
        FViewportCursorLocation CursorLoc = ViewportClient->GetCursorWorldLocation(...);
        FVector Origin = CursorLoc.GetOrigin(), Dir = CursorLoc.GetDirection();
        // 射线检测
        FHitResult Hit;
        GetWorld()->LineTraceSingleByChannel(Hit, Origin, Origin + Dir * 10000, ECC_Visibility);
        if (Hit.bBlockingHit) { PlaceSomethingAt(Hit.Location); }
        return true;   // 事件已被消费
    }
    return false;
}

视口绘制

void FMyEditorMode::Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI)
{
    // 画点、线、网格、辅助提示
    PDI->DrawLine(Start, End, FLinearColor::Green, SDPG_World);
    PDI->DrawPoint(Point, FLinearColor::Red, 10.0f, SDPG_World);
}

配合HUD 文本(HUDCanvas / ULineBatchComponent)显示操作提示。工具的可用性一半在「视口里告诉用户当前在做什么」。

EdMode Toolkit(UI)

EdMode 可带 Toolkit(Slate 面板,显示在 Modes 面板里):

class FMyEditorModeToolkit : public FModeToolkit
{
    virtual TSharedPtr<SWidget> GetInlineWidget() override;   // 返回你的 Slate UI
};

典型结构:上方参数(半径、数量)+ 下方说明。参数变更通过 Toolkit 通知 Mode。

EdMode 的坑

  1. 生命周期:Mode 在进入/退出时反复创建销毁,别持有外部对象引用不清理
  2. 与默认选择的冲突:消费了事件返回 true,不消费返回 false——返回 true 会让「左键选择 Actor」失效,想保留选择行为要小心
  3. 多视口:每个视口独立调用 Render/InputKey,状态别假设单视口
  4. 撤销:EdMode 的场景修改同样要走 FScopedTransaction,否则不可撤销
  5. 性能:Render 每帧调用,重计算缓存住

什么时候别用 EdMode

如果工具只是「点了按钮批量处理场景里的 Actor」——不需要视口交互,普通菜单命令 + EUW 就够了。EdMode 的复杂度不值得。一个判断标准:用户要不要「看着视口、指着场景里的东西」操作。要 → EdMode;不要 → 其他方式。

延伸

  • 想做严肃的几何工具(布尔、推拉),看「几何体脚本用户指南」(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/geometry-scripting-users-guide-7bb8)
  • UE5 的建模模式本身就是 EdMode 的最佳示例——反射器 + 源码可读

心得:EdMode 工具的体验有三个层次:① 准(射线检测精确)② 看得见(视口提示到位)③ 可撤销。做到① 的工具能演示,做到②③ 的工具才敢给别人用。我们做场景笔刷工具时,60% 时间花在视口提示和撤销上,而不是功能本身。