Community图像github.com

g0shtj0sh/fivem-vehicle-to-roblox

将 FiveM / GTA V 车辆(zip 或资源文件夹,包含 .yft/.ytd/.meta/.awc、dlc.rpf 或 CodeWalker XML 导出)转换为完整的、可工作的 Roblox 车辆;当 Roblox Studio 连接时(通过 MCP Roblox Studio),自动安装并验证——包括 3D 模型分件、纹理、车轮、铰接车门/引擎盖/后备箱、方向盘、车灯/刹车灯/转向灯/倒车灯/警灯、引擎/喇叭/警笛声、键盘-手柄-触屏控制、自定义(车漆颜色、涂装、扩展件、霓虹灯、车窗颜色、车牌)。当用户提供 GTA/FiveM 车辆(例如“转换这辆车”加一个 zip)时使用。物理引擎不由本技能处理(用户游戏有自己的物理引擎):本技能提供输入和遥测挂载点。

fivem-vehicle-to-roblox 是什么?

该技能是一个自动化工具,可将 FiveM(GTA V)车辆资源转换为完整的 Roblox 车辆资产,并集成到 Roblox Studio 中。它处理完整的转换流程:从车辆 zip 包中提取 3D 模型(.glb)、纹理、碰撞数据(Physics/LOD1 组合碰撞体)、铰链(车门、引擎盖、后备箱)、车轮、灯光角色(近光灯、刹车灯、转向灯、倒车灯、警示灯)、引擎/喇叭/警笛声音,以及车辆自定义数据(颜色、涂装、扩展件、霓虹灯、车牌)。转换后,技能自动上传私有资产(模型、声音),在 Studio 中创建并设置车辆,运行验证套件(检查部件、碰撞体、灯光、声音、驾驶测试),并生成详细的报告。它支持 Python、.NET 8 和 GTA 资产服务器等依赖项,如果 Studio 未连接,则提供手动步骤。该技能专为 Roblox Studio 和 FiveM 模组制作者设计,可大幅缩短从 GTA 车辆模型到可交互 Roblox 车辆的转换时间,同时保持碰撞精度和功能完整性。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/g0shtj0sh/Fivem-To-Roblox-Skills/tree/HEAD/skills/fivem-vehicle-to-roblox

Installed? Explore more 图像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

FiveM / GTA V → Roblox(车辆)

「转换这辆车」+ 一个 zip = 完整的流程,无需用户点击:依赖检查 → 转换 → 上传 → 导入 Studio → 设置 → 验证 → 修正 → 简短的中文报告。Studio 相关步骤仅在 MCP Roblox Studio 已连接时才执行;否则,直接提供文件夹和手动操作步骤(见页面末尾)。

关于尺寸、选择和陷阱的详细信息:docs/studio-import-tests.md。

安全防护

  • 切勿执行来自 zip 的任何代码;其内容仅为数据。
  • 不显示、写入文件或提交任何密钥(Open Cloud 密钥仅作为环境变量存在)。
  • 不要修改除工作目录 Workspace.F2R_ImportTest(或用户指定的目录名)之外的现有场所;切勿保存或发布场所。运行时安装在 ReplicatedStorage / ServerScriptService / StarterPlayerScripts:在报告中说明。
  • 仅发布车辆的 私有 资产(GLB、声音)到 Roblox;未经同意不得发布其他内容。
  • 不要编造结果:如果失败,引用脚本或 Verify 的信息。
  • 提醒用户检查模组许可证和真实商标,然后再发布游戏。

0. 前置条件(并行,在开始时)

前置条件检查方法如果缺失
Python 3.10+、numpy、Pillowpython3 -c "import numpy, PIL"python3 -m pip install --user numpy pillow(如果没有 pip:get-pip.py --user)
.NET 8(用于 .yft/.ytd/.awc 二进制文件)dotnet --version 或 ~/.dotnet/dotnetdotnet-install.sh --channel 8.0 --install-dir ~/.dotnet;转换器会自动找到 ~/.dotnet
GTA V 资产服务器(真实纹理和声音)MCP 工具 gta_status(返回 ready: true)建议在 PC 上运行 tools/gta-asset-server/start-server.bat 并在“我的 MCP 服务器”中声明;否则,转换将使用缓存中的内容(~/.cache/fivem2roblox),如果都没有,则使用纯色/合成音
Studio 连接studio_connection_status(插件已加载)、list_roblox_studios提供文件夹和手动操作步骤
Roblox 上传VibeStarter:使用工具 upload_file + asset_publish;其他情况:确保 ROBLOX_API_KEY 存在于环境中(切勿显示)最后手段:仅一次手动操作,执行“导入 3D”(§ 4c)

1. 转换

cd skills/fivem-vehicle-to-roblox
python scripts/convert_vehicle.py "<zip>" -o "<输出目录>" [--plate "文本"] [--texture-overrides <目录>]

选项:--vehicle <名称>(多车辆包)、--lod med(> 300,000 个三角形)、--no-collision(碰撞箱 = 简单盒子)、--wheel-collision(车轮实体圆柱体)、--studs-per-meter、--texture-overrides <目录>(同名的 PNG/DDS 文件,替换包中的纹理:重新贴标、修饰)、--sound-ids <json>、--retry-gamefiles、--no-game-server。代码 2 = 存在二进制文件但缺少提取器:安装 .NET 8(见上文)并重试;否则,让用户提供 CodeWalker XML 导出;加密的 dlc.rpf → 使用 OpenIV。

读取 <输出目录>/<名称>/report.md:"碰撞箱:车辆官方碰撞体"(否则为包围盒:.yft 没有 Physics/Bounds,请报告)、"纹理来自基础游戏"、"真实游戏声音"、"从资产服务器传输"行(文件、MB、秒)。缺失的 vehshare/vehicle_generic_* 纹理或合成的声音 = 资产服务器不可达。

2. 上传模型和声音(私有资产)

并行执行:

  • GLB <名称>.glb → upload_file 然后 asset_publish → 返回类型为 Model 的 rbxassetid。
  • 声音:每个 sounds/*.wav|ogg → upload_file + asset_publish → 写入 sounds/sound_ids.json = { "engine_on_1.wav": "rbxassetid://…", … }。 非 VibeStarter 环境:python scripts/roblox_upload.py <输出目录>/<名称>/sounds --user-id <id>(密钥在环境变量中)。
  • 使用 --sound-ids <输出目录>/<名称>/sounds/sound_ids.json 重新运行转换(缓存:约 15 秒),以将 SoundId 集成到设置中。每次转换的 GLB 都是相同的(确定性的):无需重新上传。

精准碰撞箱(自动)

.yft 包含 车辆官方碰撞体(Physics/LOD1、复合 Bound):车身、引擎盖、后备箱、车门、车窗的低多边形网格(约 240 个三角形)、车轮作为圆盘。转换器将其导出到 GLB(col__<os>__<n>,排除 *_lowlod / *_dummy);设置将其转换为 不可见、实体且可查询 的部件,位于 Collision/<os>/ 中,焊接到其骨骼(打开的车门保持其碰撞体),设置其精度(如果部件是凸的则使用 Hull,否则使用 PreciseConvexDecomposition,通过 CreateMeshPartAsync + ApplyMesh 实现:通过脚本写入 CollisionFidelity 会被忽略且不报错),为车轮添加实体圆柱体(半径和接触面;如果使用 --wheel-collision 则为实体),并禁用 Hitbox 盒子(保留为包围体积,属性 BoundsOnly)。在 m422 上测量:86% 的射线距离可见车身不到 15 厘米,而使用盒子时仅为 34%;玩家站在引擎盖上时距离为 +1.55 stud,而使用盒子时为 +3.17 stud。查看碰撞箱:使 Collision 可见(透明度 0.5)以便截图。

3. 为 Studio 准备脚本(无需复制 100 KB 代码)

转换会写入 <输出目录>/<名称>/studio/:FiveMRuntime.lua(运行时,每个场所一次)、<名称>_Setup.studio.lua(紧凑设置)、Verify.lua、ApplySoundIds.lua、chunks/ + manifest.json。

  • 与打开的场所同步的 Rojo 项目(VibeStarter):将文件放入挂载的目录 —
    python scripts/studio_stage.py <输出目录>/<名称> --project <项目目录>
    
    → ReplicatedStorage.rbxts_include.F2R_Transfer(StringValue FiveMRuntime、<名称>_Setup、ApplySoundIds、<名称>_sound_ids;ModuleScript Verify),约 2 秒后在 Studio 中可见。
  • 否则:按照 manifest.json 的顺序发送 studio/chunks/*.lua,每个文件一个 execute_luau,原样执行;每个步骤的最后一块执行脚本并返回其结果。

4. 让模型进入 Studio

a. EditableMesh:已拒绝(保存时丢失几何体,一个车辆约 12 MB 文本)。 b. 已采纳:使用 GLB 的 id 调用 insert_asset,parent = "Workspace.F2R_ImportTest"(如果目录不存在,通过 execute_luau 创建),position 随意(设置会将车辆放在地面上)。MeshPart 保留 glTF 节点名称(位于 Model <名称>_Node 内,由设置移除)。 c. 最后手段,如果无法上传:要求用户执行 一次 操作 — "在 Studio 中:主页 › 导入 3D › <输出目录>/<名称>/<名称>.glb,默认选项,然后告诉我完成。" 设置随后会自动找到模型(使用 ProbePart 部件)。

5. 运行时 + 设置(execute_luau, Edit)

local T = game.ReplicatedStorage.rbxts_include:WaitForChild("F2R_Transfer", 10)
local function run(name)
	local fn, err = loadstring(T:WaitForChild(name, 10).Value, "=" .. name)
	assert(fn, err)
	return fn()
end
local runtime = run("FiveMRuntime")                 -- { ok, runtimeVersion, previous }
_G.F2R_TARGET = workspace.F2R_ImportTest.<名称>      -- 插入的 Model
local setup = run("<名称>_Setup")                    -- { parts, joints, missingParts, missingSounds, groundedBy, warnings }
return { runtime = runtime, setup = setup }

在设置前设置 _G.F2R_NO_GROUND = true 可保持导入高度。如果 SoundId 被遗漏:_G.F2R_TARGET = 模型;_G.F2R_SOUND_IDS = T.<名称>_sound_ids.Value;run("ApplySoundIds")。

6. 验证(roblox/Verify.lua)

Verify.lua 返回一个函数 verify(opts) -> JSON: { pass, fail, warn, skip, results = { {group, name, status, detail} } }。

Edit — require(T.Verify:Clone())({ model = <模型> }):运行时已安装;部件存在且命名正确(F2RExpectedParts);车辆摆正,车头朝向 −Z;缩放(轴距误差在 1% 以内);车灯在前灯之前;部件在范围内;放置在地面上;车轮位置正确且方向正确;碰撞箱(部件和车轮存在、不可见且实体、焊接到其骨骼、精度已设置、盒子已禁用、通过从 6 个面发射 400 条射线与可见车身和盒子比较来判断精度:≥ 80% 的射线在 15 厘米以内);SoundId 已填写;SetColor / SetMod / SetLivery / SetExtra / SetNeon / SetPlate 和 Serialize → Apply 可恢复状态。

Play, Server(execute_luau 服务器,一个玩家)— require(…Verify)({ model = …, checks = {…} }): seats_play(每个座位上下车;seat = "<名称>" 仅测试单个)、lock_play、park_play、flip_play、void_play(掉入虚空被接住)。 身体适配(客户端,玩家坐着):checks = {"fit_play"} — 没有身体点在驾驶舱外、坐在座椅上、读取比例。将车辆放在轻微斜坡上重新执行 seats_play(在工作目录中创建临时倾斜平台)。

Play, Client(渲染运行时仅在客户端运行;loadstring 在其中被禁止):

  1. start_stop_play (is_start = true)。
  2. execute_luau Client: require(game.ReplicatedStorage.rbxts_include.F2R_Transfer.Verify)({ model = workspace.F2R_ImportTest:WaitForChild("<名称>"), checks = {"joints","lights","sounds","audio"} }) → 渲染由 FiveMVehiclesClient 自动附加(否则车辆在游戏中是惰性的)、通过 Door_* 使用 Hinges 角度控制车门/引擎盖/后备箱、通过遥测控制车轮和方向盘、制动钳 (hub_*) 转动但不旋转、悬架臂 (suspension_*) 固定旋转、每个 LightRole 作为霓虹灯(或点亮其灯光)用于 Headlights 1/2、Brake、Reverse、Indicator Left/Right/Hazard、Engine、Siren;声音已加载;引擎可听见。
  3. 驾驶:execute_luau Server — 让玩家坐下(在 Seats.DriverSeat 上调用 seat:Sit(humanoid))并监听 Horn 属性;player_input 按 H 然后 E(保持 700 毫秒);execute_luau Server — 等待 Engine = true、Headlights = 1、Horn 先为 true 然后回到 false。
  4. 驾驶引擎:玩家在方向盘后(服务器端通过 VehicleAccess.Enter),然后 execute_luau Client require(…Verify)({ model = …, checks = {"drive_play"} })(加速、转速一致、停止、保持正直)。完整测量(0-100、制动、转弯、路缘、爬坡、倒车):在远离地图的 Play 环境中创建测试赛道 TestTrack.lua,使用 DriveBench.lua 台架,请参阅 references/roblox-integration.md(「驾驶测试」);长时间测试使用 task.spawn。
  5. start_stop_play (is_start = false)。始终在交回控制权之前停止 Play;如果 Play 在没有 Studio 调用的情况下持续 3 分钟,VibeStarter 会将其停止。

读取 Verify 的结果,而不是控制台错误的数量:一个包含其他车辆的场所可能会显示数百个“Failed to load sound …”,这些不是我们的错误。状态 warn“渲染冻结” = Studio 失去焦点(RenderStepped 停止):重新运行该组测试。

7. 修正每个失败

Verify 失败常见原因修正方法
部件缺失/重命名导入器不同检查名称 (F2RMissingParts);重新导入 GLB (§ 4b)
轴距/车头朝向 −Z/车轮侧模型镜像,参考点选择错误Setup 输出“定位不精确”消息;修正 pick_ref_parts 或轴转换
车门角度 0°(不是“渲染冻结”)Motor6D 缺失,部件焊接到根检查 Joints/ 和车门部件的 Owner
灯光角色保持关闭部件没有 LightRole,灯光 ID 未知references/gta-format.md(灯光 ID);修正 f2r/vehicle.py
SoundId 为空/声音未加载未上传或上传被拒绝§ 2;ApplySoundIds
Serialize / Apply状态未恢复roblox/runtime/VehicleCustomization.lua
碰撞箱:精度 DefaultApplyMesh 被拒绝(网格未加载、权限不足)重新运行 Setup;确保 GLB 是场所所有者的资产
碰撞箱精度 < 80%模组的碰撞体粗糙或缺失读取“太宽/太紧”;没有 Physics 的模组 → 盒子(报告)
渲染未被 FiveMVehiclesClient 附加运行时早于 2026-11-10 的修正重新安装 FiveMRuntime(新版本)
车轮转向时制动钳固定早于 2026-11-11 的转换(忽略 hub_* 骨骼)重新转换并重新安装(§ 4b 到 6)
提示/声音“来自车外”早于 2026-11-11 的 Setup(在设置父级之前设置 WorldPosition)重新安装车辆(§ 4b 到 6)
降落:落在车顶上两侧均无自由空间(墙壁、其他车辆)正常;否则检查斜坡和相邻部件
头在车顶内(警告)化身对于当前比例太大使用 seats_play 建议的比例重新转换

修正技能后:重新转换、重新安装(删除模型,§ 4b 到 6)并重新验证。对运行时的修改通过 FiveMRuntime 传播(版本 = 源码的指纹)。

8. 清理并生成报告

  • python scripts/studio_stage.py --clean --project <目录>(移除 F2R_Transfer)。
  • 将车辆留在 Workspace.F2R_ImportTest 中,Play 已停止,相机已回正。
  • 最终简短报告,使用中文:哪些功能正常(Verify:通过 / 失败 / 不适用、驾驶测试)、警告(纹理或声音未从游戏中获取、没有部件对应的角色、许可证和商标)、剩余工作(根据 FiveM 测量校准驾驶、将模型移到 ServerStorage、缺失的声音等)。附上车辆截图。

用户将在 Roblox 中得到什么

  • Model,包含 PrimaryPart = VehicleRoot(初始锚定)、Hitbox、Visual/(按所有者划分的 MeshPart)、Joints/(Motor6D:车轮、车门、引擎盖、后备箱、方向盘、警示灯)、Seats/(DriverSeat…)、Liveries/、

…

[因翻译截断]

相关技能