绳子优化
This commit is contained in:
@@ -404,7 +404,7 @@ BoxCollider:
|
|||||||
m_ProvidesContacts: 0
|
m_ProvidesContacts: 0
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_Size: {x: 10, y: 2, z: 10}
|
m_Size: {x: 10, y: 1, z: 10}
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
--- !u!23 &306060541
|
--- !u!23 &306060541
|
||||||
MeshRenderer:
|
MeshRenderer:
|
||||||
@@ -468,8 +468,8 @@ Transform:
|
|||||||
m_GameObject: {fileID: 306060539}
|
m_GameObject: {fileID: 306060539}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: -100, z: 10}
|
m_LocalPosition: {x: 0, y: -3, z: 10}
|
||||||
m_LocalScale: {x: 10, y: 2, z: 10}
|
m_LocalScale: {x: 14.43, y: 2, z: 16.04}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
@@ -934,9 +934,9 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
mouseOffset: 10
|
mouseOffset: 10
|
||||||
nodeDistance: 0.1
|
nodeDistance: 0.1
|
||||||
nodeColliderRadius: 0.2
|
nodeColliderRadius: 0.3
|
||||||
gravityStrength: 1.962
|
gravityStrength: 1.962
|
||||||
totalLength: 10
|
totalLength: 6
|
||||||
velocityDampen: 0.95
|
velocityDampen: 0.95
|
||||||
stiffness: 0.99
|
stiffness: 0.99
|
||||||
iterateCollisionsEvery: 1
|
iterateCollisionsEvery: 1
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class Rope : MonoBehaviour
|
|||||||
|
|
||||||
[SerializeField] float nodeColliderRadius = 0.2f;
|
[SerializeField] float nodeColliderRadius = 0.2f;
|
||||||
[SerializeField] float gravityStrength = 2;
|
[SerializeField] float gravityStrength = 2;
|
||||||
[SerializeField] float totalLength = 10f; // 新增总长度参数
|
[SerializeField] float totalLength = 10f;
|
||||||
[SerializeField, Range(0, 1)] float velocityDampen = 0.95f;
|
[SerializeField, Range(0, 1)] float velocityDampen = 0.95f;
|
||||||
[SerializeField, Range(0, 0.99f)] float stiffness = 0.8f;
|
[SerializeField, Range(0, 0.99f)] float stiffness = 0.8f;
|
||||||
[SerializeField, Range(1, 10)] int iterateCollisionsEvery = 1;
|
[SerializeField, Range(1, 10)] int iterateCollisionsEvery = 1;
|
||||||
@@ -36,25 +36,11 @@ public class Rope : MonoBehaviour
|
|||||||
LineRenderer lineRenderer;
|
LineRenderer lineRenderer;
|
||||||
GameObject nodeTester;
|
GameObject nodeTester;
|
||||||
SphereCollider nodeCollider;
|
SphereCollider nodeCollider;
|
||||||
int totalNodes; // 现在由代码计算
|
int totalNodes;
|
||||||
|
float lastTotalLength; // 用于检测长度变化
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
// 计算节点数量
|
|
||||||
totalNodes = Mathf.FloorToInt(totalLength / nodeDistance) + 1;
|
|
||||||
float remainingLength = totalLength % nodeDistance;
|
|
||||||
|
|
||||||
// 如果剩余长度大于0,增加一个节点
|
|
||||||
if (remainingLength > 0 && totalLength > nodeDistance)
|
|
||||||
{
|
|
||||||
totalNodes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化数组
|
|
||||||
currentNodePositions = new Vector3[totalNodes];
|
|
||||||
previousNodePositions = new Vector3[totalNodes];
|
|
||||||
colliderHitBuffer = new Collider[colliderBufferSize];
|
|
||||||
|
|
||||||
// 获取组件引用
|
// 获取组件引用
|
||||||
lineRenderer = GetComponent<LineRenderer>();
|
lineRenderer = GetComponent<LineRenderer>();
|
||||||
cam = Camera.main;
|
cam = Camera.main;
|
||||||
@@ -66,25 +52,59 @@ public class Rope : MonoBehaviour
|
|||||||
nodeCollider = nodeTester.AddComponent<SphereCollider>();
|
nodeCollider = nodeTester.AddComponent<SphereCollider>();
|
||||||
nodeCollider.radius = nodeColliderRadius;
|
nodeCollider.radius = nodeColliderRadius;
|
||||||
|
|
||||||
|
// 初始化长度跟踪
|
||||||
|
lastTotalLength = totalLength;
|
||||||
|
InitializeRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeRope()
|
||||||
|
{
|
||||||
|
// 计算节点数量
|
||||||
|
totalNodes = Mathf.FloorToInt(totalLength / nodeDistance) + 1;
|
||||||
|
float remainingLength = totalLength % nodeDistance;
|
||||||
|
|
||||||
|
// 如果剩余长度大于0,增加一个节点
|
||||||
|
if (remainingLength > 0 && totalLength > nodeDistance)
|
||||||
|
{
|
||||||
|
totalNodes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化或调整数组大小
|
||||||
|
System.Array.Resize(ref currentNodePositions, totalNodes);
|
||||||
|
System.Array.Resize(ref previousNodePositions, totalNodes);
|
||||||
|
colliderHitBuffer = new Collider[colliderBufferSize];
|
||||||
|
|
||||||
// 初始化节点位置
|
// 初始化节点位置
|
||||||
Vector3 startPos = transform.position;
|
Vector3 startPos = transform.position;
|
||||||
for (int i = 0; i < totalNodes; i++)
|
for (int i = 0; i < totalNodes; i++)
|
||||||
{
|
{
|
||||||
// 如果是最后一个节点且有剩余长度,使用剩余长度
|
// 如果是最后一个节点且有剩余长度,使用剩余长度
|
||||||
float distance = (i == totalNodes - 1 && remainingLength > 0) ? remainingLength : nodeDistance;
|
float distance = (i == totalNodes - 1 && remainingLength > 0) ? remainingLength : nodeDistance;
|
||||||
|
|
||||||
currentNodePositions[i] = startPos;
|
// 如果数组已有数据,保持现有位置,否则初始化新位置
|
||||||
previousNodePositions[i] = startPos;
|
if (currentNodePositions[i] == null)
|
||||||
|
{
|
||||||
|
currentNodePositions[i] = startPos;
|
||||||
|
previousNodePositions[i] = startPos;
|
||||||
|
}
|
||||||
startPos.y -= distance;
|
startPos.y -= distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置线渲染器
|
// 设置线渲染器
|
||||||
lineRenderer.startWidth = ropeWidth;
|
lineRenderer.startWidth = ropeWidth;
|
||||||
lineRenderer.endWidth = ropeWidth;
|
lineRenderer.endWidth = ropeWidth;
|
||||||
|
lineRenderer.positionCount = totalNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
|
// 检查长度是否变化
|
||||||
|
if (!Mathf.Approximately(totalLength, lastTotalLength))
|
||||||
|
{
|
||||||
|
AdjustRopeLength();
|
||||||
|
lastTotalLength = totalLength;
|
||||||
|
}
|
||||||
|
|
||||||
// 处理鼠标输入
|
// 处理鼠标输入
|
||||||
if (Input.GetMouseButtonDown(0))
|
if (Input.GetMouseButtonDown(0))
|
||||||
{
|
{
|
||||||
@@ -111,6 +131,36 @@ public class Rope : MonoBehaviour
|
|||||||
DrawRope();
|
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()
|
void FixedUpdate()
|
||||||
{
|
{
|
||||||
Simulate();
|
Simulate();
|
||||||
@@ -164,10 +214,9 @@ public class Rope : MonoBehaviour
|
|||||||
Vector3 diff = node1 - node2;
|
Vector3 diff = node1 - node2;
|
||||||
|
|
||||||
// 计算期望的距离 - 如果是最后一个段且有剩余长度,使用剩余长度
|
// 计算期望的距离 - 如果是最后一个段且有剩余长度,使用剩余长度
|
||||||
float desiredDistance = (i == nodeCountMinusOne - 1 && (totalLength % nodeDistance) > 0)
|
float desiredDistance = (i == nodeCountMinusOne - 1 && (totalLength % nodeDistance) > 0) ?
|
||||||
? (totalLength % nodeDistance)
|
(totalLength % nodeDistance) : nodeDistance;
|
||||||
: nodeDistance;
|
|
||||||
|
|
||||||
float sqrDesiredDistance = desiredDistance * desiredDistance;
|
float sqrDesiredDistance = desiredDistance * desiredDistance;
|
||||||
float sqrDistance = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z;
|
float sqrDistance = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z;
|
||||||
|
|
||||||
@@ -176,7 +225,7 @@ public class Rope : MonoBehaviour
|
|||||||
{
|
{
|
||||||
float distance = Mathf.Sqrt(sqrDistance);
|
float distance = Mathf.Sqrt(sqrDistance);
|
||||||
float difference = desiredDistance - distance;
|
float difference = desiredDistance - distance;
|
||||||
Vector3 direction = diff / distance; // 比 normalized 更快
|
Vector3 direction = diff / distance;
|
||||||
|
|
||||||
Vector3 adjustment = direction * (difference * halfStiffness);
|
Vector3 adjustment = direction * (difference * halfStiffness);
|
||||||
|
|
||||||
@@ -188,13 +237,13 @@ public class Rope : MonoBehaviour
|
|||||||
|
|
||||||
void AdjustCollisions()
|
void AdjustCollisions()
|
||||||
{
|
{
|
||||||
for (int i = 1; i < totalNodes; i += 2) // 跳过更多节点减少计算
|
for (int i = 1; i < totalNodes; i += 2)
|
||||||
{
|
{
|
||||||
int hits = Physics.OverlapSphereNonAlloc(
|
int hits = Physics.OverlapSphereNonAlloc(
|
||||||
currentNodePositions[i],
|
currentNodePositions[i],
|
||||||
nodeColliderRadius,
|
nodeColliderRadius,
|
||||||
colliderHitBuffer,
|
colliderHitBuffer,
|
||||||
~(1 << 8)); // 忽略特定层
|
~(1 << 8));
|
||||||
|
|
||||||
for (int n = 0; n < hits; n++)
|
for (int n = 0; n < hits; n++)
|
||||||
{
|
{
|
||||||
@@ -216,7 +265,6 @@ public class Rope : MonoBehaviour
|
|||||||
|
|
||||||
void DrawRope()
|
void DrawRope()
|
||||||
{
|
{
|
||||||
// 直接使用currentNodePositions数组避免额外拷贝
|
|
||||||
lineRenderer.positionCount = totalNodes;
|
lineRenderer.positionCount = totalNodes;
|
||||||
lineRenderer.SetPositions(currentNodePositions);
|
lineRenderer.SetPositions(currentNodePositions);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user