技能版本 1.0.0

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. 为组织安装

    开通即安装:组织固定使用开通时的版本(当前为 1.0.0)。升级到新版本需要取消后重新开通。

  2. 创建凭证

    客户端使用组织凭证读取;绑定到数字人后,数字人使用绑定凭证按需加载。请求中携带:

    Authorization: Bearer $ZGI_MARKET_KEY

  3. 读取清单与安装包

    清单列出版本、文件和校验值;安装包是一个 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 SceneTree

SKILL.md 不止这些内容,安装后可阅读全文。

技能包内容

共 1 个文件,合计 11.2 KiB

  • SKILL.md11.2 KiB

来源与审核

审核状态
尚未审核,内容来自上游来源
许可证
未说明

审核状态是平台对上架信息的记录,不构成对上游服务质量或可用性的担保。