docs(fixsystem): 补充 PhysicCable 实现说明与渲染方案对比
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,433 @@
|
||||
# PhysicCable 实现说明
|
||||
|
||||
> 代码路径:`Assets/Scripts/FixSystemNew/Cable/`
|
||||
> 原型来源:`Assets/Prototype/2D线缆物理交互/Cable Physics.dc.html`
|
||||
> 相关文档:[线缆物理移植分析与方案](./线缆物理移植分析与方案.md)(侧重渲染移植与问题根因)
|
||||
> 更新:2026-07-09
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
`PhysicCable` 是维修面板插线玩法的**统一物理线缆**组件。它用一条 **Verlet 绳** 覆盖原先两套状态:
|
||||
|
||||
| 旧方案 | 行为 |
|
||||
|--------|------|
|
||||
| `Cable` | 拖拽时的视觉线 |
|
||||
| `PhysicCable`(旧) | 闲置下垂 |
|
||||
|
||||
新方案:**固定粒子数 + 可变总长度**,同一套模拟处理闲置下垂、拖拽送线、插孔钉住、收线隐藏。
|
||||
|
||||
上层协调由 `CablePanel` 完成;插头交互在 `Plug`;渲染由 `CableMeshRenderer` 负责。
|
||||
|
||||
```
|
||||
Plug(输入) → CablePanel(状态协调) → PhysicCable(物理 + 渲染调度)
|
||||
↓
|
||||
CableMeshRenderer(多层 ribbon Mesh)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 文件职责
|
||||
|
||||
| 文件 | 状态 | 职责 |
|
||||
|------|------|------|
|
||||
| `PhysicCable.cs` | **当前主实现** | 状态机、Verlet 模拟、送收线、手感、渲染调度 |
|
||||
| `CableMeshRenderer.cs` | **当前渲染** | 折线 → 多层色带 Mesh |
|
||||
| `Plug.cs` | 活跃 | 拖拽/插拔、DOTween 手感、事件上报 |
|
||||
| `CablePanel.cs` | 活跃 | 插头事件 ↔ 线缆 API、收放线、读档 |
|
||||
| `VerletParticle.cs` | 遗留 | 旧粒子类,**PhysicCable 未使用** |
|
||||
| `VerletStick.cs` | 遗留 | 旧约束类,**PhysicCable 未使用** |
|
||||
| `PhysicLineSegment.cs` | 遗留 | 旧 LineRenderer 方案,**PhysicCable 未使用** |
|
||||
|
||||
---
|
||||
|
||||
## 3. 状态机
|
||||
|
||||
```csharp
|
||||
public enum CableState
|
||||
{
|
||||
Hidden, // 收起:不模拟、不渲染
|
||||
Free, // 闲置:自然下垂,自动回收到最短长度
|
||||
Dragging, // 拖拽:末端钉在指针,按需送线
|
||||
Plugged // 插接:末端钉在插孔
|
||||
}
|
||||
```
|
||||
|
||||
### 3.1 状态切换 API
|
||||
|
||||
| 方法 | 进入状态 | 典型调用方 |
|
||||
|------|----------|------------|
|
||||
| `Hide()` | `Hidden` | `CablePanel.ApplyRetractedState` |
|
||||
| `ShowFree(resetShape?)` | `Free` | 放下线缆、松手未插中 |
|
||||
| `BeginDrag(pointer)` | `Dragging` | 按下插头、收线动画 |
|
||||
| `SetPointer(pointer)` | (保持 Dragging) | 拖拽中每帧 |
|
||||
| `EndDrag()` | `Free` | 松手未插中 |
|
||||
| `PlugInto(dock, snapStraight?)` | `Plugged` | 插入模块 |
|
||||
| `SetDragAssistTarget` / `ClearDragAssistTarget` | — | 靠近插孔时软吸附 |
|
||||
|
||||
### 3.2 状态与物理行为
|
||||
|
||||
| 状态 | 起点 | 末端 | 线长 `_length` |
|
||||
|------|------|------|----------------|
|
||||
| `Hidden` | — | — | 不更新 |
|
||||
| `Free` | 钉在出线口 | 自由 | 回收到 `idleLength` |
|
||||
| `Dragging` | 钉在出线口 | 钉在 `_dragTarget` | 按指针距离送线/回收 |
|
||||
| `Plugged` | 钉在出线口 | 钉在孔心 `_plugSnapEnd` | 保证够到插孔 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 物理核心
|
||||
|
||||
### 4.1 数据结构
|
||||
|
||||
```csharp
|
||||
private struct Particle { public Vector3 pos; public Vector3 prev; }
|
||||
private Particle[] _pts; // 固定数量,默认 40
|
||||
private float _length; // 可变总长度
|
||||
```
|
||||
|
||||
**关键设计**:粒子数 `_n` 固定,相邻粒子目标间距 `seg = _length / (_n - 1)` 随 `_length` 变化。因此绳可以「拉长送线」或「缩短回收」,而不改变粒子数量。
|
||||
|
||||
闲置长度:
|
||||
|
||||
```
|
||||
idleLength = minLength * idleLengthScale
|
||||
```
|
||||
|
||||
### 4.2 每帧模拟流程(`FixedUpdate` → `Simulate`)
|
||||
|
||||
```
|
||||
1. 送线 / 回收 → 调整 _length
|
||||
2. Verlet 积分 → 重力 + 阻尼
|
||||
3. 钉住端点 → 起点 / 拖拽目标 / 插孔
|
||||
4. 约束迭代 × N → 距离约束 + 出线口保护 + 插接直插 + 弯曲刚度
|
||||
5. 地面碰撞(可选) → floorLimit
|
||||
6. 插头朝向 → UpdatePlugAngle
|
||||
```
|
||||
|
||||
#### 送线 / 回收
|
||||
|
||||
```csharp
|
||||
float needed = Distance(endTarget, anchor) * 1.04f + lengthMargin;
|
||||
float targetLength = pinnedEnd ? Clamp(needed, idleLength, lMax) : idleLength;
|
||||
float rate = targetLength > _length ? feedRate : (pinnedEnd ? holdRate : retractRate);
|
||||
_length += (targetLength - _length) * rate;
|
||||
```
|
||||
|
||||
| 场景 | 速率参数 |
|
||||
|------|----------|
|
||||
| 需要更长 | `feedRate`(0.45) |
|
||||
| 末端固定但过长 | `holdRate`(0.06) |
|
||||
| 闲置松手 | `retractRate`(0.09) |
|
||||
|
||||
#### Verlet 积分
|
||||
|
||||
```csharp
|
||||
Vector3 v = (p.pos - p.prev) * damping;
|
||||
p.prev = p.pos;
|
||||
p.pos += v + Vector3.down * (gravity * dt² * endGravityBoost);
|
||||
```
|
||||
|
||||
- `pts[0]` 每帧钉在 `startTransform`(出线口)
|
||||
- 最后 3 个粒子 `endGravityBoost` 加重,插头端更坠
|
||||
|
||||
#### 距离约束
|
||||
|
||||
对每对相邻粒子,迭代 `constraintIterations`(默认 24)次,把间距拉回 `seg`:
|
||||
|
||||
- 起点粒子权重 0(完全固定)
|
||||
- 拖拽/插接时,倒数第二段在末端侧权重偏向固定,减少抖动
|
||||
|
||||
#### 附加约束
|
||||
|
||||
| 约束 | 方法 | 作用 |
|
||||
|------|------|------|
|
||||
| 出线口保护段 | `ApplyOutletStub` | P1/P2 沿出线方向伸出、横向收紧,避免出线折角 |
|
||||
| 插接直插 | `Simulate` 内 plugged 分支 | 倒数第二点拉向「孔心沿来线后退一节」 |
|
||||
| 弯曲刚度 | `bendSmooth` | 每 3 次迭代对中间点做中点平滑 |
|
||||
| 地面 | `floorLimit` | Y 钳制 + 水平摩擦;拖拽末端豁免 |
|
||||
|
||||
### 4.3 出线方向
|
||||
|
||||
`GetOutletDirection`:从 `reelCenter`(或 `startTransform.parent`)指向出线口的径向;fallback 为 `Vector3.down`。
|
||||
|
||||
---
|
||||
|
||||
## 5. 手感系统
|
||||
|
||||
物理之上叠加的交互手感,均在 `PhysicCable` 内实现。
|
||||
|
||||
### 5.1 拖拽防抖
|
||||
|
||||
指针经 `GetAssistedPointer`(吸附)后,再对 `_dragTarget` 做 `lerp * 0.3`,并按当前绳长钳制最大半径,避免拽满时末端抖动。
|
||||
|
||||
### 5.2 插孔吸附
|
||||
|
||||
`SetDragAssistTarget(dock, radius)`:指针靠近插孔时,混合向孔心偏移(`socketAssistStrength` + 平滑 blend)。
|
||||
|
||||
### 5.3 拔线阻力
|
||||
|
||||
`StartUnplugResistance`:从已插状态按下插头时,指针被「粘」在孔心;拉出距离超过 `unplugBreakDistance` 后释放,并 `KickTail` 给尾段冲量。
|
||||
|
||||
### 5.4 插入冲击
|
||||
|
||||
`BeginInsertImpact`:插入瞬间末段前推(`insertShoveDistance`)+ 横向抖动(`insertShakeAmplitude`)+ 尾段 kick(`insertTailKick`)。
|
||||
|
||||
### 5.5 插头朝向
|
||||
|
||||
`UpdatePlugAngle`:
|
||||
|
||||
- 绳拉紧(`taut > 0.92`):沿「出线口 → 末端」直线取向
|
||||
- 松弛:沿末端往回走 `plugRefArcLength` 弧长取参考点方向
|
||||
- 每帧限速转角(`plugTurnRate`、`plugMaxTurnStep`)
|
||||
|
||||
`ApplyPlugPose(plug, plugRoot)`:把插头摆到绳末端并按 `_plugAngle` 旋转。由 `CablePanel.LateUpdate` 在渲染后调用,与 `PhysicCable.LateUpdate` 读同一份点位,避免线头分离。
|
||||
|
||||
---
|
||||
|
||||
## 6. 渲染:`CableMeshRenderer`
|
||||
|
||||
### 6.1 为何不用 LineRenderer
|
||||
|
||||
旧 `LineRenderer` 已禁用(`Awake` 里 `enabled = false`)。多层描边、固定画序、顶光偏移、自遮挡等需求无法用多条 LineRenderer + sorting order 稳定复现(详见[移植分析文档](./线缆物理移植分析与方案.md))。
|
||||
|
||||
### 6.2 渲染流程(`LateUpdate` → `Render`)
|
||||
|
||||
```
|
||||
物理点 _pts[N]
|
||||
→ 拷贝到 _renderA
|
||||
→ Chaikin 切角细分 × 2(N → 4N 点,更圆滑)
|
||||
→ FindTailStart(自遮挡检测)
|
||||
→ CableMeshRenderer.UpdateMesh(多层 ribbon + 可选圆头端帽)
|
||||
```
|
||||
|
||||
Chaikin 一次细分:保留首尾,每段取 1/4、3/4 两个切分点,点数翻倍。
|
||||
|
||||
### 6.3 多层色带(像素风)
|
||||
|
||||
`BuildBands` 提交 4 层,**提交顺序 = 画序**(后画的盖前画的):
|
||||
|
||||
| 带 | 角色 | 特殊 |
|
||||
|----|------|------|
|
||||
| Shadow | 落影 | 向下偏移 `shadowDrop`;尾段重绘时跳过 |
|
||||
| Dark | 描边 | — |
|
||||
| Body | 主体 | — |
|
||||
| Mid | 中间调/顶光 | 向上偏移 `midLift` |
|
||||
|
||||
每层把折线沿法线方向扩成 ribbon(宽度 `band.width`),顶点色上色,**无光照计算**。
|
||||
|
||||
### 6.4 自遮挡(tail-over-head)
|
||||
|
||||
`FindTailStart`:找下垂最低点 `j`;若 `j` 之后尾段与 `j` 之前头段空间重叠,返回尾段起始下标;`UpdateMesh` 把尾段非阴影带**再画一遍**盖在最上。
|
||||
|
||||
### 6.5 插接圆头
|
||||
|
||||
`Plugged` 时 `roundEndCap = true`:末端用半圆端帽(`CapSegments` 细分),视觉上像插进孔里。
|
||||
|
||||
### 6.6 排序
|
||||
|
||||
- 线缆 Mesh:`Tools` 层 / `sortingOrder = 47`
|
||||
- 插头 Sprite:`Tools` 层 / `sortingOrder = 48`(永远画在线上方)
|
||||
- 收起时插头压到线盘下方(`sortingOrder = 41`)
|
||||
|
||||
---
|
||||
|
||||
## 7. 上层协作(`CablePanel`)
|
||||
|
||||
### 7.1 生命周期
|
||||
|
||||
- `Start`:停用旧 `Cable`;按 `isCableRetracted` 初始化 `Hide` 或 `ShowFree`
|
||||
- `LateUpdate`:`Free` / `Dragging` 时 `ApplyPlugPose` + `ApplyFeedbackOffset`
|
||||
|
||||
### 7.2 典型事件流
|
||||
|
||||
```
|
||||
按下插头
|
||||
→ PullUpSocket(若已插)
|
||||
→ BeginDrag(plug.position)
|
||||
→ StartUnplugResistance(若刚拔出)
|
||||
|
||||
拖拽中
|
||||
→ SetPointer(mouseWorld)
|
||||
→ SetDragAssistTarget(靠近模块时)
|
||||
|
||||
松手
|
||||
├─ 插中模块 → Plug DOTween → OnInsertSocket → PlugInto
|
||||
└─ 未插中 → ReleasePlug → EndDrag
|
||||
|
||||
收线
|
||||
→ BeginDrag + DOTween 插头到 retractedPos
|
||||
→ Hide + 插头排序降级
|
||||
```
|
||||
|
||||
### 7.3 读档
|
||||
|
||||
`ApplyCableSnapshot(retracted, pluggedModuleName)`:无动画恢复;插接时用 `PlugInto(socket, snapStraight: true)` 拉直摆型。
|
||||
|
||||
---
|
||||
|
||||
## 8. 关键参数速查
|
||||
|
||||
| 参数 | 默认量级 | 含义 |
|
||||
|------|----------|------|
|
||||
| `pointCount` | 40 | 粒子数 |
|
||||
| `minLength` | 2 | 长度基准 |
|
||||
| `idleLengthScale` | 0.08 | 闲置长度 = minLength × 此值 |
|
||||
| `maxStretch` | 8 | 最大拉出 = minLength × 此值 |
|
||||
| `gravity` | 100 | 重力(世界单位/s²) |
|
||||
| `damping` | 0.965 | 速度衰减 |
|
||||
| `constraintIterations` | 24 | 约束迭代次数 |
|
||||
| `bendSmooth` | 0.3 | 弯曲刚度 |
|
||||
| `feedRate` / `holdRate` / `retractRate` | 0.45 / 0.06 / 0.09 | 送线 / 固定回收 / 闲置回收 |
|
||||
| `plugSnapRate` | 0.55 | 插接末端收敛到孔心 |
|
||||
| `socketAssistStrength` | 0.62 | 拖拽吸附强度 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 自定义 Mesh 与「3D 做法」的关系
|
||||
|
||||
**结论:借用了 3D Mesh 的「几何数据结构」,但渲染语义是 2D,不是完整的 3D 线缆方案。**
|
||||
|
||||
| 维度 | 本项目的 `CableMeshRenderer` | 典型 3D 线缆 |
|
||||
|------|------------------------------|--------------|
|
||||
| 几何 | `Mesh`:顶点 + 三角形,沿折线法线挤出 ribbon | 同样常用 Mesh(或 LineRenderer 3D) |
|
||||
| 坐标 | 顶点直接用**世界 XY**,Z 压平为 0 | 真 3D 空间,有厚度与深度 |
|
||||
| 着色 | 顶点色 + Sprite/Unlit 材质,**不算光照** | 常配合法线、PBR、环境光 |
|
||||
| 遮挡 | `sortingLayer` + `sortingOrder` + 三角形提交顺序 | 深度缓冲(Z-test) |
|
||||
| 阴影 | 关闭 `shadowCasting` / `receiveShadows` | 可投射/接收阴影 |
|
||||
| 物理 | 2D Verlet 点链,与 Mesh **无刚体绑定** | 可选 MeshCollider / 骨骼等 |
|
||||
|
||||
更准确的说法:
|
||||
|
||||
1. **几何生成**类似 3D 管线里「沿路径挤出带状 mesh」的做法(道路、管道、绳索 ribbon 的常见套路)。
|
||||
2. **渲染管线**走的是 Unity 2D 排序(`MeshRenderer.sortingLayer`),配合无光照顶点色,等价于「用 Mesh 当画布一笔笔画上去」,复刻 HTML 原型的 painter's algorithm。
|
||||
3. **不是**把线缆做成场景里的 3D 物体——没有 Z 深度排序、没有光照响应、没有与 3D 碰撞体联动。
|
||||
|
||||
这也是 2D 游戏里画复杂形状时的常见折中:**Mesh 负责形状,2D 排序负责前后关系**。
|
||||
|
||||
---
|
||||
|
||||
## 10. 渲染方案选型:Mesh vs LineRenderer vs Shapes
|
||||
|
||||
本节说明为何维修线缆选用自定义 Mesh,以及与项目内另外两种常见「画线」方案的区别。
|
||||
|
||||
### 10.1 一句话定位
|
||||
|
||||
| 方案 | 本质 | 本项目中的用途 |
|
||||
|------|------|----------------|
|
||||
| **LineRenderer** | Unity 内置「一条线 = 一个 Renderer」 | 旧 `Cable.cs`(已停用)、`PhysicLineSegment`(遗留) |
|
||||
| **Shapes** | 第三方矢量绘图库(组件 + Immediate Mode) | 火山语言粒子连线、波形、ECG 等 |
|
||||
| **自定义 Mesh** | 手写顶点/三角形,单 `MeshRenderer` | 当前 `PhysicCable` / `CableMeshRenderer` |
|
||||
|
||||
### 10.2 LineRenderer
|
||||
|
||||
**工作方式**:给一串世界坐标,Unity 沿路径挤出圆角/圆帽管状线。一条 LineRenderer 对应一种宽度曲线 + 一种材质 + 一种颜色渐变;前后关系靠 `sortingLayer` / `sortingOrder`。
|
||||
|
||||
旧 `Cable.cs` 甚至用了**两条** LineRenderer(柔性段 + 刚性段),说明单条线难以表达复杂形态。
|
||||
|
||||
曾尝试用 **4 条子 LineRenderer** 模拟像素风分带(阴影/描边/主体/高光),遇到的问题(详见[移植分析文档](./线缆物理移植分析与方案.md)):
|
||||
|
||||
| 问题 | 原因 |
|
||||
|------|------|
|
||||
| 层之间对不齐 | 各线独立圆角/端帽设置不一致 |
|
||||
| 无法做「顶光上移」 | 只能同心变窄,无法 shadow 下移、mid 上移 |
|
||||
| 排序脆弱 | 4 个 Renderer 需同步 order;外部在 37~40 层插入物体会「插进线缆内部」 |
|
||||
| 自遮挡难做 | 尾段盖头段需再画一遍 → 8 条线 |
|
||||
| 拖拽时线/插头分层 | 线与插头分属不同 sorting 层,一根线两端遮挡关系无法表达 |
|
||||
| 外观随灯光漂移 | 共用 `Sprite-Lit`,受 `CablePanelLight` 呼吸灯影响 |
|
||||
|
||||
**适合**:简单连线、调试线、少量静态线段。
|
||||
**不适合**:固定画序、多层像素风、自遮挡、与维修面板 Sprite 精密咬合的游戏物件级线缆。
|
||||
|
||||
### 10.3 Shapes(Freya Holmér 矢量库)
|
||||
|
||||
**工作方式**:
|
||||
|
||||
1. **组件模式**:`Polyline`、`Line` 等挂在物体上(内部也生成 Mesh)。
|
||||
2. **Immediate Mode**:`ImmediateModeShapeDrawer` 每帧 `Draw.Line()` / `Draw.Polyline()`。
|
||||
|
||||
项目内参考:`ConnectionRenderer`(火山语言粒子连线)——`Draw.Command(cam)` + 透明混合 + 可配发光。
|
||||
|
||||
**Shapes 擅长**:
|
||||
|
||||
| 能力 | 说明 |
|
||||
|------|------|
|
||||
| 可变粗细 | 每点可不同 `Thickness` |
|
||||
| 渐变/虚线/发光 | dash、gradient、glow(配合 Bloom) |
|
||||
| 连接样式 | Miter / Bevel / Round join |
|
||||
| 即时绘制 | 大量动态线段,按相机 pass 批处理 |
|
||||
|
||||
**与 PhysicCable 需求的差距**:
|
||||
|
||||
Shapes 的模型是**每次 `Draw` = 一种样式的一条线**。像素线缆仍需 `Draw.Polyline × 4`,于是与 LineRenderer 遇到同类问题:
|
||||
|
||||
- 多层 = 多次绘制,画序靠调用顺序,与场景 Sprite 的 `sortingOrder` 混用时不如单 Mesh 稳
|
||||
- 难精确复刻原型的「屏幕空间垂直偏移」(shadow 下移、mid 上移)
|
||||
- 自遮挡尾段重绘需在同一帧再画一遍,且与面板元素排序协调成本高
|
||||
- 无「painter's algorithm 线缆」这一层开箱即用抽象
|
||||
|
||||
**适合**:特效连线、波形、可发光/虚线的动态图元。
|
||||
**不适合**:外观恒定、多层像素风、自遮挡、与 UI/Sprite 精密咬合的维修线缆。
|
||||
|
||||
### 10.4 自定义 Mesh(`CableMeshRenderer`)
|
||||
|
||||
**工作方式**:折线点 → 沿法线挤出 ribbon → 顶点色上色 → **按顺序** append 三角形到同一 Mesh。
|
||||
|
||||
与「画 4 条线」的本质区别:**往同一个 Mesh 里塞 4 层几何**,而非 4 个 Renderer / 4 次 Draw。
|
||||
|
||||
| 能力 | 实现 |
|
||||
|------|------|
|
||||
| 固定画序 | 三角形提交顺序 = 遮挡关系 |
|
||||
| 单层排序控制 | 对外仅 1 个 `MeshRenderer.sortingOrder` |
|
||||
| 分带垂直偏移 | `band.lift`(shadow 下移、mid 上移) |
|
||||
| 自遮挡 | 尾段几何追加在同一 Mesh 末尾(`FindTailStart`) |
|
||||
| 插接圆头 | 自定义半圆端帽三角形 |
|
||||
| 平面固定色 | 顶点色 + Unlit,不受呼吸灯影响 |
|
||||
| 尾段不重画阴影 | `skipInTail` per band |
|
||||
|
||||
代价:每帧手算顶点(当前规模 CPU 压力可忽略),mesh 逻辑约 200 行。
|
||||
|
||||
### 10.5 横向对比
|
||||
|
||||
| 维度 | LineRenderer | Shapes | 自定义 Mesh |
|
||||
|------|-------------|--------|-------------|
|
||||
| 抽象层级 | 引擎内置「画线」 | 高级「画矢量」API | 最底层「拼三角形」 |
|
||||
| 多层描边 | N 个 Renderer | N 次 Draw / N 个组件 | 1 个 Mesh 内多层 |
|
||||
| 画序/遮挡 | 多个 sortingOrder | Draw 顺序 + sorting | **三角形顺序** |
|
||||
| 路径平滑 | 自带 corner/cap | join + 可选 Bezier | 自实现 Chaikin |
|
||||
| 每点不同宽度 | widthCurve(单条) | ✅ 原生 | 自实现 `TipTaper` |
|
||||
| 虚线/发光 | ❌ 需自定义 shader | ✅ 很强 | ❌ 需自研 |
|
||||
| 与 Sprite 2D 排序 | 一般 | 一般 | **最可控** |
|
||||
| 开发成本 | 最低 | 低~中 | 中 |
|
||||
| 外观稳定性 | 差(多 Renderer + 受光) | 好(特效向) | **最好**(固定平面色) |
|
||||
| 本项目线缆 | 已淘汰 | 未采用 | **当前方案** |
|
||||
|
||||
### 10.6 选型决策树
|
||||
|
||||
```
|
||||
要画什么?
|
||||
│
|
||||
├─ 简单 / Debug / 一次性连线
|
||||
│ → LineRenderer
|
||||
│
|
||||
├─ 动态特效线(发光、虚线、渐变、大量粒子连线)
|
||||
│ → Shapes Immediate Mode(如 ConnectionRenderer)
|
||||
│
|
||||
└─ 游戏物件、与 UI/Sprite 精密咬合、多层像素风、自遮挡、外观恒定
|
||||
→ 自定义 Mesh(CableMeshRenderer)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 调试建议
|
||||
|
||||
- 播放 `PeipeiFixScene`,展开维修面板,观察 `Free` → `Dragging` → `Plugged` 过渡
|
||||
- 调 `constraintIterations`、`bendSmooth` 看刚性/柔软度
|
||||
- 调 `feedRate` / `retractRate` 看送收线节奏
|
||||
- 自遮挡:让绳下垂重叠,检查尾段是否正确盖在头段上
|
||||
- 编译后看 Console:`PhysicCable` 不依赖 `PhysicLineSegment`,后者挂在同一物体上可视为遗留
|
||||
|
||||
---
|
||||
|
||||
*与 [线缆物理移植分析与方案.md](./线缆物理移植分析与方案.md) 互补:该文档偏「为何要换 Mesh、与原型差在哪」;本文偏「当前代码怎么跑」。*
|
||||
Reference in New Issue
Block a user