Skip to content

一个 AI 游戏引擎的解剖:提示词背后到底有什么

作者:Mariana Muntean,Cinevva CEO

陌生人对 Cinevva 最常说的一句话是:这就是个 AI 套壳。他们打开首页,看到一个写着 "Describe your game" 的输入框,就觉得自己看懂了产品。他们看懂的是大门。产品是你打字时看不到的那一切,再加上从本周起,玩家走进来寻找你的游戏的那个开放世界。

输入框后面是一整套游戏引擎:一个带 26 个类型化工具的编排器,一批生成式模型,一个跨十一个素材源的聚合搜索,一个 agent 能读能写的实时游戏 iframe,还有一个店面——同一个 agent 会把你做完的游戏作为可以划动播放的游戏短视频上架。这些都不稀奇,全是管道。有意思的工作是决定把哪根管子接到哪根管子上。

这篇文章从上到下走一遍这台机器。我们给技术型投资人是这套解释,给想参与贡献的开发者也是这套解释。他们想要的是同一个答案。

1. 提示词是表层,不是系统

The Cinevva prompt input on the homepage. A single text field reads 'Make a neon space shooter with asteroids, power-ups, and a synth soundtrack.' Below it are three suggestion chips and the Cinevva logo.

第一个设计决定是:在用户真正下场之前,把一切都藏起来。首页只有一个任务,就是把一句话变成一个项目。我们把整个体验分成对外的一侧(提示词、案例展示、店面信息流)和创作者一侧(IDE、素材工具、发布流程),这样只想玩的人不必盯着驾驶舱看。

所以占位符会轮播 "Make a snake game with neon graphics" 和 "Top-down zombie shooter" 这种句子。它们不是教程。它们是一张许可证。用户看到原来 "一个奇怪的街机点子" 也是合法输入。

你按下提交的瞬间,会发生三件事。系统创建一个带稳定 ID 的全新游戏项目。它播下一棵空的文件树(index.htmlgame.jsstyle.cssassets/GDD.md)。然后把你那句话路由到编排器,附带一个指向这些空文件的项目上下文窗口。从这一刻起,你面对的是一个有双手的 agent。

2. 输入框背后,是一整个浏览器 IDE

The Cinevva creator IDE in dark mode. Three panels: a file tree on the left with GDD.md, index.html, game.js, style.css and an assets folder; a syntax-highlighted code editor in the middle showing a Three.js renderer setup; and a live game preview on the right showing a top-down neon space shooter with a SCORE and LIVES HUD.

创作者工作区是一个三栏 IDE,完全跑在浏览器里。左边文件树,中间代码编辑器,右边实时游戏 iframe,底部贯穿一条聊天输入。这个布局是刻意挑的。写过代码的人一眼就认得。不写代码的人可以无视中间那栏,全程只跟聊天框说话。

文件树不是比喻。每个项目其实就是一个小型静态站点,包含 HTML、JS、CSS、生成的图片、GLB 模型和音频文件,直接从 R2 经由 Cloudflare Worker 提供服务。没有构建步骤。这一点很关键。这意味着 agent 能读写你真正会发布的那些文件,也意味着同一份产物可以跑在 iframe 里,可以用 Capacitor 套在手机上,可以用 Tauri 套到 Steam 上,还可以作为 Embedded Activity 跑在 Discord 里。一套文件系统,六个分发目标。

我们要求每个生成的游戏在 window 上暴露两个函数。getGameState() 返回一个朴素对象,描述正在运行的游戏(玩家位置、得分、生命、敌人、计时器)。setGameState(patch) 把一个局部更新打回正在运行的游戏。这个小小的 API 是契约,让 agent 不用重载就能检查并修改一个运行中的游戏。第 6 节再讲为什么这么做。

3. 编排器,真正的引擎在这里

A diagram of the Cinevva orchestrator. A central node labeled 'Orchestrator (LLM)' is connected to eight tool nodes arranged around it: list_game_files, read_files, edit_files, write_files, generate_image (Flux), generate_skybox (Blockade), generate_music (ElevenLabs), and rig_model (Tripo). A dotted line connects the orchestrator to a 'Game iframe' node labeled 'screenshots + console.'

把这套东西叫 "AI 套壳" 的人漏掉的一块是:AI 与其说是在写代码,不如说是在指挥一支小型乐队。编排器是一个 tool-calling 循环,跑在一个前沿模型上,配着一份大约一千行的系统提示词和一个 26 个函数的类型化工具面。这些工具定义才是引擎。模型是指挥。

26 个工具分成五类。文件系统工具(list_game_filesread_filessearch_game_fileedit_fileswrite_filesdelete_filesrename_files)让 agent 把你的游戏当作任何普通代码库来处理。项目工具(create_new_gamelist_gamesopen_gameask_usergame_ready)处理项目的生命周期以及交回给人的那一步。生成式工具(generate_imagegenerate_skyboxgenerate_musicgenerate_sfxrig_modelapply_animationlist_animationslist_skybox_styles)会调用我们下一节会讲的那些专用模型。知识工具(search_fontslist_library_docssearch_library_docslist_generations)给 agent 提供可靠、有索引的事实来源,而不是凭空编出来的 API。运行时工具(read_console_logsexecute_js)让 agent 能看到并触碰运行中的游戏。

典型的第一轮大致是这样的。用户输入 "Make a neon space shooter"。模型先发一个 write_files 调用写出描述设计的 GDD.md,然后再发一次 write_files 写出 index.htmlgame.jsstyle.css。它用 prompt="synthwave space shooter, 120 BPM, driving bassline"generate_music,触发一个 ElevenLabs Music 上的任务,返回一个落在 R2 里的 MP3 URL。它用 Blockade Labs 的 model 3 风格调 generate_skybox 生成星空。它调 game_ready(title, message) 把 iframe 切到新构建,最后调 read_console_logs 确认游戏没报错就启动了。如果它看到一条堆栈,就会回到 edit_files 把它修掉,根本不等用户来汇报。

这个设计有意思的地方在于,整套东西里只有系统提示词和工具 schema 是产品特定的。换一个模型,其它一切照常运转。过去一年我们已经在三个前沿模型之间迁移过,没碰过这个表面,因为这个表面是我们自己的。

4. 素材这一侧:一个模型扇出

A three-panel asset generation dashboard. The left panel is a music generator with a prompt 'synthwave space shooter, 120 BPM, driving bassline,' a 60-second duration slider, and a Generate button, plus a playing waveform card titled 'Asteroid Drift Theme.' The middle panel is a skybox generator with the prompt 'deep space, distant nebula, two moons' and a grid of four 360 degree environment thumbnails. The right panel shows a rotating 3D model preview of a low-poly purple spaceship with a 'Rig + Walk' button and a status indicator that reads 'Rigging... 1m 42s left.'

agent 自己不生成图片、音乐、音效或 3D。它会调用专家。Cinevva 的素材这一侧是一个扇出到一组各自最强的模型,再粘合到一起,让一个的输出能直接喂给下一个。

对于图片和 sprite,generate_image 会调 Flux Pro 1.1,宽高永远是 32 的倍数,输出格式在 prompt 要求透明时切到 PNG。整首曲子由 agent 用风格 prompt 加秒数调 ElevenLabs Music。一次性音效由 ElevenLabs SFX 从 "laser gun firing, sci-fi blaster" 这种文本里产出一段 5 到 15 秒的片段。360 度环境由 generate_skybox 调用 Blockade Labs,从约九十种风格中挑,默认 model 3 Digital Painting。3D 角色由 rig_model 把一个 GLB 送到 Tripo 上蒙皮和绑定为两足、四足、六足、八足、蛇形或水生生物,再用 apply_animation 播放十五个预设里的任意一个(idle、walk、run、jump、climb、dive、slash、shoot、hurt、fall、turn,以及非两足类的行进动作)。

这些都是任务,不是同步调用。短则几秒,长则几分钟。编排器把它们启动了,立刻带着一个 jobId 返回,再由一条独立的通道在素材就绪时把结果送回对话。这彻底改变了使用感受。3D 模型在后台绑定的同时,agent 可以继续搭游戏逻辑。用户从来不用卡在某条关键路径上等。

所有产物都落到同一个地方。R2,挂在 cdn.cinevva.com 下,能用普通 URL 寻址。这意味着 agent 接下来的一次 write_files 可以直接嵌入 <audio src="https://cdn.cinevva.com/audio/abc.mp3">,游戏立刻就能用。没有 SDK,没有 asset bundler,没有 manifest。

5. 跨十一个素材源的搜索

The Cinevva asset search page in dark mode. A search bar at the top contains the query 'asteroid rock' and a row of provider filter pills shows All, PolyHaven, Sketchfab, Kenney, Quaternius, AmbientCG, OpenGameArt, Freesound, Smithsonian, Synty, and Jamendo, with Sketchfab highlighted. Below is a four-column grid of asteroid model thumbnails, each card showing its provider badge, a CC0 or CC-BY license tag, and a 'Use in game' button. A small caption in the upper right corner shows a chat bubble that reads 'ChatGPT: one of the best free asset tools for game devs.'

生成在你需要某样特定东西时很厉害。搜索在某样东西已经存在时更快。素材库 是一个跨十一个免费和授权素材源的联邦搜索,返回到一个统一排序的信息流里。

素材源注册表放在 worker 里,每次查询会并行打到 PolyHaven、Sketchfab、Freesound、Kenney、AmbientCG、Quaternius、OpenGameArt、Smithsonian 3D 收藏、TurboSquid、Synty 和 Jamendo。每个源实现一个共同接口(searchgetMetadataisBrowsablegetSupportedTypes),所以加一个新源就是一份 TypeScript 文件。聚合层负责处理各源分页方式不同的游标分页、去重 license、把素材类型归一到统一分类(model、texture、audio、hdri、sprite),还会给每个素材打上 license 标签,所以 agent 永远不会挑到一个它没法分发的素材。

上季度 ChatGPT 把这个工具推荐为给游戏开发者用的最好的免费素材工具之一时,我们去读了那条推荐。它说对了关键点。重点不是我们在某一个素材库上加了一条搜索栏。重点是一个独立开发者搜 "stone wall texture",PolyHaven 和 AmbientCG 的结果会并排出现,旁边还有 Kenney 的风格化版本和 Smithsonian 的一份摄影测量产物,一次查询,统一的 license 元数据。agent 可以打同一个 endpoint,按和人类一样的方式挑素材。

引擎里这一块经常被低估。多数游戏 AI 演示从零生成一切,最后所有东西都长着一种均匀的、亮亮的、有点诡异的脸。Cinevva 上有意思的游戏会把生成素材和 Smithsonian 来的真实 CC0 摄影测量、加上 Quaternius 一棵手工低多边形树混在一起。编排器一轮就能办到。

6. agent 自己玩游戏

A live debugging view. On the left, a running neon space shooter showing the player ship dodging asteroids with a SCORE of 4820 and 2 lives remaining. On the right, two stacked panels: an execute_js panel showing the call JSON.stringify(getGameState()) and a returned JSON object with player position, velocity, health, score, lives, and asteroid count, and a read_console_logs panel showing the most recent log lines including spawn asteroid, powerup picked, a texture load warning, and an FPS reading of 58.

这是我们展示时最让工程师惊讶的一段。agent 不只是把代码写进文件。它在一个沙箱 iframe 里跑游戏,读它的 console,分层截屏(UI 一层、3D 场景一层),并在实时运行时里执行 JavaScript 来检查或改变状态。

read_console_logs 返回 iframe 中 console.logconsole.warnconsole.error 以及未捕获异常的最近五十行。系统提示词要求 agent 每次 game_ready 调用之后,都必须调 read_console_logs 把错误修干净再交回给用户。就这一条规则,消除了其它工具里多数那种 "AI 说做完了但屏幕是黑的" 的情况。

execute_js 更狠。它在游戏的全局作用域里执行任意 JavaScript。因为每个游戏都被要求实现 getGameStatesetGameState,agent 可以跑 JSON.stringify(getGameState()) 把运行中游戏的全部状态读出来,再用 setGameState({player: {x: 500, y: 100}}) 把玩家瞬移,或者 setGameState({lives: 99}) 给一个无敌,或者 setGameState({level: 3}) 跳关。它也能戳更底层,比如 scene.children.map(c => c.type) 检查 Three.js 场景图,或者 document.querySelectorAll('canvas').length 确认渲染器挂载好了。

你能看出来为什么这件事重要。当用户说 "玩家在第二关会卡墙里",agent 不用靠猜。它打开第二关,跑 getGameState(),看碰撞数据,跑一个 execute_js 补丁试一个修法,只有验证过才把修法写回磁盘。它的调试方式跟你调试的方式一样。我们把 iframe 当同伴,不是当目标。

7. 库文档,那个无聊的事实来源

我们把游戏实际用到的那些库的官方文档(Three.js、Tone.js、Cannon,还在增加)索引到一个结构化、可搜索的 JSON 存储里。agent 在去翻开放互联网之前,先去用 search_library_docs("threejs", "Mesh")。它更快,有版本,也不会编出某个两个小版本前就被改名的方法。

这事不光鲜。但这是一个产出能跑代码的 AI 和一个产出看起来很像样、但跑到第四十行就崩的 AI 之间的差别。Cinevva 做出的游戏里大部分可见的质量都来自这一个决定。

8. 从能玩到能被发现:短视频和店面

A short-form gameplay reels storefront. In the center, a phone-shaped card plays a portrait video of a neon space shooter mid-combat with social UI icons stacked on the right (a heart with 14k, a chat bubble with 3.2k, a share arrow with 1.8k, and a 'Play Now' button). The reel label at the bottom reads 'Asteroid Drift • by @indiedev • 3.1M views.' To the left, a small chat snippet titled 'From the creator's chat' shows the assistant message 'Game is live. Reel auto-published to your storefront.' To the right, a Storefront panel lists three trending games: Asteroid Drift, Roadhawk Runner, and Birb Clicker, each with a view count and a 'Trending' badge.

没人玩的游戏就是一个私人爱好。独立游戏现在最难的没解决的问题已经不是做游戏,是分发。所以引擎不在 "能玩" 处停下。它停在 "出现在玩家面前"。

Cinevva 上每个项目都带一个稳定的分享 URL,形如 play.cinevva.com/{game-id},会在一个全屏 iframe 里打开该游戏的最新构建,上面有一个小小的覆盖层用于点赞和分享。当 agent 调 game_ready 时,它不只是切换 IDE 内的预览。它还会主动把一段 15 秒的游戏短视频发布到 Cinevva 店面。短视频是真的录像,直接从 iframe 抓出来(我们在游戏运行时里注入了一个小录制脚本),所以观众划过去的是真实的游戏过程,不是营销剪辑。

这改变了开发者每天经历的循环。旧循环是:写代码、构建、打包、上传、写一个 Steam 页面、跟算法较劲、盯愿望单计数。新循环是:打一句话、看 agent 搭出来、按发布、看你的游戏跟其它东西一起出现在同一个划动信息流里。发现发生在创作发生的同一个产品里、同一个 URL 下、同一个登录态下。

写给开发者社区读者:这是值得检查的一块。分发一直是游戏引擎本身没附带的护城河。Unity 出一个编辑器,你在 Steam 上发游戏。Unreal 出一个编辑器,你在 Epic Store 上发。Cinevva 两边都出。引擎和店面通过同一个搭出游戏的编排器互相对话。

9. Top Performers:发现飞轮

The Cinevva Top Performers chart. Three tabs at the top read Trending, Recent, and Top, with Top selected. Below, a podium row of three featured games: number one The Breaker Belt with 42.1k plays, number two Roadhawk Runner with 27.7k plays, and number three Asteroid Drift with 37.1k plays. Below the podium, a denser grid of six smaller game cards including Pixel Platformer, Zombie Shooter, Fruit Ninja Clone, Tower Defense, Card Battler, and Zombie Builder, each with thumbnails, creator handles, and play counts.

短视频信息流是飞轮的一半。Top Performers 榜单 是另一半。它按 Trending、Recent、Top 三个维度对游戏排序,权重用的是完成率(玩家有没有完整玩完一局),不是原始点击。完成率比安装数难刷。一个能拉住注意力六十秒的游戏,胜过一个打开又关上的游戏。

每一个信号都会回灌进编排器的下一轮。当 agent 说 "我们加个 power-up",它不是从一个固定的模式库里翻。它是从一个见过这个月 Cinevva 上哪些机制真的能留住玩家的模型里翻。飞轮不是页面底部那张图。它是整个引擎的训练信号。

写给投资人:这是数据护城河。我们不只有生成的游戏。我们有附着了真实会话级互动数据的生成游戏,挂着触发它们的提示词,挂着 agent 当时挑的素材,挂着喜欢它们的玩家。每一圈都让下一圈更紧。

10. 引擎变成一个游戏

接下来这一段,我在社交平台上吊了好几个月。第 1 节到第 9 节说的是一套搭游戏的系统。更难解释的、要看见才能明白的,是当这个系统本身变成一个地方时会发生什么。

哪怕我们已经上线了这么多东西,做游戏还是个累活。如果你从没做过游戏,你会突然要为剧情、角色、世界、机制负责,要决定谁在什么时候做什么,光怎么走,特效怎么叠,音乐、音效、镜头怎么动。事多。而且在所有这些之上,你想让做出来的东西觉得是你的,不是别人工具吐出来的模板。提示词和编排器替你干了大部分机械活。它们一个人办不到的是:给你做完的东西一个有别人看着的舞台。

所以我们把舞台搭出来了。今年大半年 Oleg 和引擎团队一直在发布一个 14 篇的系列,讲怎么把一个开放世界塞进浏览器。能实时雕的地形。会根据坡度和海拔自动给自己贴岩石或草地的群系。80,000 根草,长在计算着色器生成的地形上、随风弯。一个角色,能在高度图地形和体素地形之间一步连着走、冲刺、跳、滑翔。没一项是为技术演示而做的。它是为这个东西准备的基底。

今天开放世界已经以早期形态上线了。你套上一个虚拟形象走进去。你发布过的游戏会作为可造访的空间出现在你周围,就像 店面短视频Top Performers 榜单 现在展示它们的方式,只是你这次是用脚走过去,不是划进去的。你可以不离开这个世界就跳进一个陌生人的游戏。你可以站在你刚玩过那个东西的作者旁边,告诉他接下来该加什么。你可以跟一个刚认识的人一起雕一块地形,把它做成一个新项目的种子。发现不再是一个信息流。它变成一次散步。

我们的引擎一直在技术意义上是游戏引擎。今天它也在字面意义上变成游戏引擎。那个搭你游戏的东西,自己也是一个游戏,而第 3 节那个编排器、第 4 节那条素材轨道、第 6 节那个 getGameState 契约、第 8 节那些短视频、第 9 节那张榜单,全都拼进你的玩家走来走去的同一个地方。"做" 和 "玩" 之间的边界一直是人为画的。现在没了。

我们觉得自己做对的几件事

第一件做对的事是:把提示词当作一个 UI 手感,不是产品。产品是编排器、工具面、素材轨道和店面。提示词是把用户装进系统最便宜的办法。

第二件是坚持一个扁平的、浏览器原生的文件系统,没有构建步骤。所以一个 Cinevva 游戏能从一份事实来源里发到手机、桌面、Steam 和 Discord 上。所以 agent 能读到它自己写过的内容。

第三件是 "每个生成的游戏都实现 getGameStatesetGameState" 这条契约。系统提示词里的这一行,就是 agent 像合作者而不是代码生成器的原因。agent 能玩,能玩的系统才能调试。

第四件是把店面接进引擎所在的同一个循环。我们不会在原始模型质量上赢。比某个开放权重的生成器领先两个月,没什么可守的。我们赢的方式是:搭你游戏的那个 agent,也负责把它发布出去、衡量它、从陌生人怎么玩它中学到东西。

想看整台机器跑起来,首页那个提示词仍然是大门。打一句话。看它背后发生什么。然后回到这里告诉我们引擎里哪一块该下一篇写。