feat(cable): 线缆优化
This commit is contained in:
@@ -68,7 +68,9 @@ namespace AibisDream.FixSystem
|
||||
/// </summary>
|
||||
private void ResolveConfig()
|
||||
{
|
||||
_headStiffLength = config.headStiffLength <= 0f ? 0.055f : config.headStiffLength;
|
||||
_headStiffLength = config.headStiffLength <= 0f
|
||||
? (config.stiffLength > 0f ? config.stiffLength : 0.055f)
|
||||
: config.headStiffLength;
|
||||
_headRenderBlend = config.headRenderBlend <= 0f ? 0.55f : Mathf.Clamp01(config.headRenderBlend);
|
||||
|
||||
_tailStiffCount = config.tailStiffCount < 2 ? 2 : config.tailStiffCount;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
[RequireComponent(typeof(PhysicLineSegment))]
|
||||
public class PhysicCable : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("StartTranform")] public Transform startTransform;
|
||||
@@ -13,12 +14,15 @@ public class PhysicCable : MonoBehaviour
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
physicLine = transform.GetComponent<PhysicLineSegment>();
|
||||
EnsurePhysicLine();
|
||||
}
|
||||
|
||||
public void Init(Vector3 endPos)
|
||||
{
|
||||
physicLine.Initialize(startTransform.position, endPos);
|
||||
EnsurePhysicLine();
|
||||
if (physicLine == null || startTransform == null) return;
|
||||
|
||||
physicLine.Initialize(startTransform.position, endPos, GetOutletDirection(endPos));
|
||||
}
|
||||
|
||||
public void HideCable()
|
||||
@@ -46,9 +50,14 @@ public class PhysicCable : MonoBehaviour
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
EnsurePhysicLine();
|
||||
if (physicLine == null) return;
|
||||
|
||||
// 更新起点位置
|
||||
if (startTransform != null)
|
||||
{
|
||||
Vector3 fallbackTarget = targetTransform != null ? targetTransform.position : startTransform.position + startTransform.right;
|
||||
physicLine.UpdateOutletDirection(GetOutletDirection(fallbackTarget));
|
||||
physicLine.UpdateStart(startTransform.position);
|
||||
}
|
||||
|
||||
@@ -59,4 +68,37 @@ public class PhysicCable : MonoBehaviour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GetOutletDirection(Vector3 fallbackTarget)
|
||||
{
|
||||
if (startTransform == null)
|
||||
{
|
||||
return Vector3.right;
|
||||
}
|
||||
|
||||
if (startTransform.parent != null)
|
||||
{
|
||||
Vector3 radialDirection = startTransform.position - startTransform.parent.position;
|
||||
if (radialDirection.sqrMagnitude > 1e-6f)
|
||||
{
|
||||
return radialDirection.normalized;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 fallbackDirection = fallbackTarget - startTransform.position;
|
||||
if (fallbackDirection.sqrMagnitude > 1e-6f)
|
||||
{
|
||||
return fallbackDirection.normalized;
|
||||
}
|
||||
|
||||
return startTransform.right;
|
||||
}
|
||||
|
||||
private void EnsurePhysicLine()
|
||||
{
|
||||
if (physicLine == null)
|
||||
{
|
||||
physicLine = transform.GetComponent<PhysicLineSegment>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
{
|
||||
public float segmentSpacing = 0.1f;
|
||||
public int k = 30;
|
||||
[Header("出线口保护段")]
|
||||
[SerializeField] private float outletGuardLength = 0.15f;
|
||||
[SerializeField] private int outletGuardParticleCount = 4;
|
||||
|
||||
public List<VerletParticle> particles = new();
|
||||
private List<VerletStick> sticks = new();
|
||||
@@ -15,8 +18,16 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
public float gravity = -9.8f;
|
||||
|
||||
private float originalLength;
|
||||
private Vector3 outletStart;
|
||||
private Vector3 outletDirection = Vector3.right;
|
||||
private int protectedParticleCount = 1;
|
||||
|
||||
public void Initialize(Vector3 start, Vector3 end)
|
||||
{
|
||||
Initialize(start, end, end - start);
|
||||
}
|
||||
|
||||
public void Initialize(Vector3 start, Vector3 end, Vector3 startDirection)
|
||||
{
|
||||
particles.Clear();
|
||||
sticks.Clear();
|
||||
@@ -26,25 +37,37 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
}
|
||||
|
||||
originalLength = Vector3.Distance(start, end);
|
||||
outletStart = start;
|
||||
outletDirection = ResolveDirection(startDirection, end - start);
|
||||
|
||||
segmentCount = Mathf.RoundToInt(originalLength / segmentSpacing);
|
||||
float spacing = Mathf.Max(0.001f, segmentSpacing);
|
||||
segmentCount = Mathf.Max(3, Mathf.CeilToInt(originalLength / spacing) + 1);
|
||||
protectedParticleCount = ResolveProtectedParticleCount(segmentCount);
|
||||
lineRenderer = GetComponent<LineRenderer>();
|
||||
float guardLength = ResolveGuardLength();
|
||||
Vector3 guardEnd = start + outletDirection * guardLength;
|
||||
|
||||
// Initialize particles
|
||||
for (int i = 0; i < segmentCount; i++)
|
||||
{
|
||||
var particle = new VerletParticle(Vector3.Lerp(start, end, i / (float)segmentCount));
|
||||
Vector3 position = GetInitialParticlePosition(start, guardEnd, end, i);
|
||||
var particle = new VerletParticle(position)
|
||||
{
|
||||
isLocked = i < protectedParticleCount
|
||||
};
|
||||
particles.Add(particle);
|
||||
}
|
||||
|
||||
// Initialize sticks
|
||||
for (int i = 0; i < segmentCount - 1; i++)
|
||||
{
|
||||
sticks.Add(new VerletStick(particles[i], particles[i + 1], segmentSpacing));
|
||||
sticks.Add(new VerletStick(
|
||||
particles[i],
|
||||
particles[i + 1],
|
||||
Vector3.Distance(particles[i].position, particles[i + 1].position)));
|
||||
}
|
||||
|
||||
// Lock the first particle
|
||||
particles[0].isLocked = true;
|
||||
ApplyOutletGuard();
|
||||
|
||||
lineRenderer.positionCount = segmentCount;
|
||||
}
|
||||
@@ -63,8 +86,10 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
|
||||
void UpdateLine()
|
||||
{
|
||||
ApplyOutletGuard();
|
||||
|
||||
// Apply gravity to particles
|
||||
for (int i = 1; i < particles.Count; i++)
|
||||
for (int i = 0; i < particles.Count; i++)
|
||||
{
|
||||
particles[i].ApplyForce(Vector3.up * gravity * Time.deltaTime);
|
||||
particles[i].UpdatePosition();
|
||||
@@ -78,6 +103,8 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
stick.UpdateStick();
|
||||
}
|
||||
}
|
||||
|
||||
ApplyOutletGuard();
|
||||
}
|
||||
|
||||
public void UpdatePlug(Transform plug)
|
||||
@@ -95,9 +122,69 @@ public class PhysicLineSegment : MonoBehaviour
|
||||
|
||||
public void UpdateStart(Vector3 newStartPosition)
|
||||
{
|
||||
if (particles.Count > 0)
|
||||
outletStart = newStartPosition;
|
||||
ApplyOutletGuard();
|
||||
}
|
||||
|
||||
public void UpdateOutletDirection(Vector3 newOutletDirection)
|
||||
{
|
||||
outletDirection = ResolveDirection(newOutletDirection, outletDirection);
|
||||
ApplyOutletGuard();
|
||||
}
|
||||
|
||||
private Vector3 GetInitialParticlePosition(Vector3 start, Vector3 guardEnd, Vector3 end, int index)
|
||||
{
|
||||
if (index < protectedParticleCount)
|
||||
{
|
||||
particles[0].position = newStartPosition;
|
||||
float t = protectedParticleCount <= 1 ? 0f : index / (float)(protectedParticleCount - 1);
|
||||
return Vector3.Lerp(start, guardEnd, t);
|
||||
}
|
||||
|
||||
int flexibleCount = segmentCount - protectedParticleCount;
|
||||
float flexT = (index - protectedParticleCount + 1) / (float)flexibleCount;
|
||||
return Vector3.Lerp(guardEnd, end, flexT);
|
||||
}
|
||||
|
||||
private void ApplyOutletGuard()
|
||||
{
|
||||
if (particles.Count == 0) return;
|
||||
|
||||
int count = Mathf.Min(protectedParticleCount, particles.Count);
|
||||
float guardLength = ResolveGuardLength();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float t = count <= 1 ? 0f : i / (float)(count - 1);
|
||||
Vector3 lockedPosition = outletStart + outletDirection * (guardLength * t);
|
||||
particles[i].position = lockedPosition;
|
||||
particles[i].previousPosition = lockedPosition;
|
||||
particles[i].isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private int ResolveProtectedParticleCount(int count)
|
||||
{
|
||||
int requestedCount = Mathf.Max(1, outletGuardParticleCount);
|
||||
return Mathf.Clamp(requestedCount, 1, Mathf.Max(1, count - 1));
|
||||
}
|
||||
|
||||
private float ResolveGuardLength()
|
||||
{
|
||||
float configuredLength = Mathf.Max(0f, outletGuardLength);
|
||||
return Mathf.Min(configuredLength, originalLength * 0.45f);
|
||||
}
|
||||
|
||||
private static Vector3 ResolveDirection(Vector3 direction, Vector3 fallback)
|
||||
{
|
||||
if (direction.sqrMagnitude > 1e-6f)
|
||||
{
|
||||
return direction.normalized;
|
||||
}
|
||||
|
||||
if (fallback.sqrMagnitude > 1e-6f)
|
||||
{
|
||||
return fallback.normalized;
|
||||
}
|
||||
|
||||
return Vector3.right;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user