
天啊游戏开发行业大变天AI可以开发游戏啦——这一类标题最近频繁出现在技术社区里看多了很容易让人产生两种极端情绪要么觉得游戏开发者马上要失业要么觉得这就是又一个蹭 AI 热度的文字游戏。我的判断是两种都不准确。AI 确实让“一个人做一款游戏”的门槛大幅降低了但它的作用方式不是替你完成创作而是把 UE5 的工程摩擦降到最低。过去新手要在引擎设置、C 编译、蓝图连接、碰撞配置之间来回折腾今天在 TraeAI 这类 AI 编程工具辅助下你可以直接生成大部分样板代码把时间留给玩法设计。这篇文章不贩卖情绪只给一条可以完整跑通的路径用 TraeAI 配合 UE5从零做出一个“马里奥式”横版平台跳跃原型包含角色左右移动、跳跃、金币收集加分的核心闭环。文章会讲清楚 AI 能做什么、不能做什么、有哪些坑以及每一步怎么验证。1. 这篇文章真正要解决的问题先问一个实在的问题有多少人尝试过用 UE5 做一个小游戏最后倒在了第一步比如蓝图节点太多逻辑一旦复杂就看不懂想用 C 却不知道文件放在哪里编译报错时面对几百行日志完全无从下手想做一个最普通的“碰到金币加分”也要在多个类、多个资产之间来回切换。这些不是能力问题而是工具链的摩擦问题。传统开发流程里做一个平台跳跃原型通常要经历创建工程选择模板搞清楚 C 和蓝图的组织方式写一个角色类处理输入、移动、跳跃布置关卡加碰撞体和触发器写一个 GameMode 管理分数和游戏状态创建 UI 控件绑定得分数据反复编译、调试碰撞和输入问题。对老手来说这套流程可能只要半天对新手来说可能要一周甚至更久因为在第 2 步和第 6 步会消耗大量时间。而 TraeAI 这类工具改变的关键点是把“从零写代码”变成“描述需求、让 AI 生成、自己审查验证”。它并不能消灭游戏开发的复杂度但能消灭大部分重复性的“体力活”。这篇文章适合三类人刚接触 UE5 想快速跑通一个完整游戏原型的新手做独立游戏想在早期快速验证玩法的开发者以及已经在用 VS、Rider 写 UE5想知道 AI 编程工具能不能接入现有工作流的 C 使用者。不适合谁如果目标是 AAA 项目的工业化管线、大规模多人在线网络同步AI 目前还更像是辅助而不是替代。这一点在后面会展开。2. TraeAI 定位与 UE5 协同开发的基本原理2.1 TraeAI 是什么TraeAI 是一款以 AI 为核心的集成开发环境IDE它保留了工程管理、Git、终端、代码编辑等常规能力同时把 AI 对话、代码补全、代码生成、问题修复放在同一个界面里。你可以直接在对话窗口里说“帮我写一个继承 ACharacter 的跳跃角色类”它会读取当前工程的文件结构然后生成或修改代码。它和 UE5 的关系值得说清楚。UE5 是一个完整的游戏引擎负责场景渲染、物理、动画、音频、蓝图脚本等TraeAI 则是一个代码层的工具它能读写的是 UE5 工程里的 C 源码、配置文件、构建脚本。2.2 为什么 AI 能“开发” UE5 游戏打开任何一个 UE5 C 工程你会看到这些内容.uproject工程文件、Source/目录下的 C 代码、Config/目录下的配置、以及大量.uasset资产文件。真正的游戏逻辑一部分写在蓝图里一部分写在 C 类里。很多教程会让你从纯蓝图做起但纯蓝图项目对 AI 代码工具很不友好。因为蓝图是图形化的脚本保存成的是二进制资产TraeAI 这类 IDE 无法像阅读文本那样去分析节点连线。这就是为什么大量 AI 游戏开发教程都建议用 C 工程只有 C 源码才是 IDE 能直接读写的。更稳妥的判断是如果你想最大化 AI 的帮助从一开始就创建包含Source目录的 C 项目。纯蓝图项目虽然也能让 AI 帮你分析报错、写文档但 AI 能介入的深度完全不同。2.3 核心概念角色、GameMode 与增强输入在进入代码之前先解释将要反复出现的几个术语避免被概念绕晕。ActorUE5 场景中所有可以被放置的对象小到金币大到整个关卡。Character继承自 Pawn 的游戏角色类自带胶囊体碰撞和角色移动组件。GameMode定义一局游戏的规则比如玩家出生点、默认角色、如何计分。Enhanced InputUE5 主推的输入框架把“按 A 键”和“角色向左移动”分开管理按键映射更灵活。UMGUE5 的 UI 系统用来做血条、得分、菜单等界面。这几个概念会贯穿整个示例。如果想看它们之间的对比可以参考下面这张表维度蓝图方式C 方式上手速度快可视化连接节点慢需要了解类和 API可维护性逻辑复杂时容易乱代码可读、可重构AI 工具介入深度低AI 读不到节点图高AI 可直接读写源码推荐场景原型快测、简单交互正式项目、复杂逻辑3. 环境准备与项目建立3.1 软件环境本文示例的核心环境如下版本细节请以你本机实际安装为准操作系统Windows 10 / Windows 11游戏引擎Unreal Engine 5建议 5.1 或更新版本下载和启动通过 Epic Games Launcher 完成AI 编程工具TraeAI 桌面版编译环境Visual Studio 2022安装时勾选“使用 C 的游戏开发”工作负载。TraeAI 是基于桌面 IDE 形态的工具安装完成后直接启动即可。3.2 创建 UE5 C 项目打开 Epic Games Launcher启动已安装的 UE5 版本在项目浏览器中选择“游戏”分类下的“第三人称游戏”模板或直接选“空白”模板。关键的一步在项目默认设置里项目类型一定要选 C而不是 Blueprint。为什么必须选 C前面已经解释过AI 工具需要读文本形式的源码。选择 C 模板后工程根目录会生成MyProject/ ├── Config/ ├── Content/ ├── Source/ │ ├── MyProject/ │ │ ├── MyProject.Build.cs │ │ ├── MyProject.cpp │ │ ├── MyProject.h │ │ ├── MyProjectCharacter.cpp │ │ └── MyProjectCharacter.h │ ├── MyProject.Target.cs │ └── MyProjectEditor.Target.cs ├── MyProject.uproject └── ...如果已经创建了纯蓝图项目也有补救办法在 UE 编辑器菜单中找到“新建 C 类”New C Class随便创建一个类UE 会自动生成Source目录并触发一次编译让项目从蓝图工程变成 C 工程。3.3 在 TraeAI 中导入项目启动 TraeAI 后用类似“文件 - 打开文件夹”的方式直接选中 UE5 工程根目录也就是MyProject.uproject所在的目录。打开后先做一件事让 TraeAI 了解项目结构。可以这样提问请先阅读以下项目文件不要做任何修改 - MyProject.uproject - Source/MyProject/MyProject.Build.cs - Source/MyProject.Target.cs - Source/MyProjectEditor.Target.cs 然后告诉我 1. 这个项目依赖哪些模块 2. 默认角色类是什么 3. 创建新类时应该放在 Source 的哪个子目录。这看起来像一句普通对话但它决定了 AI 后续生成的代码是否放在正确位置、是否引用了正确的模块。素材越多AI 的上下文就越准确。另外建议在 TraeAI 的忽略文件配置中排除 UE5 自动生成的目录例如Intermediate/、Binaries/、Saved/、.vs/。这些目录文件量大、内容不稳定不该进入 AI 的上下文也不该进入 Git 提交。4. 用 TraeAI 写一个马里奥式角色控制4.1 提示词设计原则很多人用 AI 编程工具效果差问题往往不在工具而在提示词。在 UE5 场景下一个合格的提示词至少要包含四个信息引擎版本、项目类型、目标类和任务约束。反例是这样写一个马里奥角色这个提示词会让 AI 无从下手它不知道你的项目是 C 还是蓝图、不知道放在哪个模块、不知道要不要考虑输入系统。正例应该像这样你是资深 UE5 C 工程师。当前项目是 UE5 C 工程的根目录模块名是 MyProject。 请完成以下任务 1. 创建 ASuperMarioCharacter 类继承 ACharacter实现横版平台跳跃角色的左右移动和跳跃 2. 使用 Enhanced Input 输入系统类中暴露 MoveAction、JumpAction、DefaultMappingContext 三个 UPROPERTY供蓝图指定资产 3. 在 BeginPlay 中把 DefaultMappingContext 注册到当前玩家控制器 4. 代码放在 Source/MyProject/Characters/ 目录下 5. 使用英文注释不要删除已有代码输出前说明每个文件的放置路径。把目标、约束、路径说清楚后AI 生成的代码质量会明显提高。这也是 TraeAI 这类 AI IDE 和搜索引擎问答最大的区别它有当前工程上下文提词越具体落点越准。4.2 角色类代码让 TraeAI 生成之后核心代码大致对应下面的结构。头文件Source/MyProject/Characters/SuperMarioCharacter.h#pragma once #include CoreMinimal.h #include GameFramework/Character.h #include InputActionValue.h #include SuperMarioCharacter.generated.h class UInputAction; class UInputMappingContext; UCLASS() class MYPROJECT_API ASuperMarioCharacter : public ACharacter { GENERATED_BODY() public: ASuperMarioCharacter(); protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaTime) override; virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; UFUNCTION() void Move(const FInputActionValue Value); UFUNCTION() void StartJump(); UFUNCTION() void StopJump(); UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input) class UInputAction* MoveAction; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input) class UInputAction* JumpAction; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input) class UInputMappingContext* DefaultMappingContext; };实现文件Source/MyProject/Characters/SuperMarioCharacter.cpp#include SuperMarioCharacter.h #include EnhancedInputComponent.h #include EnhancedInputSubsystems.h #include InputActionValue.h #include InputMappingContext.h #include GameFramework/CharacterMovementComponent.h ASuperMarioCharacter::ASuperMarioCharacter() { PrimaryActorTick.bCanEverTick true; UCharacterMovementComponent* MoveComp GetCharacterMovement(); if (MoveComp) { MoveComp-bOrientRotationToMovement true; MoveComp-RotationRate FRotator(0.f, 720.f, 0.f); MoveComp-JumpZVelocity 500.f; MoveComp-AirControl 0.6f; } } void ASuperMarioCharacter::BeginPlay() { Super::BeginPlay(); if (APlayerController* PlayerController CastAPlayerController(GetController())) { if (DefaultMappingContext) { if (UEnhancedInputLocalPlayerSubsystem* Subsystem ULocalPlayer::GetSubsystemUEnhancedInputLocalPlayerSubsystem(PlayerController-GetLocalPlayer())) { Subsystem-AddMappingContext(DefaultMappingContext, 0); } } } } void ASuperMarioCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void ASuperMarioCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); if (UEnhancedInputComponent* EnhancedInput CastUEnhancedInputComponent(PlayerInputComponent)) { if (MoveAction) { EnhancedInput-BindAction(MoveAction, ETriggerEvent::Triggered, this, ASuperMarioCharacter::Move); } if (JumpAction) { EnhancedInput-BindAction(JumpAction, ETriggerEvent::Started, this, ASuperMarioCharacter::StartJump); EnhancedInput-BindAction(JumpAction, ETriggerEvent::Completed, this, ASuperMarioCharacter::StopJump); } } } void ASuperMarioCharacter::Move(const FInputActionValue Value) { const FVector2D AxisValue Value.GetFVector2D(); if (Controller) { AddMovementInput(GetActorForwardVector(), AxisValue.X); } } void ASuperMarioCharacter::StartJump() { Jump(); } void ASuperMarioCharacter::StopJump() { StopJumping(); }这段代码有几点需要解释ASuperMarioCharacter继承ACharacter所以自带 Capsule 碰撞体和 CharacterMovementComponent不用自己创建移动组件MoveAction、JumpAction、DefaultMappingContext是暴露给编辑器蓝图的属性编译后可以在角色蓝图类里赋值移动函数读取的是FVector2D如果 Input Action 的 Value Type 不是 Axis2D这里取值可能会失败这正是新手最容易踩坑的地方。4.3 输入资产与绑定C 代码只解决绑定逻辑按键资产还需要在编辑器里创建。在内容浏览器中新建一个Input文件夹然后创建两个 Input ActionIA_Move和IA_Jump创建一个 Input Mapping ContextIMC_Default打开IMC_Default给IA_Move绑定 A 键和 D 键Value Type 设置为 Axis2D给IA_Jump绑定空格键Value Type 设置为 Digital编译后在角色蓝图类的细节面板中把MoveAction、JumpAction、DefaultMappingContext指向刚刚创建的三个资产在关卡中放置这个角色蓝图作为默认 Pawn或者把 GameMode 的 DefaultPawnClass 指定为这个角色。如果不想手动创建资产也可以让 AI 生成“运行时加载资产”的版本在 C 中通过ConstructorHelpers::FObjectFinder按路径加载。相比手动指定这种方式更容易出错但好处是复制代码就能跑。对新手我更推荐先手动创建资产因为你能直观看到输入映射的配置逻辑排错也更容易。5. 金币、敌人与碰撞检测角色能跑能跳之后游戏才算有了“玩法”。这一节实现马里奥式关卡里最常见的两个交互碰到金币加分碰到敌人死亡。5.1 金币 Actor金币的本质是一个带有碰撞触发器的 Actor。它不需要自己写移动逻辑只需要在重叠事件里通知 GameMode 加分然后销毁自己。头文件Source/MyProject/Actors/CoinActor.h#pragma once #include CoreMinimal.h #include GameFramework/Actor.h #include CoinActor.generated.h class UStaticMeshComponent; class USphereComponent; UCLASS() class MYPROJECT_API ACoinActor : public AActor { GENERATED_BODY() public: ACoinActor(); protected: virtual void BeginPlay() override; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category Components) USphereComponent* Trigger; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category Components) UStaticMeshComponent* Mesh; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category Gameplay) int32 ScoreValue 1; UFUNCTION() void OnTriggerOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult SweepResult); };实现文件Source/MyProject/Actors/CoinActor.cpp#include CoinActor.h #include Components/SphereComponent.h #include Components/StaticMeshComponent.h #include GameFramework/Character.h #include Kismet/GameplayStatics.h #include MyProject/GameModes/SuperMarioGameMode.h ACoinActor::ACoinActor() { PrimaryActorTick.bCanEverTick false; Trigger CreateDefaultSubobjectUSphereComponent(TEXT(Trigger)); RootComponent Trigger; Trigger-SetGenerateOverlapEvents(true); Mesh CreateDefaultSubobjectUStaticMeshComponent(TEXT(Mesh)); Mesh-SetupAttachment(Trigger); Mesh-SetCollisionEnabled(ECollisionEnabled::NoCollision); Trigger-OnComponentBeginOverlap.AddDynamic(this, ACoinActor::OnTriggerOverlap); } void ACoinActor::BeginPlay() { Super::BeginPlay(); if (UStaticMeshComponent* MeshComp CastUStaticMeshComponent(Mesh)) { if (MeshComp-GetStaticMesh() nullptr) { // 在编辑器里给 Mesh 指定一个 Sphere 或任意基础网格运行时找不到资产时不会崩溃 UE_LOG(LogTemp, Warning, TEXT(CoinActor: Mesh is empty, please assign a static mesh in editor.)); } } } void ACoinActor::OnTriggerOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult SweepResult) { if (ACharacter* Character CastACharacter(OtherActor)) { if (AGameModeBase* GM UGameplayStatics::GetGameMode(this)) { if (ASuperMarioGameMode* GameMode CastASuperMarioGameMode(GM)) { GameMode-AddScore(ScoreValue); } } Destroy(); } }连接 Overlap 事件的关键在于碰撞设置Trigger需要开启Generate Overlap Events并且与角色的碰撞响应设置为 Overlap而不是 Block。默认的 Sphere 碰撞预设不一定满足条件你需要在组件的细节面板里检查 Collision Preset。如果只碰撞不触发八成是这里的问题。5.2 敌人的死亡判定敌人的实现思路类似可以在敌人 Actor 中加入一个 Overlap 触发器。但在马里奥式的玩法里玩家踩到敌人时应该消灭敌人撞到侧面时玩家死亡。区分方式通常有两种看碰撞发生的位置Top vs Side或者看角色是否在空中且下落速度方向朝下。为了让示例保持在可跑通的复杂度内先实现最直接的版本任何与敌人重叠都判定为玩家死亡处理方式是重开当前关卡。// 在角色碰到敌人的 Overlap 回调中或在敌人的 OnTriggerOverlap 中调用 void AEnemyActor::OnKillPlayer(AActor* Player) { if (Player Player-ActorHasTag(FName(Player))) { UGameplayStatics::OpenLevel(this, FName(*GetWorld()-GetName())); } }OpenLevel的方式简单粗暴适合原型验证。正式项目中不建议这么写因为会丢失游戏状态、造成加载闪烁。更成熟的做法是设计一个检查点系统让角色回到最近的存档点这部分可以用 AI 继续迭代也是很好的练习题目。5.3 碰撞相关的常见误区在 UE5 里“碰到”并不是默认发生的。很多新手写了 OnOverlap 却没有任何反应真正原因往往不是代码写错而是碰撞通道配置不对。两个 Actor 要发生 Overlap必须满足双方至少一方设置了 Generate Overlap Events两者之间的碰撞响应是 Overlap 或 Ignore而不是 Block事件绑定发生在 BeginPlay 之前通常是在构造函数中通过AddDynamic绑定。如果捕获不到事件第一件事不是改代码而是打开 Actor 的碰撞预设确认响应关系。UE 的运行时调试日志也会输出碰撞查询结果结合日志排查会比盲改高效得多。6. 用 GameMode 管理得分与游戏状态6.1 GameMode 代码金币加分的目标需要一个全局对象来记录。在 UE5 里GameMode 天然适合承担这个职责它知道当前一局的规则并且可以通过事件通知 UI 更新。头文件Source/MyProject/GameModes/SuperMarioGameMode.h#pragma once #include CoreMinimal.h #include GameFramework/GameModeBase.h #include SuperMarioGameMode.generated.h DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnScoreChanged, int32, NewScore); UCLASS() class MYPROJECT_API ASuperMarioGameMode : public AGameModeBase { GENERATED_BODY() public: ASuperMarioGameMode(); UFUNCTION(BlueprintCallable, Category Score) void AddScore(int32 Amount); UPROPERTY(BlueprintAssignable, Category Score) FOnScoreChanged ScoreChanged; UPROPERTY(BlueprintReadOnly, Category Score) int32 CurrentScore 0; };实现文件Source/MyProject/GameModes/SuperMarioGameMode.cpp#include SuperMarioGameMode.h #include MyProject/Characters/SuperMarioCharacter.h ASuperMarioGameMode::ASuperMarioGameMode() { DefaultPawnClass ASuperMarioCharacter::StaticClass(); } void ASuperMarioGameMode::AddScore(int32 Amount) { CurrentScore Amount; UE_LOG(LogTemp, Warning, TEXT(Score %d), CurrentScore); ScoreChanged.Broadcast(CurrentScore); }ScoreChanged是一个动态多播委托它的作用是解耦 GameMode 和 UIGameMode 只管加分和广播UMG 控件负责监听并刷新显示。6.2 用 UMG 显示分数在内容浏览器中创建一个 Widget Blueprint例如WBP_Score。在其中放一个 TextBlock然后在蓝图事件图中监听ScoreChanged事件。UE 的蓝图操作在这里自然展开你可以在 Widget 蓝图的 Event Graph 中右键创建Bind Event to ScoreChanged节点也可以用一个 GameMode 引用在 BeginPlay 里绑定。简单的方式是把 WBP_Score 添加到视口后每次 GameMode 广播时读取CurrentScore并更新 TextBlock 的文本内容。这一节有一个设计建议不要把 UMG 业务逻辑全部塞给 C。UMG 本身可视化程度高适合在蓝图里做布局和数据绑定C 负责提供数据和事件源。两相结合结构反而最清晰。7. 运行验证与效果检查代码生成完成后回到 UE 编辑器点击编译按钮或使用 Live Coding 快捷键让 C 代码生效。如果编译报错优先看输出日志里的第一个错误绝大多数情况下是缺少模块依赖或文件路径写错。编译通过后把关卡中默认角色替换为ASuperMarioCharacter的蓝图类在场景里放几个金币和至少一个敌人然后点击 Play 测试。预期效果应该包括按 A / D 键角色左右移动按空格键角色跳跃落地后可以再次跳起角色碰到金币后金币消失日志中打印Score 1、Score 2等递增数值角色碰到敌人后关卡重新加载角色回到初始位置。如果吃掉金币后日志没有变化先在编辑器里暂停游戏查看金币 Trigger 的 Overlap 事件是否真的触发了。如果连 Overlap 都没有触发请回到 5.3 查看碰撞配置。如果 Overlap 触发但没有加分查看 GameMode 的 Cast 是否成功最可能的原因是场景里的 GameMode 类型不是ASuperMarioGameMode。8. 常见问题与排查思路以下是 TraeAI 辅助 UE5 开发时最容易出现的几个问题可以直接对照排查问题现象可能原因排查方式解决方案TraeAI 看不到 Source 代码创建的是纯蓝图项目检查工程根目录是否有 Source 文件夹新建一个 C 类或重新创建 C 工程编译报错找不到 EnhancedInput 模块项目 Build.cs 缺少依赖查看输出日志和 Build.cs在PublicDependencyModuleNames加入EnhancedInput角色没有反应移动跳跃全失效InputAction / MappingContext 资产未指定在角色蓝图细节面板检查三个 Input 属性指定资产或在 BeginPlay 中动态加载按住按键只触发一次移动IA_Move 的 Value Type 设置错误检查 Input Action 的 Value Type改为 Axis2D或 Axis1D并确保绑定 Triggered 事件OnOverlap 不触发碰撞响应没有设为 Overlap选中组件查看 Collision Preset开启 Generate Overlap Events调整碰撞响应加分失败场景中的 GameMode 类型不匹配查看 World Settings 和日志将 GameMode 覆盖为ASuperMarioGameMode头文件报错找不到 .generated.h编译顺序或 UHT 生成文件异常删除 Intermediate 目录后重新生成让 UE 重新编译项目生成新的头文件AI 生成的 API 在当前版本不存在引擎版本差异导致 API 名称变化让 AI 读取本地引擎源码或文档在提示词里明确 UE5 的小版本号每一条看起来都是小问题但在实际操作中会消耗大量时间。建议收藏这张表踩到坑时按顺序排查。9. 最佳实践AI 辅助 UE5 开发的工程建议9.1 工程结构先规范化在让 AI 写代码之前先明确目录规则。比如Characters/放角色类Actors/放场景中的交互物件GameModes/放游戏规则类UI/放控件蓝图。在提示词里带上目录约束AI 就不会把任意类堆到根目录。工程结构越规范后期重构成本越低。9.2 一次只改一个模块游戏开发中AI 最危险的操作是“一条龙重构”让 AI 同时修改角色、GameMode、UI、输入配置结果它生成的代码彼此不兼容报错堆积如山。正确的方式是拆分任务。一次只让 AI 处理一个模块编译通过、验证有效后再进入下一个模块。如果中途失败回滚范围也小。9.3 把 Git 当作安全边界AI 生成代码多少会有小幅偏差。每次让 AI 修改前先提交一次AI 输出后先查看 Git Diff 再决定是否接受。如果 Diff 不合理直接回滚重试。这比来回删改代码高效得多。9.4 警惕 AI 幻觉UE5 的 API 在不同小版本之间变化很大AI 完全可能生成一个“看起来正确但实际不存在”的函数。遇到这种情况不要急着让 AI 再改一次而是让它先去读本地引擎的源码请先到 Engine/Source/Runtime/Engine/Classes/GameFramework/ 目录查看 ACharacter 的源码 然后告诉我当前引擎版本中正确的事件绑定方式。把 AI 的注意力引导到真实的引擎源码可以有效减少幻觉。9.5 了解版权与许可边界用 AI 做一个“马里奥式”平台跳跃用来学习完全没问题但如果要公开发布或商业化不要直接用任天堂的角色名、贴图、音效和商标。替换成原创外观玩法上做差异化。同时也需要遵守 UE5 和 TraeAI 各自的软件许可与服务条款。AI 生成代码不等于免费商用代码这一点要分清。9.6 代码审查不是可选项AI 生成的碰撞、存档、网络代码尤其要仔细审查。涉及数据持久化和安全边界时不要盲目相信 AI要明确最小权限原则。例如OpenLevel重开关卡适合原型但正式项目要有检查点系统GameMode 的全局分数要决定数据结构是存在 GameState 还是 SaveGame避免后期迁移困难。10. 总结与后续学习方向回到开头的问题AI 能开发游戏吗从本文的示例看答案是“能但更像辅助不像替代”。AI 真正改变的是原型阶段的速度和入门阶段的摩擦。你用 TraeAI 配合 UE5 做出一个马里奥式平台跳跃角色可能需要一个下午但要做到“好玩”需要处理跳跃手感、关卡节奏、动画反馈、敌人 AI、音效配合这些仍然靠你。下一步值得继续深入的方向有增强输入的高级用法比如多按键组合和技能冷却动画蓝图让角色在跑步、跳跃、下落之间切换行为树给敌人写简单的巡逻和追击逻辑UMG 与事件广播把当前得分、生命、关卡状态做成完整 UI 面板。如果你想真正验证 AI 辅助开发是否适合自己最快的办法是换一个小玩法再做一遍打砖块、俯视角射击、简易塔防都可以。同样用本文的流程C 工程起步、TraeAI 生成核心逻辑、编辑器补资产、最终跑通验证。做完第二个原型之后你对自己擅长什么、AI 擅长什么会有远比读十篇文章更清晰的感觉。