
做AR开发这些年我最大的感触不是技术门槛高而是“重复劳动太多”。一个AR交互脚本翻来覆去就是触摸检测、射线命中、平面放置、物体旋转、异常销毁这些事逻辑不复杂但写起来又长又碎。尤其是换了新项目、换了SDK版本之后很多以前的代码片段直接失效又得重新查API、重新调坐标。后来我开始把ChatGPT拉进这个流程配合提示词工程让大模型先生成AR交互脚本的骨架和核心逻辑我再负责校验和落地整体产出速度确实翻了一倍不止。这篇就聊聊我实际项目里最常用的5个技巧适合正在用Unity AR Foundation、ARKit、ARCore或者WebAR写交互脚本的开发者参考。需要先说清一个边界提示工程不是让你当甩手掌柜把整个AR项目交给ChatGPT去写。而是用一套提问方法让大模型在合适的位置输出结构清晰、接近工程可用的代码草稿把最消耗时间的“翻译工作”先做完你再集中精力解决真正有技术含量的部分。1. 为什么AR交互脚本特别适合用提示工程生成1.1 AR交互脚本的真实痛点重复、琐碎、易错很多没有真正写过AR项目的朋友会以为AR开发的核心是SLAM、空间计算、图像识别这些硬核算法。但真到了工程落地阶段你会发现一天下来写的大部分代码其实是【点一下屏幕→发一条射线→命中平面→生成一个虚拟物体→让它跟着手指移动】这种基础交互。这类代码重复度高、结构套路化但又有几个很容易踩坑的点。第一AR Foundation的API在版本迭代中经常变化网上搜到的大量老教程代码在Unity 2022 AR Foundation 5.x环境下根本跑不起来。第二不同平台的API差异很大同一套逻辑在ARCore和ARKit上可能需要不同的生命周期处理。第三交互脚本通常要和“识别状态”“放置状态”紧紧绑定状态一旦混乱真机上就会频繁出现幽灵物体、点击失灵、物体凭空飞走等诡异问题。这几件事叠加在一起就导致一个尴尬局面代码很好写但很耗时间而且Bug率还不低。大模型正好适合处理这类“模式化很强、且已经有大量公开代码语料”的任务。1.2 提示工程的真正价值把“意图”翻译成“结构”提示工程看起来只是在“好好说话”但核心作用是把你的需求从模糊的自然语言翻译成模型更容易遵循的结构化指令。AR交互脚本恰好很吃这一套。比如你直接问“帮我想一个AR交互”ChatGPT大概率会给你一个泛泛的概念什么“识别平面、放置物体、旋转缩放”但代码不一定能用。如果你用提示工程的方式把交互状态、触发条件、SDK版本、生命周期逻辑全部拆清楚模型输出结果的质量会完全不一样。换成年底要跟项目排期你就能明显感觉到提示工程本质上是在“花钱买确定性”。你把结构交代得越清楚ChatGPT生成的东西就越接近可用的初稿你修改的成本就越低。这也是为什么同样的模型、同样的项目有人能一小时出一个Demo有人折腾一下午还是在跟编译错误搏斗。1.3 我的大模型搭配习惯先交代一下我的工作流。目前我主力使用的是ChatGPT Plus的网页版偶尔会用API把一些固定模板接入团队内部工具。模型能力只需要到能生成靠谱的Unity C#脚本即可不需要太花哨的Agent式编排。我的核心习惯是让模型“一次只写一个脚本但要把上下文喂全”。比如过去的对话里已经有项目的技术选型、SDK版本、代码风格约定我再让它生成新功能时就会附上“沿用之前代码风格”的约束。这种做法明显比每次重新开个新会话、让模型从零猜你的项目环境要稳定得多。还有一个细节我不让ChatGPT直接生成几百行的大杂烩。宁可多花几次对话让它先把交互流程梳理成几个模块再逐个生成脚本。这样出的代码虽然不那么“一气呵成”但每段都更容易编译通过排查问题时也更容易定位。2. 技巧一角色约束加上SDK版本生成工程化代码2.1 为什么提示词必须带上Unity和AR Foundation版本这是最基础也最容易被忽略的技巧。很多人在用ChatGPT生成Unity代码时只说一句“帮我写一个AR放置物体的脚本”。结果模型可能生成基于老版本Vuforia的代码甚至生成一个用OnGUI实现的伪AR交互。不是模型不行而是它无法替你做技术选型。AR技术栈对版本极其敏感。以Unity AR Foundation为例从4.x升级到5.x后许多接口的namespace和调用方式都发生了变化。直接让模型默认API它大概率会选训练语料里最常出现的版本而不是你项目正在用的版本。我自己就遇到过这样的坑AR Foundation旧版里你可以直接用ARRaycastManager.Raycast配合TrackableType.PlaneWithinPolygon来命中平面新版本依然支持但部分老接口被移除或标记为过期。如果提示词不写版本生成的代码很像“印象流的经典写法”编译时却各种飘红。2.2 一个可直接照抄的角色型提示词模板下面这个提示模板是我实测下来效果比较稳定的你是一名专注于Unity AR Foundation开发的工程师熟悉ARCore和ARKit的通用接口也熟悉Unity 2022 LTS环境。请使用C#实现一个AR交互脚本需求如下在AR场景中点击屏幕通过ARRaycastManager进行射线命中测试。命中平面后在命中位置生成一个虚拟物体并把命中点的Pose设置为物体初始位置。每次点击最多只生成一个物体再次点击时销毁上一个物体再生成。代码必须包含必要的using引用并处理AR Session生命周期。请输出完整可运行的脚本并在代码注释中解释关键步骤。这个模板里最关键的有三块“Unity AR Foundation开发工程师”这个角色约束锁定技术栈方向“Unity 2022 LTS”这个版本约束避免生成过时API“必须包含必要的using引用”这个输出约束减少编译错误。2.3 实际生成效果差异分析用这个模板生成的代码结构上已经有了工程感。合理情况下你会拿到一个像这样的初稿using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; public class PlaneTapSpawner : MonoBehaviour { [SerializeField] private ARRaycastManager _raycastManager; [SerializeField] private GameObject _prefab; [SerializeField] private bool _replaceOnNextTap true; private GameObject _spawnedObject; private readonly ListARRaycastHit _hits new ListARRaycastHit(); private void Update() { if (Input.touchCount 0) return; Touch touch Input.GetTouch(0); if (touch.phase ! TouchPhase.Began) return; if (!TryGetTouchPosition(out Vector2 touchPosition)) return; if (_raycastManager.Raycast(touchPosition, _hits, TrackableType.PlaneWithinPolygon)) { Pose hitPose _hits[0].pose; HandlePlaneHit(hitPose); } } private void HandlePlaneHit(Pose hitPose) { if (_replaceOnNextTap _spawnedObject ! null) Destroy(_spawnedObject); _spawnedObject Instantiate(_prefab, hitPose.position, hitPose.rotation); } private bool TryGetTouchPosition(out Vector2 touchPosition) { if (Input.touchCount 0) { touchPosition default; return false; } touchPosition Input.GetTouch(0).position; return true; } }这段代码不是说直接可以放进项目里跑因为ARRaycastManager的引用还需要你在Inspector里拖进去但至少已经省掉了我大概二十分钟的搜索和纠错时间。版本约束带来最大的收益就是它没有用淘汰的接口来坑我。3. 技巧二先画状态机再让ChatGPT落成脚本3.1 交互脚本的本质是有限状态机AR交互脚本和普通UI交互最大的区别在于系统里的“状态”非常多。空闲时你可以点击识别到平面后你可以放置放置完成后你可以拖动拖动过程中手势触摸坐标发生变化又可能进入旋转状态。如果直接把整个交互流程的描述扔给ChatGPT它很容易写成一大块if-else逻辑乱得没法维护。我的做法是先在提示词里把有限状态机画出来。所谓有限状态机就是明确当前系统处于什么状态、遇到什么事件会跳转到什么新状态、跳转时要执行什么动作。一个典型的AR物体放置与编辑交互可以拆成这样当前状态触发事件条件跳转状态执行动作Idle检测到平面命中类型为平面Tracking显示可放置提示信息Tracking点击屏幕射线命中平面Placing在命中点生成物体Placing触碰物体手指触摸碰撞体Selected高亮物体或播放特效Selected单指拖拽拖拽距离超过阈值Dragging跟随手指在平面上移动Dragging抬起手指触摸结束Selected停止跟随保持当前位置Selected双指捏合两指距离变化Scaling缩放物体Selected点击空白射线未命中物体Tracking/Idle取消选中并还原提示一旦你把这张状态表喂给模型它输出的代码结构会非常明确所有的状态转移都写成一个个独立方法而不是把几十个标志位揉在一起。3.2 如何把状态描述“结构化”地写进提示词结构化不是让你画图而是用文字表格或者列表把状态和事件写清楚。这段提示词是我经常用的骨架请用有限状态机模型设计一个AR物体放置交互。状态包括Idle、Tracking、Placing、Selected、Dragging、Scaling、Confirmed。事件包括平面检测成功、屏幕点击、拖动Delta、手指抬起、旋转手势、双击确认。请先列出状态转移表再根据这个状态转移表生成C#脚本。脚本需要包含一个枚举InteractionState来管理当前状态并提供状态切换时的事件回调方法。这里为什么要强调“先列出状态转移表再生成脚本”因为这样能让大模型按两步输出先做设计决策再做代码实现。模型在“设计模式”上比一次性直接蹦代码更容易保持一致性代码里各个方法的分工也会更清楚。3.3 从状态机到C#代码的实例片段用上面那个方法我经常得到类似这样的结构。public class ARStateInteraction : MonoBehaviour { public enum InteractionState { Idle, Tracking, Placing, Selected, Dragging, Scaling, Confirmed } private InteractionState _currentState InteractionState.Idle; private void ChangeState(InteractionState newState) { if (_currentState newState) return; InteractionState previousState _currentState; _currentState newState; OnStateExit(previousState); OnStateEnter(newState); } private void OnStateEnter(InteractionState state) { switch (state) { case InteractionState.Tracking: ShowHint(检测到平面可以点击放置); break; case InteractionState.Placing: SpawnObjectAtTouchPoint(); break; case InteractionState.Selected: HighlightObject(true); break; } } private void OnStateExit(InteractionState state) { switch (state) { case InteractionState.Dragging: StopFollowingFinger(); break; case InteractionState.Selected: HighlightObject(false); break; } } }状态机的价值在于当你把逻辑交给编译器去检查或者交给测试人员去验证时每个人都能很快说出“现在应该处于什么状态为什么不能执行某个动作”。这比散落一地的if嵌套要好维护得多。4. 技巧三把坐标换算和物理规则写进提示避免“看上去能跑”4.1 AR脚本里最常见的“隐藏数学”AR交互脚本很少只处理单一坐标系的逻辑。屏幕点击得到的是屏幕坐标射线命中返回的是世界坐标平面锚点又带有自己的局部坐标虚拟物体在世界坐标里再进行旋转和缩放。这中间还夹着相机的投影矩阵、屏幕分辨率、设备的陀螺仪姿态。很多人拿到了ChatGPT生成的代码第一印象是“逻辑挺完整”但跑起来之后物体总是悬空或者乱飘原因就是数学约束没有告诉模型。比如放置物体不是简单地在命中点Instantiate更重要的是“物体应该贴着平面表面而不是穿模一半或者倾斜”。这需要在提示词里明确要求物体初始旋转必须使用命中点的Pose旋转且只绕Y轴对齐。再比如做拖拽时如果只用ScreenToWorldPoint很容易把物体拖到平面上空或地下正确做法是在命中平面上取一点用平面法线方向修正拖拽高度。4.2 把数学约束写进提示词的典型示例遇到坐标换算敏感的AR需求我会这样补充提示需要一个AR平面放置逻辑。屏幕点击后使用ARRaycastManager进行命中测试命中平面类型为TrackableType.PlaneWithinPolygon。命中结果Pose作为生成物体的位置和旋转。生成后如果用户单指拖动物体需要跟随手指在同一个平面上移动也就是物体位置始终与平面命中点保持在同一平面高度不允许出现上下跳动。另外需要把物体的缩放设置为与初始生成时一致不要被平面面积影响。请同时考虑屏幕Pixel坐标和物理屏幕尺寸无关这种问题。这一段提示词里的关键数学信息是“物体位置始终与平面命中点保持在同一平面高度”这直接约束了模型必须根据命中平面来求拖拽位置而不是简单地把屏幕坐标转成世界坐标。4.3 生成结果中我会重点检查哪几行拿到ChatGPT输出后我一般会重点检查几个地方。一个是是否用到了ARRaycastManager.Raycast的hits[0].pose.rotation另一个是拖拽时是否重新发了一次射线第三个是缩放时是否以物体的原始尺寸为基准。如果这三处都合理代码落地的成功率会高很多。我举个例子。有一次我要做一个“在墙面平面放置相框”的AR功能直接把需求扔进ChatGPT它给出的代码用的是TrackableType.PlaneWithinPolygon但物体的初始rotation直接用了Quaternion.identity。这在桌面平面上看起来问题不大可换成墙面上就会倒着贴上去。后来我在提示词里补上一句“物体需要和命中的平面法线对齐保持物体正面面向相机”生成的代码就正确使用了hitPose.rotation而且进一步处理了Y轴偏转。这就是把数学规则和物理意图写进提示词的力量。模型没有能力在真机上验证它只能从你的约束里推测最接近的方案。约束越清晰结果越接近真机可用。5. 技巧四用少样本示例锁死项目的代码风格5.1 GPT默认代码风格为什么总让人皱眉ChatGPT生成的代码有时候“能力很强但是风格很让团队崩溃”。它会默认使用很学术化的命名比如HandleObjectSpawnRequest也会喜欢写超长方法还会在Unity脚本里堆大量public变量而不用[SerializeField]。这些在单机Demo里都能跑一旦进入团队协作或长期维护阶段就变成了一场灾难。AR项目尤其如此原因是AR脚本往往要和特效、音频、UI、网络传输等多个模块协作。如果变量命名不一致、模块划分不清晰三个月之后你自己都看不懂当时写的逻辑。少样本提示词是解决这个问题最直接的办法。所谓少样本是给模型提供一两个你已经认可的真实示例让它在生成新代码时模仿示例的风格。5.2 少样本提示词的正确写法和示例以项目里的AR交互组件为例我通常会先给模型看一小段已有的代码风格参考下面这段代码是我们项目的标准风格请严格按照这种风格来实现新的AR交互脚本public class ARInteractable : MonoBehaviour { [SerializeField] private Transform _contentRoot; [SerializeField] private float _rotationSensitivity 0.1f; public void OnSelect() { _contentRoot.localScale Vector3.one * 1.2f; } public void OnDeselect() { _contentRoot.localScale Vector3.one; } public void ApplyRotation(float angle) { Vector3 euler _contentRoot.localEulerAngles; euler.y angle; _contentRoot.localEulerAngles euler; } }要求使用_开头的私有字段命名不允许public字段。公开方法使用PascalCase私有方法使用CamelCase。变量显式标注初始值。每个方法只做一件事方法长度控制在20行以内。提供必要的Unity Event回调如OnPointerDown、OnDrag。每条注释使用中文简洁说明意图。喂了这段参考之后ChatGPT生成新脚本时风格会明显向这个方向靠拢。你可以把这种提示方式理解成给外包设计师看“设计规范手册”模型是一个理解能力很强但缺少项目审美共识的外包你把规范给它它就能按规范输出。5.3 实操案例让AR组件模块划分更清晰我最近用少样本方法让ChatGPT生成一个“AR模型柜”的交互组件。需求是点击柜门打开抽屉、放大视角查看模型、双击还原视角。在提示词里放了一段项目现有的ARInteractable作为风格参考并强调模块划分原则“交互状态相关的变量放一个InteractionState枚举里模型展示相关的方法放ModelDisplayController里相机视角控制放另一个独立组件里”。结果生成的代码虽然还是需要手动调整但整体模块分割已经比较专业了每个脚本只负责单一职责。这比之前拿到一个几百行的“God Object脚本”再拆出来节省的时间至少是半小时起步。6. 技巧五先让模型“找茬”再做实现6.1 把指令从“生成代码”改成“先审需求”这个技巧是我在连续被几个运行时崩溃折磨之后总结出来的。AR交互脚本复杂的地方在于写代码只是一个动作真正难的是提前想清楚哪些地方会出错。而ChatGPT在直接“生成代码”模式下往往倾向把事情简化把异常处理忽略掉。后来我换了一种玩法先让它当审查员不要急着写代码。我会发一句先不要写代码。请审查下面这个AR交互需求指出至少5个可能发生的边界问题、性能问题或生命周期问题然后再给出修改建议。这个反向步骤看起来多了一次对话实际上能省非常多的调试时间。6.2 让它自己列异常清单再补全逻辑举个例子。我要做一个需要长时间运行的AR展示应用用户可以在室内扫描平面后摆放虚拟家居。需求包括点击放置、双击删除、拖动旋转。如果直接生成代码很容易得到一份“理想环境下的Demo”。但当我把这个需求先交给ChatGPT审查时它列出了这些我差点忽略的问题用户相机权限未授予时AR Session不会正常启动。持续扫描平面会产生电量消耗和发热需要在生命周期内管理扫描开关。双击删除操作可能和单击放置操作互相冲突默认点击延迟会导致操作感知迟钝。Android端返回桌面时Unity的AR Session需要暂停回后台再回来时锚点可能会漂移。数量过多的虚拟物体同时存在会带来渲染压力最好做对象池。如果平面在放置后突然消失已生成物体的锚点会悬空。这些内容看起来是常识但真到了“一口气写完功能”的时候开发者尤其是新手经常一条都顾不上。让模型生成代码之前先列异常清单相当于免费获得了一次代码评审。6.3 我用这个技巧抓出来的典型遗漏现在我在写R提示词模板里通常会预留一个固定环节列出风险清单 → 针对风险逐条给出处理方案 → 最后生成代码。这个方法帮助我抓出过很多典型遗漏。权限问题是最高频的。ChatGPT默认在ARFoundation代码里只写CameraPermission的调用但真机调试时还要考虑权限拒绝、永久拒绝、以及权限回调时AR Session的状态。另一个是高危的生命周期问题比如应用切到后台再回来AR World Origin可能变化之前生成的位置坐标全都不对。还有一个特别容易出现的问题是适配不同机型的屏幕安全区域和FOV如果不提前提醒模型它生成的屏幕点击坐标很可能会在刘海屏或超长屏上产生偏移。把这些风险丢回给模型让它生成处理逻辑比自己在真机上反复调要快得多。7. 常见问题与排查技巧实录7.1 ChatGPT生成的AR代码编译不过怎么办这是我用ChatGPT辅助AR开发时遇到最多的问题。原因通常出在命名空间缺失、API版本过期、或者Unity版本与AR Foundation版本不匹配。我的处理方式不是手动一顿乱补而是把报错信息原样贴回给ChatGPT同时在提示词里加上一句“项目使用Unity 2022 LTS和AR Foundation 5.x请根据报错信息修复代码并重新输出完整脚本。”这一招的成功率非常高因为编译错误大多是可确定的语法或引用问题大模型看着报错信息修复代码的能力比自己瞎翻文档要强不少。只需要注意在粘贴报错信息时把路径和项目内部类名敏感信息做脱敏处理。7.2 真机上坐标偏移、物体乱跳这个问题十有八九出在坐标系混用上。屏幕坐标默认以屏幕左下角为原点但Unity的触摸坐标也是屏幕坐标看起来一致可在进行射线命中测试时如果误用了视口坐标或者世界坐标就会出现明显偏移。我的排查习惯是在提示词里要求ChatGPT在关键计算位置加上Debug日志把触摸坐标、射线命中坐标、生成物体坐标全部打印出来。这类日志输出看起来笨拙但对于确定坐标偏移原因非常有效。如果发现生成物体坐标和射线命中坐标在数值上就不一致那问题大概率是坐标转换写错如果坐标一致但视觉上依然不对那就要查相机和AR Session原点之间的错位了。7.3 对话越长输出质量越差ChatGPT一旦聊了太多轮尤其是多次修改同一个小功能之后后面的回答质量会明显下降甚至开始自己改掉前面已经确定的结构。这是典型的上下文污染问题。我的对策是每完成一个独立的小功能就新开一个会话把项目背景用模板重新粘贴一遍。可以把常用的项目背景描述做成一个提示词模板里面写好技术栈、SDK版本、代码风格、已经使用的模块名称每次开新会话时直接复用。这样既不会丢失关键信息也避免了长时间对话导致模型越改越乱。7.4 提示词太长被截断怎么办有朋友问过我上面展示的提示词模板都很长直接复制后ChatGPT输出的内容变短了或者中间断掉。这是因为上下文窗口是有限的尤其是当对话里已经有很多历史记录时新发一条超长提示很容易被截断。我的做法是把长需求拆成几段发送一次只让模型处理一个小目标。比如先让它“列状态转移表”等它输出结束后再跟一句“根据上面的状态表生成C#脚本”。这样每一轮的输入输出长度都保持在合理范围内模型不会因为信息过载而开始胡编。7.5 敏感项目如何安全使用大模型AR项目有时会涉及未公开产品的外观设计、内部代号甚至商业展台的模型。我的原则很直接不把核心美术资源、未公开的模型素材、内部命名规则原样发给ChatGPT。如果要让模型帮助写代码可以先把敏感名称替换成GenericName等生成完再替换回来。这类替换对交互逻辑的生成几乎没有影响因为模型不需要知道你具体放置的是最新的汽车模型还是营销展台它只需要知道“我有一个需要识别的目标对象”就够了。上线前再统一把占位符改回正式的名字这样既能用上大模型的高效又不会把商业机密泄露出去。8. 让这套方法真正融入日常AR工作流如果你把上面五个技巧组合在一起用其实就是一套完整的AR交互脚本生成SOP先定义角色和版本再拆状态机再加上数学约束接着给风格参考最后让模型先审查再实现。这套SOP我沉淀成了团队内部的“AR提示词库”新同事接手AR项目时直接复用提示词模板能在很短时间内生成质量稳定的脚本初稿。最后再分享一个我个人的习惯无论ChatGPT生成的结果看起来多靠谱我拿到代码后一定会先做一个最小可验证Demo。只保留最基本的功能比如放一个Cube在桌面上确认物体能稳定跟随平面移动再考虑动画、特效、网络同步这些业务层内容。这么做是因为AR开发里很多Bug并不是逻辑错误而是真实设备的环境差异导致的大模型无法完全替你验证真机效果。所以让ChatGPT帮你承担那些重复、模式化、API琐碎的工作把省下来的时间和精力用在真机调试和体验打磨上这才是提示工程对AR开发最实际的价值。希望这几个技巧对你手头的项目也有用。