运行时生成NavModifierVolume

概述

引擎默认的ANavModifierVolume 如果在游戏运行时生成是不起作用的,它只有在编辑器中放置的时候起作用。为了解决这个问题,我们实现了ARuntimeNavModifierVolume
ARuntimeNavModifierVolume 是一个专门为运行时动态导航修改体积类。该类继承自 ANavModifierVolume 并实现了 IUnLuaInterface 接口,支持在蓝图预览模式和运行时模式下动态创建和管理导航网格修改区域。

类继承关系

ARuntimeNavModifierVolume 
├── ANavModifierVolume (父类)
└── IUnLuaInterface (接口)

主要功能特性

  • 运行时动态创建:支持在游戏运行时动态创建导航修改体积
  • 灵活的导航区域配置:可配置不同的导航区域类型(如障碍区域、可行走区域等)
  • 尺寸动态调整:支持运行时调整体积范围和缩放因子
  • 启用/禁用控制:可动态控制导航修改的启用状态
  • UnLua脚本支持:通过IUnLuaInterface接口支持Lua脚本集成

成员变量说明

公共属性

变量名 类型 默认值 说明
NavBoxExtent FVector FVector(100.f) 导航体积的范围(半尺寸)
NavAreaClass TSubclassOf<UNavArea> 导航区域类型
bUseRadius bool false 是否使用半径和高度模式
NavRadius float 100.f 半径模式下的半径值
NavHeight float 100.f 半径模式下的高度值
ScaleFactor float 1.f 导航网格缩放因子

受保护属性

变量名 类型 默认值 说明
bIsEnabled bool true 是否启用导航修改
bIsRuntimeCreated bool false 是否在运行时创建

方法说明

构造函数

ARuntimeNavModifierVolume(const FObjectInitializer&amp;amp; ObjectInitializer)
  • 功能:初始化导航修改体积
  • 默认设置
    • 启用状态:true
    • 运行时创建标记:false
    • 默认导航区域:UNavArea_Obstacle
    • 禁用碰撞检测

核心方法

InitializeRuntimeVolume

void InitializeRuntimeVolume(const FVector&amp;amp; InLocation, const FVector&amp;amp; InExtent, TSubclassOf<UNavArea> InAreaClass = nullptr)
  • 功能:初始化运行时导航修改体积
  • 参数
    • InLocation:体积的世界位置
    • InExtent:体积的范围(半尺寸)
    • InAreaClass:导航区域类型(可选,默认为nullptr)

SetVolumeExtent / GetVolumeExtent

void SetVolumeExtent(const FVector&amp;amp; InExtent)
FVector GetVolumeExtent() const
  • 功能:设置/获取体积范围

SetNavigationModifierEnabled / IsNavigationModifierEnabled

void SetNavigationModifierEnabled(bool bEnabled)
bool IsNavigationModifierEnabled() const
  • 功能:启用/禁用导航修改,并检查当前状态

AdjustNavmeshBoxSize

void AdjustNavmeshBoxSize(float InScaleFactor)
  • 功能:调整导航网格的大小
  • 参数InScaleFactor – 缩放因子

导航系统接口重写

GetNavigationData

virtual void GetNavigationData(FNavigationRelevantData&amp;amp; Data) const override
  • 功能:提供导航相关数据给导航系统
  • 逻辑:仅在启用状态下提供数据,根据bUseRadius选择使用半径模式或盒子模式

GetNavigationBounds

virtual FBox GetNavigationBounds() const override
  • 功能:获取导航边界
  • 逻辑:仅在启用状态下返回有效边界

UnLua接口实现

GetModuleName_Implementation

virtual FString GetModuleName_Implementation() const override
  • 返回值"Feature.ChestPVE.Script.Logic.Game.GPO.DungeonRuntimeNavModifierVolume"
  • 功能:返回对应的Lua模块名称

使用示例

蓝图使用示例

// 创建运行时导航修改体积
ARuntimeNavModifierVolume* NavVolume = GetWorld()->SpawnActor<ARuntimeNavModifierVolume>();

// 初始化体积
NavVolume->InitializeRuntimeVolume(
    FVector(1000, 500, 100),  // 位置
    FVector(200, 200, 50),    // 范围
    UNavArea_Obstacle::StaticClass()  // 区域类型
);

// 动态调整尺寸
NavVolume->SetVolumeExtent(FVector(300, 300, 75));

// 启用/禁用导航修改
NavVolume->SetNavigationModifierEnabled(true);

C++使用示例

// 在C++中创建和使用
ARuntimeNavModifierVolume* CreateDungeonNavVolume(UWorld* World, const FVector&amp;amp; Location, const FVector&amp;amp; Extent)
{
    FActorSpawnParameters SpawnParams;
    SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

    ARuntimeNavModifierVolume* Volume = World->SpawnActor<ARuntimeNavModifierVolume>(
        ARuntimeNavModifierVolume::StaticClass(),
        Location,
        FRotator::ZeroRotator,
        SpawnParams
    );

    if (Volume)
    {
        Volume->InitializeRuntimeVolume(Location, Extent);
    }

    return Volume;
}

技术实现细节

导航数据生成逻辑

  1. 启用检查:只有在bIsEnabledtrue时才生成导航数据
  2. 模式选择:根据bUseRadius选择不同的导航修改器创建方式:
    • 半径模式:使用NavRadiusNavHeight
    • 盒子模式:使用NavBoxExtent
  3. 缩放应用:所有尺寸参数都会乘以ScaleFactor

编辑器支持

  • 属性变更响应:在编辑器中修改属性时会自动重建导航数据
  • 预览模式支持:确保在蓝图预览模式下也能正常工作

注意事项

  1. 性能考虑:频繁调用RebuildNavigationData()可能影响性能,建议批量操作
  2. 内存管理:运行时创建的体积需要手动管理生命周期
  3. 碰撞设置:默认禁用碰撞,如需碰撞检测需要手动启用
  4. 导航系统依赖:需要确保导航系统已正确初始化

相关文件

  • 头文件DungeonRuntimeNavModifierVolume.h
  • 实现文件DungeonRuntimeNavModifierVolume.cpp

发表评论