作为 Unity 开发者,你可能已经感受到 AI 编程的潜力。Unity 的 C# 脚本开发具有高度模式化的特点——MonoBehaviour 生命周期、组件通信、协程等——这正是 AI 擅长的领域。
一、Unity 脚本中的 AI 适用场景
| 场景 |
AI 能力 |
示例 |
| 组件脚本生成 |
根据描述生成完整脚本 |
“创建第三人称角色移动控制器” |
| 游戏逻辑 |
实现特定行为模式 |
“实现追踪玩家的敌人 AI” |
| 动画控制 |
Animator 参数和状态逻辑 |
“根据移动速度切换行走/奔跑动画” |
| 物理交互 |
碰撞/触发逻辑 |
“玩家进入触发器打开门” |
| 工具脚本 |
编辑器扩展和辅助 |
“创建批量重命名编辑器工具” |
二、C# 脚本生成实战
2.1 玩家控制脚本
在 Cursor 中创建新脚本,使用 Cmd+K:
1 2 3 4 5 6
| 创建一个第三人称角色控制器: - 使用 CharacterController 组件 - WASD 控制移动,空格跳跃 - 摄像机跟随,鼠标控制视角旋转 - 支持冲刺(按住 Shift) - 移动和跳跃时播放对应的动画
|
AI 会生成结构完整的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| using UnityEngine;
public class ThirdPersonController : MonoBehaviour { [Header("移动参数")] [SerializeField] private float walkSpeed = 5f; [SerializeField] private float sprintSpeed = 8f; [SerializeField] private float jumpForce = 8f; [SerializeField] private float gravity = -20f; [Header("摄像机")] [SerializeField] private Transform cameraTarget; [SerializeField] private float mouseSensitivity = 2f; private CharacterController controller; private Animator animator; private Vector3 velocity; private float currentSpeed; private void Awake() { controller = GetComponent<CharacterController>(); animator = GetComponent<Animator>(); } private void Update() { HandleMovement(); HandleJump(); HandleCamera(); UpdateAnimation(); } private void HandleMovement() { float x = Input.GetAxis("Horizontal"); float z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; currentSpeed = Input.GetKey(KeyCode.LeftShift) ? sprintSpeed : walkSpeed; controller.Move(move * currentSpeed * Time.deltaTime); velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } private void HandleJump() { if (Input.GetButtonDown("Jump") && controller.isGrounded) velocity.y = Mathf.Sqrt(jumpForce * -2f * gravity); } private void HandleCamera() { float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; transform.Rotate(Vector3.up * mouseX); cameraTarget.localRotation *= Quaternion.Euler(-mouseY, 0, 0); } private void UpdateAnimation() { if (animator == null) return; animator.SetFloat("Speed", currentSpeed / sprintSpeed); animator.SetBool("IsGrounded", controller.isGrounded); } }
|
2.2 敌人 AI 脚本
1 2 3 4 5 6
| 创建一个简单的敌人 AI: - 在指定路径上巡逻(Waypoint 系统) - 检测到玩家后追击 - 超出最大追击距离后返回巡逻 - 使用状态机模式(Idle/Patrol/Chase) - 可视化 Gizmos 显示检测范围
|
AI 生成的敌人 AI 脚本包含完整的状态机:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| using UnityEngine; using System.Collections.Generic;
public enum EnemyState { Idle, Patrol, Chase }
public class SimpleEnemyAI : MonoBehaviour { [Header("巡逻设置")] [SerializeField] private List<Transform> waypoints; [SerializeField] private float patrolSpeed = 2f; [SerializeField] private float waitTime = 2f; [Header("追击设置")] [SerializeField] private float chaseRange = 10f; [SerializeField] private float chaseSpeed = 5f; [SerializeField] private float maxChaseDistance = 20f; private EnemyState currentState; private int currentWaypointIndex; private float waitTimer; private Transform player; private void Awake() { player = GameObject.FindWithTag("Player").transform; ChangeState(EnemyState.Patrol); } private void Update() { switch (currentState) { case EnemyState.Patrol: UpdatePatrol(); break; case EnemyState.Chase: UpdateChase(); break; case EnemyState.Idle: UpdateIdle(); break; } float dist = Vector3.Distance(transform.position, player.position); if (dist <= chaseRange && currentState != EnemyState.Chase) ChangeState(EnemyState.Chase); } private void UpdatePatrol() { if (waypoints.Count == 0) return; Transform target = waypoints[currentWaypointIndex]; float dist = Vector3.Distance(transform.position, target.position); if (dist < 0.5f) { waitTimer += Time.deltaTime; if (waitTimer >= waitTime) { currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Count; waitTimer = 0; } } else { transform.position = Vector3.MoveTowards( transform.position, target.position, patrolSpeed * Time.deltaTime); transform.LookAt(target); } } private void UpdateChase() { float dist = Vector3.Distance(transform.position, player.position); if (dist > maxChaseDistance) { ChangeState(EnemyState.Patrol); return; } transform.position = Vector3.MoveTowards( transform.position, player.position, chaseSpeed * Time.deltaTime); transform.LookAt(player); } private void UpdateIdle() { } private void ChangeState(EnemyState newState) { currentState = newState; waitTimer = 0; } private void OnDrawGizmosSelected() { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, chaseRange); Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, maxChaseDistance); } }
|
2.3 对象池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class ObjectPool<T> where T : MonoBehaviour { private readonly Queue<T> pool = new(); private readonly T prefab; private readonly Transform parent; public ObjectPool(T prefab, int initialSize, Transform parent = null) { this.prefab = prefab; this.parent = parent; for (int i = 0; i < initialSize; i++) { T obj = CreateNew(); obj.gameObject.SetActive(false); pool.Enqueue(obj); } } public T Get() { T obj = pool.Count > 0 ? pool.Dequeue() : CreateNew(); obj.gameObject.SetActive(true); return obj; } public void Return(T obj) { obj.gameObject.SetActive(false); pool.Enqueue(obj); } private T CreateNew() { T obj = Object.Instantiate(prefab, parent); obj.name = $"{prefab.name}_{pool.Count}"; return obj; } }
|
2.4 动画控制脚本
1 2 3
| 在 Cursor 中用 Cmd+K 创建动画控制器脚本: "创建一个动画控制脚本,根据角色的移动速度切换 Idle/Walk/Run 动画状态,并根据移动方向调整朝向"
|
2.5 物理交互脚本
1 2 3 4 5
| 生成一个触发器脚本: - 玩家进入 Trigger 区域时开门 - 离开时关门 - 门平滑旋转打开 - 添加可配置的开门速度和角度
|
AI 生成后只需拖拽到 GameObject 上,配置好引用即可运行。
三、AI 与 Unity 项目的最佳实践
3.1 .cursorrules Unity 专属配置
利用 .cursorrules 设定 C# 编码规范和架构模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 你是一名资深的 Unity C# 开发者。
编码规范: - 私有字段使用 _camelCase - 使用 [Header] 和 [Tooltip] 组织 Inspector - 序列化字段使用 [SerializeField] 而非 public
架构原则: - 优先使用 ScriptableObject 架构 - 使用依赖注入而非 GetComponent 查找 - 使用对象池管理频繁创建的对象 - 使用事件系统(UnityEvent/C# event)解耦组件
避免: - GameObject.Find / FindObjectOfType(运行时查找) - Update 中的 GC Alloc(字符串拼接、LINQ) - 频繁的 Instantiate/Destroy(用对象池替代)
项目信息: - Unity 2022.3 LTS - Universal Render Pipeline - Cinemachine + Input System 包
|
3.2 AI 生成后的检查清单
| 检查项 |
说明 |
自动/手动 |
| 组件引用 |
AI 生成的代码中 Awake/Start 的 GetComponent 是否正确 |
自动 |
| 事件绑定 |
Inspector 中需要手动拖拽绑定的引用 |
手动 |
| 参数调整 |
生成的默认参数(速度、范围)是否合理 |
手动 |
| 命名空间 |
是否缺少 using 语句 |
自动 |
| 性能 |
Update 中是否有不必要的操作 |
自动 |
3.3 常见 Prompt 模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Unity 脚本类型 Prompt 模板:
1. 玩家控制: "创建一个[第一/第三]人称控制器,使用[CharacterController/Rigidbody], 支持[WASD/摇杆]移动,[空格跳跃],[Shift 冲刺]"
2. 敌人 AI: "创建一个敌人 AI,使用状态机模式,包含[巡逻/追击/攻击]状态, 使用[NavMeshAgent/Transform.MoveTowards]移动"
3. UI 管理: "创建一个血量条 UI 脚本,使用 Slider 组件, 支持[平滑过渡/渐变颜色/闪烁警告]"
4. 工具脚本: "创建一个编辑器工具,批量[重命名/查找/替换]场景中的 GameObject"
|
本章小结
- Unity 的 C# 脚本生成是 AI 的高价值场景,模式化代码效率提升显著
- 第三人称控制器、敌人 AI(带状态机)、对象池等常见功能可一键生成
- AI 能生成完整的动画控制、物理交互、UI 管理等脚本
- .cursorrules 能让 AI 遵循 Unity 编码规范和架构模式
- AI 生成的代码需要检查:组件引用、事件绑定、参数调整、性能
- 模板化的 Prompt 能大幅提升生成质量——把”需求描述”变成”填空式”指令
下一篇继续 Unity 专题,用 AI 构建一个完整的游戏项目。