## 概述
引擎默认的`ANavModifierVolume` 如果在游戏运行时生成是不起作用的,它只有在编辑器中放置的时候起作用。为了解决这个问题,我们实现了`ARuntimeNavModifierVolume`
`ARuntimeNavModifierVolume` 是一个专门为运行时动态导航修改体积类。该类继承自 `ANavModifierVolume` 并实现了 `IUnLuaInterface` 接口,支持在蓝图预览模式和运行时模式下动态创建和管理导航网格修改区域。
## 类继承关系
```cpp
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` | 是否在运行时创建 |
## 方法说明
### 构造函数
```cpp
ARuntimeNavModifierVolume(const FObjectInitializer&amp; ObjectInitializer)
```
- **功能**:初始化导航修改体积
- **默认设置**:
- 启用状态:`true`
- 运行时创建标记:`false`
- 默认导航区域:`UNavArea_Obstacle`
- 禁用碰撞检测
### 核心方法
#### InitializeRuntimeVolume
```cpp
void InitializeRuntimeVolume(const FVector&amp; InLocation, const FVector&amp; InExtent, TSubclassOf<UNavArea> InAreaClass = nullptr)
```
- **功能**:初始化运行时导航修改体积
- **参数**:
- `InLocation`:体积的世界位置
- `InExtent`:体积的范围(半尺寸)
- `InAreaClass`:导航区域类型(可选,默认为nullptr)
#### SetVolumeExtent / GetVolumeExtent
```cpp
void SetVolumeExtent(const FVector&amp; InExtent)
FVector GetVolumeExtent() const
```
- **功能**:设置/获取体积范围
#### SetNavigationModifierEnabled / IsNavigationModifierEnabled
```cpp
void SetNavigationModifierEnabled(bool bEnabled)
bool IsNavigationModifierEnabled() const
```
- **功能**:启用/禁用导航修改,并检查当前状态
#### AdjustNavmeshBoxSize
```cpp
void AdjustNavmeshBoxSize(float InScaleFactor)
```
- **功能**:调整导航网格的大小
- **参数**:`InScaleFactor` - 缩放因子
### 导航系统接口重写
#### GetNavigationData
```cpp
virtual void GetNavigationData(FNavigationRelevantData&amp; Data) const override
```
- **功能**:提供导航相关数据给导航系统
- **逻辑**:仅在启用状态下提供数据,根据`bUseRadius`选择使用半径模式或盒子模式
#### GetNavigationBounds
```cpp
virtual FBox GetNavigationBounds() const override
```
- **功能**:获取导航边界
- **逻辑**:仅在启用状态下返回有效边界
### UnLua接口实现
#### GetModuleName_Implementation
```cpp
virtual FString GetModuleName_Implementation() const override
```
- **返回值**:`"Feature.ChestPVE.Script.Logic.Game.GPO.DungeonRuntimeNavModifierVolume"`
- **功能**:返回对应的Lua模块名称
## 使用示例
### 蓝图使用示例
```cpp
// 创建运行时导航修改体积
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++使用示例
```cpp
// 在C++中创建和使用
ARuntimeNavModifierVolume* CreateDungeonNavVolume(UWorld* World, const FVector&amp; Location, const FVector&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. **启用检查**:只有在`bIsEnabled`为`true`时才生成导航数据
2. **模式选择**:根据`bUseRadius`选择不同的导航修改器创建方式:
- 半径模式:使用`NavRadius`和`NavHeight`
- 盒子模式:使用`NavBoxExtent`
3. **缩放应用**:所有尺寸参数都会乘以`ScaleFactor`
### 编辑器支持
- **属性变更响应**:在编辑器中修改属性时会自动重建导航数据
- **预览模式支持**:确保在蓝图预览模式下也能正常工作
## 注意事项
1. **性能考虑**:频繁调用`RebuildNavigationData()`可能影响性能,建议批量操作
2. **内存管理**:运行时创建的体积需要手动管理生命周期
3. **碰撞设置**:默认禁用碰撞,如需碰撞检测需要手动启用
4. **导航系统依赖**:需要确保导航系统已正确初始化
## 相关文件
- **头文件**:`DungeonRuntimeNavModifierVolume.h`
- **实现文件**:`DungeonRuntimeNavModifierVolume.cpp`