拾起物品同步

This commit is contained in:
2026-10-03 18:48:04 +08:00
parent 0dcfb88bfe
commit 3d23804fa5
10 changed files with 359 additions and 86 deletions
+12 -12
View File
@@ -86,22 +86,22 @@ func _process(_delta: float) -> void:
# ---------------- 对外接口(玩家控制器只读这几个) ----------------
## 缆上参数 t∈[0,1] 处的世界坐标。
## 曲线先在**本地空间**算完再转世界:sag 是本地单位,父节点一有缩放整条缆要跟着一起缩,
## 形状才不走样(混用 global 锚点 + 未缩放的 sag,下垂比例会随父节点缩放而变)。
func sample(t: float) -> Vector3:
var a := anchor_a.global_position
var b := anchor_b.global_position
return a.lerp(b, t) - Vector3.UP * (sag * 4.0 * t * (1.0 - t))
return to_global(_curve_local(t))
## 缆上参数 t 处的世界方向(单位向量,指向 B)。
## 用解析导数而不是前后差分:差分在 t=0/1 处要越界取样,端点会偏。
func tangent(t: float) -> Vector3:
var d := (anchor_b.global_position - anchor_a.global_position) - Vector3.UP * (sag * 4.0 * (1.0 - 2.0 * t))
return d.normalized()
var d := (anchor_b.position - anchor_a.position) - Vector3.UP * (sag * 4.0 * (1.0 - 2.0 * t))
return (global_transform.basis * d).normalized()
## 乘坐时人应该待的世界坐标:缆点再往下挂 hang_offset。
func ride_point(t: float) -> Vector3:
return sample(t) - Vector3.UP * hang_offset
return to_global(_curve_local(t) - Vector3.UP * hang_offset)
## 找出世界坐标 pos 在缆上最近的一点,供玩家「就近吸附」。
@@ -134,9 +134,9 @@ func _downhill_dir() -> int:
return 1 if anchor_b.global_position.y <= anchor_a.global_position.y else -1
## 世界曲线转成本地坐标:缆绳网格是本节点的子节点,顶点必须落在局部空间里。
func _local_sample(t: float) -> Vector3:
return to_local(sample(t))
## 下垂曲线在**本节点局部空间**的点。sag 是本地单位,所以父节点缩放时整条缆一起缩、形状不变。
func _curve_local(t: float) -> Vector3:
return anchor_a.position.lerp(anchor_b.position, t) - Vector3.UP * (sag * 4.0 * t * (1.0 - t))
## 把下垂曲线扫成一根管子。用三角形带:每个截面 RING_SEGMENTS+1 个顶点,
@@ -146,17 +146,17 @@ func _rebuild_cable() -> void:
return
var st := SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
var prev := _local_sample(0.0)
var prev := _curve_local(0.0)
length = 0.0
for i in range(segments + 1):
var t := float(i) / float(segments)
var p := _local_sample(t)
var p := _curve_local(t)
if i > 0:
length += p.distance_to(prev)
prev = p
# 截面参考轴取「切线 × 世界上方向」。切线接近竖直时叉乘会退化成零向量,
# 这时换 RIGHT 兜底,否则 normalize() 会吐 NaN 把整根缆搅烂。
var tan_dir := (_local_sample(minf(t + 0.01, 1.0)) - _local_sample(maxf(t - 0.01, 0.0))).normalized()
var tan_dir := (_curve_local(minf(t + 0.01, 1.0)) - _curve_local(maxf(t - 0.01, 0.0))).normalized()
var n := tan_dir.cross(Vector3.UP)
if n.length_squared() < 0.0001:
n = tan_dir.cross(Vector3.RIGHT)