// using UnityEngine; // // [RequireComponent(typeof(LineRenderer))] // public class Rope : MonoBehaviour // { // [Header("Attachment Points")] [SerializeField] // public Transform startAttachment; // 绳子起点绑定的Transform // // [SerializeField] public Transform endAttachment; // 绳子终点绑定的Transform // // [Header("Verlet Parameters")] [SerializeField] // float nodeDistance = 0.35f; // // [SerializeField] float nodeColliderRadius = 0.2f; // [SerializeField] float gravityStrength = 2; // [SerializeField] float totalLength = 10f; // [SerializeField, Range(0, 1)] float velocityDampen = 0.95f; // [SerializeField, Range(0, 0.99f)] float stiffness = 0.8f; // [SerializeField] int iterateCollisionsEvery = 1; // [SerializeField] int iterations = 10; // [SerializeField] int colliderBufferSize = 1; // // [Header("Line Renderer")] [SerializeField] // float ropeWidth = 0.1f; // // // 私有变量 // Vector3 gravity; // // // 数组和缓存 // Vector3[] currentNodePositions; // Vector3[] previousNodePositions; // Collider[] colliderHitBuffer; // LineRenderer lineRenderer; // GameObject nodeTester; // SphereCollider nodeCollider; // int totalNodes; // float lastTotalLength; // // void Awake() // { // // 获取组件引用 // lineRenderer = GetComponent(); // gravity = new Vector3(0, -gravityStrength, 0); // // // 初始化节点测试器 // nodeTester = new GameObject("Node Tester"); // nodeTester.layer = 8; // nodeCollider = nodeTester.AddComponent(); // nodeCollider.radius = nodeColliderRadius; // // // 初始化长度跟踪 // lastTotalLength = totalLength; // InitializeRope(); // } // // void InitializeRope() // { // // 计算节点数量 // totalNodes = Mathf.FloorToInt(totalLength / nodeDistance) + 1; // float remainingLength = totalLength % nodeDistance; // // if (remainingLength > 0 && totalLength > nodeDistance) // { // totalNodes++; // } // // // 初始化或调整数组大小 // System.Array.Resize(ref currentNodePositions, totalNodes); // System.Array.Resize(ref previousNodePositions, totalNodes); // colliderHitBuffer = new Collider[colliderBufferSize]; // // // 初始化节点位置 // Vector3 startPos = startAttachment != null ? startAttachment.position : transform.position; // for (int i = 0; i < totalNodes; i++) // { // float distance = (i == totalNodes - 1 && remainingLength > 0) ? remainingLength : nodeDistance; // // currentNodePositions[i] = startPos; // previousNodePositions[i] = startPos; // startPos.y -= distance; // } // // // 设置线渲染器 // lineRenderer.startWidth = ropeWidth; // lineRenderer.endWidth = ropeWidth; // lineRenderer.positionCount = totalNodes; // } // // void Update() // { // // 检查长度是否变化 // if (!Mathf.Approximately(totalLength, lastTotalLength)) // { // AdjustRopeLength(); // lastTotalLength = totalLength; // } // // DrawRope(); // } // // void AdjustRopeLength() // { // Vector3[] oldPositions = (Vector3[])currentNodePositions.Clone(); // Vector3[] oldPrevPositions = (Vector3[])previousNodePositions.Clone(); // // InitializeRope(); // // int copyLength = Mathf.Min(oldPositions.Length, currentNodePositions.Length); // System.Array.Copy(oldPositions, currentNodePositions, copyLength); // System.Array.Copy(oldPrevPositions, previousNodePositions, copyLength); // // if (currentNodePositions.Length > oldPositions.Length) // { // Vector3 lastPos = oldPositions[oldPositions.Length - 1]; // for (int i = oldPositions.Length; i < currentNodePositions.Length; i++) // { // float distance = (i == currentNodePositions.Length - 1 && (totalLength % nodeDistance) > 0) // ? (totalLength % nodeDistance) // : nodeDistance; // // lastPos.y -= distance; // currentNodePositions[i] = lastPos; // previousNodePositions[i] = lastPos; // } // } // } // // void FixedUpdate() // { // Simulate(); // // for (int i = 0; i < iterations; i++) // { // ApplyConstraint(); // // if (i % (iterateCollisionsEvery + 1) == 0) // { // AdjustCollisions(); // } // } // } // // void Simulate() // { // float fixedDt = Time.fixedDeltaTime; // for (int i = 0; i < totalNodes; i++) // { // Vector3 velocity = (currentNodePositions[i] - previousNodePositions[i]) * velocityDampen; // previousNodePositions[i] = currentNodePositions[i]; // currentNodePositions[i] += velocity + gravity * fixedDt; // } // } // // void ApplyConstraint() // { // // 绑定到起点Transform // if (startAttachment != null) // { // currentNodePositions[0] = startAttachment.position; // } // // // 绑定到终点Transform // if (endAttachment != null) // { // currentNodePositions[totalNodes - 1] = endAttachment.position; // } // // float halfStiffness = 0.5f * stiffness; // int nodeCountMinusOne = totalNodes - 1; // // for (int i = 0; i < nodeCountMinusOne; i++) // { // Vector3 node1 = currentNodePositions[i]; // Vector3 node2 = currentNodePositions[i + 1]; // Vector3 diff = node1 - node2; // // float desiredDistance = (i == nodeCountMinusOne - 1 && (totalLength % nodeDistance) > 0) // ? (totalLength % nodeDistance) // : nodeDistance; // // float sqrDesiredDistance = desiredDistance * desiredDistance; // float sqrDistance = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z; // // if (Mathf.Abs(sqrDistance - sqrDesiredDistance) > 0.001f) // { // float distance = Mathf.Sqrt(sqrDistance); // float difference = desiredDistance - distance; // Vector3 direction = diff / distance; // // Vector3 adjustment = direction * (difference * halfStiffness); // // currentNodePositions[i] += adjustment; // currentNodePositions[i + 1] -= adjustment; // } // } // } // // void AdjustCollisions() // { // for (int i = 1; i < totalNodes; i += 2) // { // int hits = Physics.OverlapSphereNonAlloc( // currentNodePositions[i], // nodeColliderRadius, // colliderHitBuffer, // ~(1 << 8)); // // for (int n = 0; n < hits; n++) // { // if (Physics.ComputePenetration( // nodeCollider, // currentNodePositions[i], // Quaternion.identity, // colliderHitBuffer[n], // colliderHitBuffer[n].transform.position, // colliderHitBuffer[n].transform.rotation, // out Vector3 direction, // out float distance)) // { // currentNodePositions[i] += direction * distance; // } // } // } // } // // void DrawRope() // { // lineRenderer.positionCount = totalNodes; // lineRenderer.SetPositions(currentNodePositions); // } // // void OnDestroy() // { // if (nodeTester != null) // { // Destroy(nodeTester); // } // } // // // 公开方法用于动态设置绑定点 // public void SetAttachments(Transform start, Transform end) // { // startAttachment = start; // endAttachment = end; // } // }