godot-asset-path-surgery
Fix stale absolute paths baked inside Godot binary resources (.mesh / .material / .scn / .res / .tres) after a folder rename, migration, or Phase-3-style restructure. Use this skill whenever the user reports editor errors like "Cannot open file 'res://<old path>'", "Failed loading resource", "referenced non-existent resource at", or when they've just moved a folder and the editor console lights up red even though the files exist at the new location. Also use when they ask "how do I rename/move a
价格
免费
- 安装:免费
在组织开通时一次性收取;再次读取清单或下载不重复收费。
以上为公开标价。你的组织可能有协议价,以控制台显示的价格为准。
如何使用
为组织安装
开通即安装:组织固定使用开通时的版本(当前为 1.0.0)。升级到新版本需要取消后重新开通。
创建凭证
客户端使用组织凭证读取;绑定到数字人后,数字人使用绑定凭证按需加载。请求中携带:
Authorization: Bearer $ZGI_MARKET_KEY读取清单与安装包
清单列出版本、文件和校验值;安装包是一个 zip 文件。
读取清单 curl "https://market-api.zgi.im/v1/market/skills/godot-asset-path-surgery/manifest" \ -H "Authorization: Bearer $ZGI_MARKET_KEY"下载安装包 curl "https://market-api.zgi.im/v1/market/skills/godot-asset-path-surgery/package" \ -H "Authorization: Bearer $ZGI_MARKET_KEY" \ -o godot-asset-path-surgery.zip读取清单和下载安装包不计入用量。下载后请用响应头中的 SHA-256 校验文件。
技能说明
- 名称
- godot-asset-path-surgery
- 说明
- Fix stale absolute paths baked inside Godot binary resources (.mesh / .material / .scn / .res / .tres) after a folder rename, migration, or Phase-3-style restructure. Use this skill whenever the user reports editor errors like "Cannot open file 'res://<old path>'", "Failed loading resource", "referenced non-existent resource at", or when they've just moved a folder and the editor console lights up red even though the files exist at the new location. Also use when they ask "how do I rename/move an asset folder in Godot without breaking references".
技能包内没有脚本文件:这个技能是供模型阅读的文本。
SKILL.md 节选
# Godot Asset Path Surgery
> **When to invoke**: user is staring at red errors of the form
> `Cannot open file 'res://old/path/thing.material'` *while the file
> obviously exists at a new path*. This is almost always because a binary
> resource has the old path hard-coded in its payload (Godot bakes
> `ExtResource` paths into `.mesh` / `.material` / `.scn` / compressed
> `.tres` / `.res` at save time).
---
## Core insight
Godot resources carry **two kinds of path information**:
| Kind | Where | Update mechanism |
|---|---|---|
| **Discovery path** (how the editor finds the file) | `.godot/uid_cache.bin`, `<file>.uid` sidecar | Auto-updated by Godot when it sees the file move |
| **Internal ExtResource paths** (who this file references) | **Inside the binary payload** of the file | **Not auto-updated** — the file must be `load()` + `save()` again to rewrite them |
Phase-3-style folder migrations fix kind #1 for free but **silently break kind #2**. Symptom: editor reports broken refs; game often still runs because `load()` can still find the target via UID, but the error panel is polluted and hides real issues.
---
## Decision tree
```
Editor shows: "Cannot open file 'res://<old-path>'"
│
├─ Does the target file exist at the new path?
│ ├─ No → you actually deleted it. Restore it or fix the reference.
│ └─ Yes → go to next check
│
├─ Is the error coming from a *binary* resource (.mesh/.material/.scn/.res)?
│ ├─ No → it's a plain .tscn/.tres referencing the old path by text;
│ │ use sed/IDE search-replace on the text file and you're done.
│ └─ Yes → use the surgery pattern below (file's internal payload
│ carries the stale path as UTF-8 bytes).
│
├─ Does the affected binary ALSO depend on another resource that also moved?
│ ├─ No → Pattern A (simple resave).
│ └─ Yes → Pattern B (shim + reassign + resave), because ResourceLoader
│ refuses to open a file whose ExtResource target is missing.
```
---
## Pattern A — Simple resave (self-contained binary)
**When**: a `.mesh` / `.material` / `.scn` carries a stale *self-path* header
or a stale external path, but the target of that external path still exists
(just at a new location accessible by UID).
```gdscript
# tools/resave_<thing>.gd -- SceneTree-mode one-shot
extends SceneTree
const PATHS := [
"res://art/models/<new>/thing.mesh",
"res://art/models/<new>/thing.material",
]
func _initialize() -> void:
var failed := 0
for p in PATHS:
var res := ResourceLoader.load(p, "", ResourceLoader.CACHE_MODE_IGNORE)
if res == null:
push_error("[resave] load failed: %s" % p)
failed += 1
continue
# Force the in-memory resource_path to match the on-disk path so
# ResourceSaver doesn't keep the stale path baked into the header.
res.resource_path = p
# FLAG_COMPRESS preserves the original RSCC compression; without it
# binary resources (esp. .material) may bloat 3-5x.
var err := ResourceSaver.save(res, p, ResourceSaver.FLAG_COMPRESS)
if err != OK:
push_error("[resave] save failed (%d): %s" % [err, p])
failed += 1
continue
print("[resave] ok: ", p)
quit(0 if failed == 0 else 1)
```
Run:
```bash
/Applications/Godot.app/Contents/MacOS/Godot --headless --quit \
--path . --script tools/resave_<thing>.gd
```
---
## Pattern B — Shim + reassign (binary with broken ExtResource)
**When**: the binary resource internally references an `ExtResource` whose
*path* is stale, and Godot refuses to open the binary ("Can't load
dependency"). Pattern A won't work because `ResourceLoader.load()` fails
before you can rewrite the resource.
**Strategy**: temporarily place the dependency's current content at the
*old* path so the loader resolves, retarget the reference to the *new*
path in memory, save, clean up the shim.
```gdscript
# tools/resave_<thing>.gd -- SceneTree-mode one-shot
extends SceneTreeSKILL.md 不止这些内容,安装后可阅读全文。
技能包内容
共 1 个文件,合计 11.2 KiB
- SKILL.md11.2 KiB
来源与审核
- 审核状态
- 尚未审核,内容来自上游来源
- 许可证
- 未说明
审核状态是平台对上架信息的记录,不构成对上游服务质量或可用性的担保。