ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI提示词实战:Unity RPG角色控制、对话与任务系统开发指南

AI提示词实战:Unity RPG角色控制、对话与任务系统开发指南 先说个背景IP这个系列第一弹我聊了基础工作流的搭建从AI选型到提示词模板的通用写法反响还行。这一弹“RPG与冒险篇”重点非常明确——把所有提示词能力集中在RPG和冒险游戏最常见的玩法模块上角色控制、对话系统、任务追踪、NPC行为、战区和谜题。我为什么单独拎出RPG讲因为这类游戏的结构足够模板化一个项目中80%的代码都是在重复造轮子而这恰恰是AI提示词最擅长的场景。这篇内容适合任何人——不管是刚进游戏开发坑的在校生还是正在用Unity或Godot做独立项目的开发者。就算你现在手上没有任何AI辅助工具光看里面的提示词模板和代码示例也能当一套速查笔记用。1. 为什么RPG与冒险类特别适合AI提示词1.1 RPG的核心循环与重复结构先拆解一下RPG的核心玩法循环通常就是探索地图、遇到敌人或NPC、对话触发任务、战斗和解谜、获得奖励、角色成长然后继续循环。这套结构稳定得可怕几十年来几乎没有本质变化。也就是说只要你是一个从事RPG开发的程序员你迟早会遇到这么一堆功能模块第三人称或第一人称角色控制器玩家与物体、NPC的交互系统对话跳转和分支逻辑任务数据结构和任务日志敌人AI的巡逻、索敌、追击伤害计算和生命值管理检查点、存档和重生逻辑这些模块在技术层面其实都是“已知问题的已知解法”但写起来非常耗时间。尤其在新项目里很多代码只是上一份代码的变体换一套输入映射、换一个移动速度、多一个冲刺技能但骨架几乎相同。AI提示词的价值就在这里——它不是帮你写那些从没出现过的新系统而是把那些已经被写过一万遍的“标准零件”快速组装出来。你不需要每次从零辛辛苦苦写一个带重力、碰撞检测和跳跃缓冲的角色控制器你把需求丢给AI拿到的脚本至少有七八成能直接用剩下的时间可以用来调手感。调手感才是RPG的核心竞争力而手感的本质不是代码能不能跑而是参数合不合适。1.2 提示词目标从“可运行”到“可调优”很多人一开始让AI生成代码期望太高总想一句话就让AI写一个“完美的暗黑LikeARPG框架”。我不能说完全不可能但大概率会得到一个大而无当的包里面的类设计复杂到你都不敢动。正确思路不是“AI一步到位”而是“AI先给我一个可运行的最小闭环我再来改参数、加功能”。所以这一弹所有提示词我都遵循同一个目标生成的第一个版本必须是一个能拖进场景就跑的最小系统而不是一个华丽但调试成本极高的框架。你给AI设定这个约束AI出来的代码反而更稳。2. 提示词架构设计五个必填要素我发现自己平时在群里聊天时说的“给我写一个RPG对话系统”和大佬真正用的提示词效果差着十万八千里。差的不是AI的能力而是输入的信息结构。经过了第一弹的摸索我整理出一套五要素模板适用于游戏开发里的绝大多数生成请求。2.1 角色设定让AI知道自己是“谁”提示词第一句要告诉AI它该以什么身份和标准来回答。比如“你是一名有10年经验的Unity客户端开发工程师熟悉URP渲染管线、新Input System和CharacterController”。别小看这句话它直接决定了AI输出的代码风格和谨慎程度。你如果说“帮我写个移动脚本”它可能给你一份四五十行的极简版本但如果设定它是资深工程师它会更自然地写进重力、碰撞检测、参数面板等“工程细节”。2.2 上下文与版本环境信息决定代码可用性这是最容易踩坑的一项。同样一段C#代码Unity的旧输入管理器Input.GetAxis和新输入系统InputSystem完全不一样物理引擎版本不一样碰撞检测逻辑也有差异。在提示词里必须明确给出引擎版本或工具版本Unity 2021 LTS / Unity 6、Godot 4.2输入系统方案旧版Input Manager /新版Input System渲染管线URP/HDRP/内置管线目标平台PC、移动端还是WebGL项目已有的关键依赖比如已经引入了TextMeshPro我见过太多人问“AI生成的代码报错怎么办”点开报错一看全是因为项目中根本没引入AI代码里用到的命名空间或类库。与其事后补不如事前在提示词里写清楚“只允许使用Unity内置组件和标准包不依赖任何第三方插件”。2.3 功能清单拆成一条一条的具体要求尽量别写“帮我做一个任务系统”这种模糊需求要把需求拆细。比如支持接取任务和放弃任务任务目标分三类击杀N只敌人、收集N个物品、到达某地点任务进度实时更新并保存到PlayerPrefs任务完成后显示提示UI这样AI才能写出真正的数据结构和逻辑而不是给一个只有AddQuest和RemoveQuest的空壳。要相信一条经验提示词里写得越细生成出来的代码越接近可用状态。2.4 输出格式约束呈现方式建议在提示词末尾加上“输出包含完整的C#代码代码块中不要省略任何方法实现。”“额外附一段Inspector参数配置说明。”“如果某个功能需要用到的事件或接口直接给出示例调用方式。”这一步能保证AI不会在代码里写“// 此处省略实现”这种让人牙痒的占位内容也能保证你用起来不需要细读源码才能理解参数含义。2.5 约束与验收标准明确什么能做什么不能做最后一个要素是“验收标准”。告诉AI“代码应能直接挂到某个对象上运行控制台不能有报错”以及“移动使用CharacterController而不是Rigidbody”。这些约束不是废话它是帮你过滤掉那些更炫酷但引入额外复杂度的方案。我常用的提示词收尾是“完成后自检一遍有没有未定义变量有没有空引用风险有没有未处理的组件缺失情况如果不确定某个API在当前Unity版本中是否存在优先推荐内部API并标注。”五个要素都填上之后提示词就从一个残缺的问句变成了标准的需求单。我可以直接把它保存成模板后续所有替AI生成RPG模块的请求都套这个结构极大降低了沟通成本。3. 核心实操RPG手感三件套我在实际项目中感受到RPG游戏最容易影响玩家评价的就是三个基础模块角色移动手感、对话系统的节奏、任务追踪的清晰度。下面我把这三个模块的完整提示词和核心代码示例都放出来直接复制即可。3.1 第三人称角色控制器角色控制器是所有RPG功能的基础。这个模块必须优先做并且要做稳。这里我给AI的提示词是这么写的你是一名资深Unity 3D游戏开发者熟悉URP、新输入系统和CharacterController。 请帮我实现一个第三人称角色控制器具体要求 1. 使用CharacterController组件不要使用Rigidbody。 2. 支持WASD相对角色朝向移动Shift加速空格跳跃。 3. 地面检测和重力处理落地后短时间内允许连续跳跃跳跃缓冲。 4. 不移动时角色保持面向当前朝向不自动旋转。 5. 所有参数移动速度、跳跃高度、重力、转向速度都能在Inspector窗口调整。 6. 只使用Unity内置API和标准输入请输出完整C#代码不要省略任何方法并附参数说明。整个代码量不大但是AI拿这个提示词写出来的结构通常比我自己从零写要规范得多。核心性能点在于自己实现地面检测时不要依赖Physics.BoxCast直接用CharacterController的isGrounded会省掉大量调试工作。我踩过很多坑之前自己用Raycast做地面检测斜坡角度一换就出问题最后还得改回isGrounded。using UnityEngine; public class ThirdPersonController : MonoBehaviour { [Header(Movement)] public float moveSpeed 5f; public float sprintMultiplier 2f; public float jumpHeight 1.5f; public float gravity -9.81f; public float turnSmoothSpeed 10f; private CharacterController controller; private Vector3 velocity; private float verticalInput; private float horizontalInput; private bool isGrounded; private float jumpBufferTimer; void Start() { controller GetComponentCharacterController(); } void Update() { HandleInput(); ApplyGravity(); HandleJump(); MoveCharacter(); } void HandleInput() { horizontalInput Input.GetAxisRaw(Horizontal); verticalInput Input.GetAxisRaw(Vertical); } void ApplyGravity() { isGrounded controller.isGrounded; if (isGrounded velocity.y 0) { velocity.y -2f; } velocity.y gravity * Time.deltaTime; } void HandleJump() { if (Input.GetButtonDown(Jump)) { jumpBufferTimer 0.15f; } else { jumpBufferTimer - Time.deltaTime; } if (jumpBufferTimer 0f isGrounded) { velocity.y Mathf.Sqrt(jumpHeight * -2f * gravity); jumpBufferTimer 0f; } } void MoveCharacter() { Vector3 direction new Vector3(horizontalInput, 0f, verticalInput).normalized; if (direction.magnitude 0.1f) { float targetAngle Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg; Quaternion targetRotation Quaternion.Euler(0f, targetAngle, 0f); transform.rotation Quaternion.Slerp(transform.rotation, targetRotation, turnSmoothSpeed * Time.deltaTime); Vector3 moveDir Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward; controller.Move(moveDir * moveSpeed * Time.deltaTime); } controller.Move(velocity * Time.deltaTime); } }这里有个细节跳跃缓冲jump buffer其实比很多新手想的重要。你在正常游戏里按跳跃键通常期望“脚一沾地就立刻跳起来”而不是等角色落地后重新读一次按键。没有跳跃缓冲的控制器手感会很“木”AI生成代码时如果没要求这一项它就可能漏写。所以我在提示词里特别强调。3.2 交互提示与对话系统RPG里和NPC对话是让玩家进入剧情的关键载体。对话系统通常需要两块一个是UI显示层一个是逻辑控制层。UI层推荐直接让AI用TextMeshPro但在提示词里一定要说清楚“项目已导入TMP如果没有导入先通过Window/TextMeshPro/Import TMP Essential Resources导入”。这段是我的标准对话系统提示词实现一个基于Unity UGUI和TextMeshPro的对话系统 1. 支持指定NPC名字和逐行多句对话点击“Enter”或“Space”切换到下一句。 2. 对话开始时显示面板对话结束后自动隐藏并触发结束回调。 3. 支持通过代码传入对话数据StartDialogue(string speakerName, string[] sentences)。 4. 使用Input System的默认键盘类Keyboard.current读取按键。 5. 输出脚本应包含对话面板关闭时的光标状态控制可选功能但请实现。AI生成的对话脚本可能没有把“对话中是否允许移动”这种逻辑写进去提一句“对话期间禁用角色控制”会让它主动考虑输入锁。我一般会拿到AI生成的脚本后手动加一个bool isDialogueActive在StartDialogue和EndDialogue里修改角色控制器的enabled。using UnityEngine; using TMPro; using UnityEngine.InputSystem; public class DialogueController : MonoBehaviour { [Header(UI Reference)] public GameObject dialoguePanel; public TextMeshProUGUI speakerNameText; public TextMeshProUGUI dialogueContentText; private string[] currentSentences; private int currentIndex; private System.Action onDialogueEnd; public bool IsDialogueActive { get; private set; } void Start() { dialoguePanel.SetActive(false); } public void StartDialogue(string speakerName, string[] sentences, System.Action onEnd null) { if (IsDialogueActive) return; IsDialogueActive true; onDialogueEnd onEnd; currentSentences sentences; currentIndex 0; speakerNameText.text speakerName; dialoguePanel.SetActive(true); DisplayCurrentSentence(); } void Update() { if (!IsDialogueActive) return; bool pressed Keyboard.current.enterKey.wasPressedThisFrame || Keyboard.current.spaceKey.wasPressedThisFrame; if (pressed) { NextLine(); } } void DisplayCurrentSentence() { dialogueContentText.text currentSentences[currentIndex]; } void NextLine() { currentIndex; if (currentIndex currentSentences.Length) { EndDialogue(); } else { DisplayCurrentSentence(); } } void EndDialogue() { IsDialogueActive false; dialoguePanel.SetActive(false); onDialogueEnd?.Invoke(); } }这里有个容易忽略但必须处理的点如果在对话过程中直接禁用角色控制可能会造成动画和实际位置不同步。我建议不要直接改角色控制器的enabled而是在角色控制脚本里留一个公共bool像这样public bool lockControl false;在Update开头判断if (lockControl) return;然后对话开始设置true结束设置false。这样角色不会因为禁用CharacterController而失去物理属性动画系统也不会乱掉。3.3 任务追踪与日志任务系统是RPG里信息量最大的模块。AI生成时最容易写出一个光鲜的UI壳但底层数据结构一塌糊涂。任务系统的核心其实不在于UI而在于数据的解耦。一个任务应该包含任务ID、任务名、任务描述、目标列表每个目标包含目标类型、目标描述、当前计数、目标计数。UI显示只是读这些数据。我的任务追踪示提示词这样写设计一个RPG任务数据管理器基于Unity C# 1. Quest类包含questName、questDescription、ListQuestObjective、任务完成检查。 2. QuestObjective包含Description、CurrentCount、TargetCount、IsComplete。 3. QuestManager提供AddQuest、UpdateObjective(string questName, string objectiveDescription, int amount)方法。 4. UpdateObjective要防止当前计数超出目标计数。 5. 不画UI只输出数据层脚本和调用示例。这种提示词刻意要求“不用UI”目的就是让AI把精力放在数据结构上。事实证明数据层做对了之后接UI是十分钟的事。using System; using System.Collections.Generic; [Serializable] public class QuestObjective { public string description; public int targetCount; public int currentCount; public bool IsComplete currentCount targetCount; public void AddProgress(int amount) { currentCount Math.Min(currentCount amount, targetCount); } } [Serializable] public class Quest { public string questName; public string questDescription; public ListQuestObjective objectives new ListQuestObjective(); public bool IsComplete { get { for (int i 0; i objectives.Count; i) { if (!objectives[i].IsComplete) return false; } return true; } } public bool IsConfigValid() { return objectives.Count 0; } } public class QuestManager : MonoBehaviour { public ListQuest activeQuests new ListQuest(); public ListQuest completedQuests new ListQuest(); public void AddQuest(Quest quest) { if (probeDuplicate(quest.questName)) return; activeQuests.Add(quest); } bool probeDuplicate(string questName) { for (int i 0; i activeQuests.Count; i) { if (activeQuests[i].questName questName) return true; } return false; } public void UpdateObjective(string questName, string objectiveDescription, int amount 1) { Quest quest activeQuests.Find(q q.questName questName); if (quest null) return; QuestObjective objective quest.objectives.Find(o o.description objectiveDescription); if (objective null) return; objective.AddProgress(amount); if (quest.IsComplete) { bool isCompleted activeQuests.Remove(quest); if (isCompleted) { completedQuests.Add(quest); Debug.Log(任务完成 quest.questName); } } } }实际用的时候我一般会再加一个事件系统比如MissionEventBus在玩家击杀怪物时广播事件然后任务管理器监听。这个扩展在提示词里可以追加一句“加一个event OnQuestProgressChanged进度变化时发出通知”。把事件加上UI刷新就方便了不用每帧去轮询任务列表。4. 冒险感怎么造AI生成关卡逻辑而非美术RPG和冒险游戏的地牢或野外场景最影响体验的其实是地图里的“节奏点”哪里遇到怪、哪里触发机关、哪里开宝箱、哪里设置捷径。AI没法直接帮你建模做美术但它能生成所有这些逻辑层的东西。你只需要把层级挂到对应的触发器对象上就行。4.1 巡逻怪物与触发事件一个竞技场式的敌人区域最基础的需求是有一两个怪在固定路径上巡逻玩家进入某个球形范围后怪切换到追击状态。这个逻辑AI生成很快。生成一个2D蠢萌风格的巡逻AI 1. NPC身上挂NavMeshAgent。 2. 巡逻路径由数组waypoints表示依次到达后循环。 3. 玩家距离小于detectRadius后开始追击追击使用NavMeshAgent.SetDestination。 4. 追击距离大于loseRadius后丢弃目标并回到最近巡逻点。 5. 不用动画不用音效只提供逻辑代码和Inspector参数。注意我用了“NavMeshAgent”这就是一个典型的上下文选择。如果你用CharacterController做敌人还要自己处理绕障碍和寻路做出来的敌人转头时会很蠢。作为从业者我强烈推荐敌人的移动统一使用NavMeshAgent物理碰撞和寻路都帮你处理了最常见的问题是“Agent会滑步”但那是动画层的Body Mask没配好。4.2 谜题机关状态机不要让AI“思考过多”谜题系统的本质是一个状态机。比如四盏灯需要按顺序点亮或者两个压力板需要同时踩下。这种逻辑其实不难但用传统if else嵌套写多了很容易变成一团乱麻。用提示词让AI先设计状态枚举然后再实现状态转换逻辑结构会清晰很多实现一个地牢门禁系统 1. 包含两个压力板PressurePlateA和PressurePlateB。 2. 玩家同时站在两块压力板上时大门gate动画播放并向上升起。 3. 任意一个压力板离开大门3秒后自动关闭。 4. 压力板是触发器Collider通过OnTriggerEnter和OnTriggerExit检测。 5. 装置状态只允许使用枚举Locked、Waiting、Opening、Open、Closing。 6. 输出完整的C#脚本包含Public Inspector变量用于拖拽引用。这个提示词很有代表性它要求AI用状态枚举来管理逻辑避免代码里堆一堆bool标记。我在实际项目里发现状态机让解谜系统的调试成本降了一半。每个状态对应明确的进入条件和退出条件出问题时只需要看当前状态是什么基本就能定位到是哪段转换逻辑出了问题。4.3 战区波次控制战斗波次系统在RPG和冒险游戏里几乎是标配。AI生成的典型问题是没有做“波次之间的延迟”或者没有处理怪全部死亡后的刷新逻辑。这一块我会刻意把时间轴写明白实现一个波次怪物生成器 1. 每个波次包含一个怪物列表每只怪从预制体ResourceManager加载。 2. Wave 0到Wave N依次触发每次玩家清空当前波次所有怪物后等2秒进入下一波。 3. 支持在Inspector配置每波怪物数量和难度的缩放系数。 4. 全部波次清空后调用LevelClearCallback并通过UnityEvent通知。 5. 使用协程而非Update每帧判断。写这个时容易忽略的一点是每波怪物生成前要检查场上还有没有残留怪物否则上一波没清完就强行刷下一波逻辑就彻底乱了。我自己的实现习惯是记录并维护当前存活怪物数量每只怪物死亡时通过OnEnemyDied事件减少计数当计数清零再触发下一波。如果你直接把“生成的时候不管存活状态直接数波次”作为提示词AI也会照着写所以把这条需求写明确。5. 常见问题与排查技巧实录使用AI辅助游戏开发碰到的坑大同小异。我在这一个多月的RPG原型开发里踩了几个雷这里做一个速查表后续可以直接对着查。5.1 AI“一本正经胡说八道”的API最常见的问题是AI会给出Unity中根本不存在的API或者拼写错误的方法。比如它可能让你用Input.GetAxis(LeftHorizontal)这种自定义字符串或者让你调用CharacterController.SetHeight()这种不存在的函数。排查思路第一步看到控制台红色报错不要慌先把报错信息复制给同一款AI让AI自己解释。第二步把AI生成的代码在IDE里过一遍凡是看到没见过的API先查文档或搜索引擎确认后再用。第三步在提示词里强制加一句“只用Unity官方文档中有记载的标准API”能挡住绝大部分幻觉。我在实际使用中发现把报错信息原封不动贴回给AI然后问“这个报错是什么原因如何修复”AI的自我纠错能力很强通常一两轮就能搞定。但注意不要让AI无限循环改代码改了三轮还不行就手动介入。AI犯的错往往不是逻辑错而是一个API不匹配手动改一行可能比让它重写整个脚本更快。5.2 坐标与朝向的经典坑AI生成的角色控制器或怪物流方向错误大多是在移动方向上用了Vector3.forward这个固定世界方向没有转换到角色朝向或相机朝向。尤其是第三人人称游戏如果你让角色自由朝向移动方向应该是transform.forward和transform.right方向的组合而不是固定向量。我在测试AI生成的第三人称控制器时就遇到过角色按W往后走、按S往前走的现象。排查了半天才发现AI在移动计算中写的是Vector3.forward * z Vector3.right * x而上面代码里我手动转了角色朝向所以两个坐标系混在一起了。正确的写法是在移动方向计算后乘上transform.rotation或者直接用transform.right、transform.forward。这个问题非常典型做个标记生成代码后先试一个方向如果方向颠倒了优先检查坐标转换是否用对了变换。5.3 生成代码和项目版本不匹配新Input System和旧Input Manager是最大的版本鸿沟。如果项目开启了“Active Input Handling Both”大多数代码还能跑如果只开着新Input SystemAI生成的老代码会直接编译失败提示Input.GetAxis不存在。解决方案在提示词里明确写“基于新Input System使用Keyboard.current.xxx.wasPressedThisFrame”。或者在项目设置中把Active Input Handling改为Both让新旧API同时生效。但实际做下来两个系统混着用会让输入行为难以预测比如同一帧同时触发两次输入事件并不是好方案。类似的还有TMP和UGUI Text的冲突、URP管线的Shader名称变化等等。凡是遇到版本相关的问题都建议在提示词里先交代清楚环境AI的输出质量会明显上升。5.4 表格速查RPG提示词中的常见问题症状常见原因修复建议角色移动方向颠倒移动计算用了世界坐标而非角色或相机朝向坐标用transform.right/forward替代Vector3.right/forward跳跃高度不稳定重力值直接用-9.81且按高度公式未算对使用velocity.y Mathf.Sqrt(jumpHeight * -2f * gravity)对话无法继续按键检测写在了旧Input Manager接入新Input System或全局切换Active Input HandlingAI生成代码大量报错提示词环境上下文缺失补全引擎版本、渲染管线、第三方包信息敌人不追击或乱走NavMeshAgent被禁用了但没有resume或者路径未更新检查agent.enabled以及SetDestination调用节奏波次刷新重复刷怪没有清点当前存活怪物数加入当前存活计数器和死亡事件回调任务进度不变UpdateObjective里的字符串描述不完全匹配统一用任务目标ID而非描述文本做匹配键5.5 用“错误日志反哺提示词”的独家技巧最后分享一个我用了很久的技巧当一个AI生成的代码报错后不急着手动改而是把完整的报错堆栈和对应代码片段一起丢给AI同时追加一句“请判断这个错误的根本原因并指出是哪个API不匹配还是逻辑错误。如果三行内看不出问题就列出排查方案不要轻易重写全部代码。”这样AI通常能快速定位到一个变量范围、一处空引用或一个API版本问题而不是直接把整个脚本推翻重来。这个技巧可以帮你省掉很多翻文档的力气。我个人在实际项目里的体会是AI生成代码这件事真正的胜负手不在AI水平而在你输入的质量和验收方式。你如果一开始就抱着“AI写好了我直接用”的心态大概率会失望但如果你把它当成一个什么都懂一点、但偶尔犯迷糊的同事先给需求单再复核再让小问题反哺回去修它的产出效率会高得离谱。建议你在做自己的RPG项目时从最小闭环开始先让AI生成角色控制器跑通7个方向感再加入对话系统串通和NPC交互最后才上任务管理器。一路下来你会发现自己已经不用手写那些模板代码了省出来的精力全部可以放在真正影响游戏好玩的系统设计上。
返回列表