AI


1. AIControllerFactory 类

概述

AIControllerFactory是CARLA仿真平台中实现AI控制器动态生成的核心工厂类,继承自ACarlaActorFactory。其职责包括:
- 定义支持的AI控制器类型(如行人、车辆等)
- 通过Unreal Engine的反射系统实现类型注册
- 提供标准化的Actor生成接口与错误处理机制

成员函数

GetDefinitions

  • 功能:返回工厂支持的AI控制器定义集合,用于引擎的类型发现与蓝图集成。
  • 代码示例
    TArray<FactorDefinitions> AAIControllerFactory::GetDefinitions() {
        // 使用工具类创建Walker控制器定义
        auto WalkerController = ABFL::MakeGenericDefinition(
            TEXT("controller"), TEXT("ai"), TEXT("walker")
        );
        // 绑定具体类对象
        WalkerController.Class = WalkerAIController::StaticClass();
        return { WalkerController };
    }
    
  • 参数说明
  • TEXT("controller"):控制器类型ID,需全局唯一。
  • TEXT("ai"):用于编辑器分类的元数据。
  • TEXT("walker"):语义标签,支持场景语义查询。

SpawnActor

  • 功能:根据描述和位置生成具体的AI控制器实例。
  • 关键参数
  • FTransform:指定生成位置和旋转。
  • FactorDescription:Actor类型和配置。
  • 方法签名
    FActorSpawnResult SpawnActor(
      const FTransform& SpawnAtTransform,
      const FActorDescription& Description,
      FActorSpawnParameters SpawnParameters = FActorSpawnParameters()
    );
    
  • 关键流程
  • 世界上下文验证:
    UWorld* World = GetWorld();
    if (!World || !World->IsGameWorld()) {
      UE_LOG(LogCarla, Fatal, TEXT("Invalid world context for AI controller spawning"));
      return FActorSpawnResult(ENullPointerError);
    }
    
  • 碰撞处理:强制忽略碰撞生成Actor(ESpawnActorCollisionHandleMethod::AlwaysSpawn)。
    SpawnParameters.SpawnCollisionHandlingMethod = 
      ESpawnActorCollisionHandlingMethod::AlwaysSpawn;  // 忽略物理碰撞
    }
    
  • 实例化与错误捕获: cpp AActor* SpawnedActor = World->SpawnActor<AActor>( Description.Class, SpawnAtTransform, SpawnParameters ); if (!SpawnedActor) { UE_LOG(LogCarla, Error, TEXT("Failed to spawn AI controller of type %s"), *Description.Id); return FActorSpawnResult(ESpawnActorErrorCode::UnknownError); }

错误处理体系

错误类型 触发条件 处理策略 错误码
ENullWorldContext 世界对象未初始化或无效 终止生成流程,返回错误码 0x8001
EClassNotRegistered 控制器类未注册到反射系统 检查 UCLASS() 宏与编译依赖
ESpawnCollisionBlock 碰撞处理策略未覆盖物理阻挡 强制设置为 AlwaysSpawn 模式

说明

  • ENullWorldContext
  • 触发时立即终止生成流程,避免无效操作占用资源。
  • 错误码 0x8001 用于快速定位问题场景。

  • EClassNotRegistered

  • 需验证反射系统配置(如 UCLASS() 宏是否遗漏)。
  • 检查编译依赖链是否包含目标类的头文件。

  • ESpawnCollisionBlock

  • 默认碰撞策略(如 AdjustIfPossible)可能无法覆盖复杂物理环境。
  • 强制使用 AlwaysSpawn 模式可确保生成流程完成,但可能引发物理重叠。

代码实现

  • 以空世界检查为例:
    if (World == nullptr) {
       E_LOG(logCarla, Error, TEXT("AAIControllerFactory: cannot spawn controller into an empty world."));
       return {};
    }
    

继承关系

  • 父类 :ACarlaActorFactory(CARLA仿真平台的Actor工厂基类)。
  • 子类 :通过重写 GetDefinitions 和 SpawnActor 实现定制化AI控制器生成。

2. WalkerAIController 类

定义与职责

  • 继承关系 :继承自 AActor,作为行人AI控制器的轻量级句柄。
    classDiagram
      AActor <|-- AWalkerAIController
      class AActor {
          +RootComponent: USceneComponent*
          +BeginPlay()
          +Tick(float DeltaSeconds)
      }
      class AWalkerAIController {
          -bIsActive: bool
          +SetMovementTarget(FVector Target)
          +OnNavigationComplete()
      }
    
  • 核心作用
  • 轻量级代理:作为服务端与客户端控制逻辑的中介,避免直接操作物理实体。
  • 状态同步:通过RPC(Remote Procedure Call)实现跨网络的状态同步。
  • 生命周期管理:处理控制器的激活/休眠状态切换。

构造函数

  • 初始化设置
  • 禁止Actor的Tick功能:PrimaryActorTick.bCanEverTick = false
  • 隐藏根组件:RootComponent->bHiddenInGame = true

  • 代码实现

    AWalkerAIController(const FObjectInitializer &ObjectInitializer)
        : Super(ObjectInitializer) {
        PrimaryActorTick.bCanEverTick = false;
        RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
        RootComponent->bHiddenInGame = true;
    }
    

成员变量与属性

  • PrimaryActorTick :设置为 false,禁止帧更新以优化性能。
  • RootComponent :默认场景组件,用于管理Actor的变换和渲染,游戏运行时不可见。

使用场景

  • 行人模拟 :在CARLA仿真中,通过此类控制行人的基础属性(如位置、状态)。
  • 多客户端协作 :作为服务端与客户端间的代理,传递控制指令。

3. Unreal Engine 集成机制

反射系统集成

  • UCLASS宏扩展 :UCLASS宏用于在Unreal Engine中注册C++类到反射系统,使得这些类可以被蓝图访问和继承,以及支持序列化、垃圾回收等功能。
  • 示例:
    UCLASS(
      Blueprintable,                     // 允许蓝图继承
      ClassGroup = (Custom),             // 自定义编辑器分类
      meta = (DisplayName = "AI Controller Factory")  // 编辑器显示名称
    )
    class CARLA_API AAIControllerFactory : public ACarlaActorFactory {
      GENERATED_BODY()
      // ...
    };
    
  • 属性暴露到编辑器
  • 示例:
    UPROPERTY(
      EditDefaultsOnly,                  // 仅在默认值编辑器中可修改
      Category = "AI Controller",        // 分类标签
      meta = (Tooltip = "Controller类型ID")  // 悬浮提示
    )
    FString ControllerTypeId = TEXT("default");      
    

Actor生成机制

  • 生成流程 :通过 World->SpawnActor,传入类名、变换参数和碰撞处理模式。
  • 方法生成实例
    auto *Controller = World->SpawnActor<AActor>(Description.Class, Transform, SpawnParameters);
    
  • SpawnActor内部流程
  • 内存分配:通过FMemory::Malloc在引擎内存池中分配对象空间。
  • 组件初始化:调用InitializeComponent()递归初始化子组件。
  • 注册到世界:将Actor添加到UWorld::PersistentLevel的Actor列表。
  • 事件触发:广播OnActorSpawned事件,通知监听系统。
  • 碰撞检测
    // 使用Sweep检测避免穿模
    FCollisionQueryParams CollisionParams;
    CollisionParams.bTraceComplex = true;  // 使用复杂碰撞体
    if (World->SweepTestByChannel(StartLoc, EndLoc, FQuat::Identity, ECC_Visibility, CollisionShape, CollisionParams)) {
      // 处理碰撞阻挡
    }
    
  • 碰撞处理 :强制生成(ESpawnActorCollisionHandleMethod::AlwaysSpawn)。

组件管理

  • 默认组件 :创建 USceneComponent 作为根组件,用于坐标系管理。
  • 示例
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    
  • 可见性控制 :通过 bHiddenInGame 属性隐藏非渲染组件。

4. 代码实例与用法

创建 AI 控制器

// 定义Walker控制器类型
auto WalkerController = ABFL::MakeGenericDefinition(
  TEXT("controller"), TEXT("ai"), TEXT("walker")
);

// 生成实例
FTransform SpawnTransform; // 设置生成位置
FactorSpawnResult Result = Factory->SpawnActor(SpawnTransform, WalkerController);

配置 Walker AI

  • 属性修改 :通过客户端接口更新行人的目标位置或移动速度。
  • 事件绑定 :注册碰撞事件或状态变更回调。

错误调试

  • 日志排查
    if (Controller == nullptr) {
      UE_LOG(logCarla, Error, TEXT("生成控制器失败"));
    }
    
  • 断点调试 :检查 World 对象有效性及 SpawnParameters 配置。

5. 相关文件与依赖

头文件依赖树

plaintext AI/ ├── AIControllerFactory.h ├── CarlaActorFactory.h ├── ActorBlueprintFunctionLibrary.h ├── WalkerAIController.h └── GameFramework/Actor.h

依赖的引擎模块

  • Actor系统 :GameFramework/Actor.h(Actor基类)。
  • 反射系统 :UObject/UObjectGlobals.h(支持 UCLASS 和 GENERATED_BODY)。
  • 工具库 :ActorBlueprintFunctionLibrary.h(提供快速定义工具)。

Build.cs配置示例

cpp PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "Carla", // CARLA插件模块 "NavigationSystem" // 依赖导航系统 });