using System; using UnityEngine; namespace AibisDream.FixSystem { [RequireComponent(typeof(LineRenderer))] public class Cable : MonoBehaviour { private Transform _start; private Transform _end; private LineRenderer _lineRenderer; private LineRenderer _stiffLineRenderer; // 用于渲染刚性部分 private Vector3[] _points; private CablePanel _cablePanel; [SerializeField] private CableConfig config = CableConfig.GeneDefaultConfig(); public void ShowCable() { _lineRenderer.enabled = true; _stiffLineRenderer.enabled = true; } public void HideCable() { _lineRenderer.enabled = false; _stiffLineRenderer.enabled = false; } private void Awake() { _lineRenderer = GetComponent(); _lineRenderer.positionCount = config.resolution - config.stiffCount; // 创建第二个LineRenderer用于刚性部分 GameObject stiffObj = new GameObject("StiffLineRenderer"); stiffObj.transform.SetParent(transform); _stiffLineRenderer = stiffObj.AddComponent(); _stiffLineRenderer.positionCount = config.stiffCount; } private void Start() { InitComponentRefs(); InitPoints(); } private void InitComponentRefs() { _cablePanel = transform.GetComponentInParent(); // 复制第一个LineRenderer的属性到第二个 _stiffLineRenderer.startWidth = _lineRenderer.startWidth; _stiffLineRenderer.endWidth = _lineRenderer.startWidth; _stiffLineRenderer.material = _lineRenderer.material; _stiffLineRenderer.startColor = _lineRenderer.startColor; _stiffLineRenderer.endColor = _lineRenderer.startColor; _stiffLineRenderer.sortingLayerName = _cablePanel.CableReelRef.GetComponent().sortingLayerName; _stiffLineRenderer.sortingOrder = _cablePanel.CableReelRef.GetComponent().sortingOrder - 1; // 连线起止点 _start = _cablePanel.CableRootPos; _end = _cablePanel.PlugRef.transform; } private void InitPoints() { _points = new Vector3[config.resolution]; for (int i = 0; i < config.resolution; i++) { float t = i / (float)(config.resolution - 1); _points[i] = Vector3.Lerp(_start.position, _end.position, t); } } private void FixedUpdate() { DrawLine(); } void DrawLine() { var points = UpdateRope(); // 渲染刚性部分 for (int i = 0; i < config.stiffCount; i++) { _stiffLineRenderer.SetPosition(i, points[i] + Vector3.forward * -.3f); } // 渲染非刚性部分 for (int i = 0; i < config.resolution - config.stiffCount; i++) { _lineRenderer.SetPosition(i, points[i + config.stiffCount] + Vector3.forward * -.3f); } } Vector3[] UpdateRope() { float t = Mathf.InverseLerp(config.dstMin, config.dstMax, (_start.position - _end.position).magnitude); float F = Mathf.Lerp(config.forceMin, config.forceMax, t); // 计算出线方向(从转盘出线口到起始点) Vector3 dir = (_start.position - _cablePanel.CableReelRef.transform.position).normalized; // 设置刚性部分 for (int i = 0; i < config.stiffCount; i++) { float t_stiff = (float)i / (config.stiffCount - 1); _points[i] = _start.position + dir * (config.stiffLength * t_stiff); } // 设置末端点 _points[^1] = _end.position; // 只对非刚性部分进行物理模拟 for (int ik = 0; ik < config.k; ik++) { // 确保非刚性部分的第一个点与刚性部分的最后一个点重合 _points[config.stiffCount] = _points[config.stiffCount - 1]; for (int i = config.stiffCount + 1; i < _points.Length - 1; i++) { Vector3 offsetPrev = _points[i - 1] - _points[i]; Vector3 offsetNext = _points[i + 1] - _points[i]; Vector3 velocity = offsetPrev.normalized * (offsetPrev.magnitude * F) + offsetNext.normalized * (offsetNext.magnitude * F); _points[i] += velocity * Time.deltaTime / config.k; } for (int i = config.stiffCount + 1; i < _points.Length - 1; i++) { _points[i] += Vector3.down * (9.8f * Time.deltaTime) / config.k; } } return _points; } /// /// 为线缆设置末端点 /// /// 末端点 public void SetEndPos(Transform endPos) { _end = endPos; } public Vector3 GetDirection() { return _points[^1] - _points[^2]; } } [Serializable] public struct CableConfig { public int resolution; public float dstMin; public float dstMax; public float forceMin; public float forceMax; public int k; public int stiffCount; // 刚性部分点数 public float stiffLength; // 刚性部分长度 public static CableConfig GeneDefaultConfig() { return new CableConfig { resolution = 10, dstMin = 0.1f, dstMax = 1.0f, forceMin = 0.1f, forceMax = 150f, k = 10, stiffCount = 3, stiffLength = 0.1f }; } } }