Files
agame/.workbuddy/memory/2026-10-12.md
T

56 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-10-12
## 可拖拽判断(PickupItem 标记)
**需求**:`scripts/item.gd` 提供 `can_pickup`,只有为 true 时才能拖拽。
**item.gd 本次改动**:加了 `class_name PickupItem` 和说明注释,功能不变。
```gdscript
class_name PickupItem
extends Node
@export var can_pickup: bool = true
```
### ⚠ 关键发现:脚本挂载位置 ≠ 射线打中的节点
用户在 `world/main.tscn` 第 155 行把 item.gd 挂在了 `SM_Bottle_12` 上,但那个节点**不是刚体**。
实例来源 `res://assets/Furniture_FREE-af040129/SM_Bottle_1.glb`,实际结构是:
```
SM_Bottle_12 (Node3D) ← item.gd 挂在这一层(glb 实例的根)
└── SM_Bottle_1 (RigidBody3D) ← 射线实际打中的是这一层
├── SM_Bottle_1 (MeshInstance3D)
└── CollisionShape3D
```
**实测确认**:glb 内部节点的 `owner` 指向实例根(`SM_Bottle_1.owner == SM_Bottle_12`),
再往上为 null。所以「沿 owner 链向上找标记」正好一步命中。
### 实现(`player_pickup.gd`)
- 新增 `@export var allow_unmarked: bool = false`
- **false(默认)= 白名单**:只有挂了 `PickupItem` 且 `can_pickup=true` 的才拖得动
- true = 黑名单:没挂标记的默认可拖,只有显式设 false 的不能拖
- 新增 `can_grab(collider) -> bool`:先判 `is RigidBody3D`,再查标记
- 新增 `_find_item_marker(body)`:顺序 **刚体自身 → 直接子节点 → owner 链向上**
- 向上时**只查节点自身、不查子节点** —— 否则走到 World 层会遍历几百个子节点,而这是每物理帧都要跑的
- `_update_interact_state()` 的 hovering 判定改用 `can_grab()`
- `_grab()` 里再判一次(悬停状态来自上一物理帧,其间 can_pickup 可能已被改掉)
### 实测验证(headless,全部符合预期)
```
can_grab(SM_Bottle_1 RigidBody3D) = true ✓
can_grab(SM_Bottle_12 Node3D) = false ✓(不是刚体)
can_grab(Can2 内部刚体) = false ✓(严格/白名单模式)
allow_unmarked=true 后 Can2 = true ✓
```
### ⚠ 副作用(需告知用户)
默认白名单模式下,场景里**所有没挂 item.gd 的刚体都拖不动了**
(`Can2`、饭盒、水果等)。要么逐个挂标记,要么把 `allow_unmarked` 勾上。
### MCP 备注
4 次 `script_patch` 均返回 `replacements: 1` 但伴随 `gdscript_reload_failed (code 43)`
假报错(`fallback_line: true`)—— 与 10-10 记录的是同一现象。
离线 `--check-only` 两个脚本均通过;`PickupItem` 已进 `global_script_class_cache.cfg`。