Files
aibis-dream/Assets/Scripts/FixSystemNew/BodyModule/CableReel.cs
T

130 lines
4.9 KiB
C#

using UnityEngine;
namespace AibisDream.FixSystem
{
public class CableReel : MonoBehaviour
{
[Header("转盘设置")]
[SerializeField] private float torqueStrength = 200f; // 扭矩强度
[SerializeField] private float angularDamping = 5f; // 角速度阻尼
[SerializeField] private float maxHalfAngle = 60f; // 单侧最大转角(总范围约 2× 此值 ≈ 120°)
[SerializeField] private float returnSpeed = 4f; // 闲置回正速度
private CablePanel cablePanel;
private float angularVelocity; // 角速度
private float currentAngle; // 当前角度
public Vector3 outletPos { get; private set; } // 出线口位置
private SpriteRenderer spriteRenderer;
private float reelRadius; // 转盘半径
private void Start()
{
// 获取CablePanel引用
cablePanel = transform.GetComponentInParent<CablePanel>();
// 兼容尚未重新保存的旧场景/预制体:新增序列化字段缺失时仍使用设计默认值。
if (maxHalfAngle <= 0f) maxHalfAngle = 60f;
if (returnSpeed <= 0f) returnSpeed = 4f;
currentAngle = transform.eulerAngles.z;
// 获取SpriteRenderer并计算半径
spriteRenderer = GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
// 使用sprite的bounds来计算半径
reelRadius = spriteRenderer.bounds.extents.y; // 使用y方向的半高作为半径
}
else
{
Debug.LogWarning("CableReel没有SpriteRenderer组件!");
reelRadius = 0.5f; // 默认值
}
// 初始化出线口位置
UpdateOutletPosition();
}
private void UpdateOutletPosition()
{
// 更新出线口位置(圆形本地坐标 (0, -radius) 转成世界坐标)
outletPos = transform.TransformPoint(new Vector3(0, -reelRadius, 0));
}
public void ResetRotation()
{
// 重置角度和角速度
currentAngle = 0;
angularVelocity = 0;
transform.rotation = Quaternion.identity;
UpdateOutletPosition();
}
/// <summary>遗留兼容(旧 CableSystem 场景仍在调用)。</summary>
public void UpdateRotation()
{
if (cablePanel == null || cablePanel.PlugRef == null) return;
UpdateRotation(true);
}
/// <summary>
/// 供旧 CableSystem 使用:以插头位置驱动线盘,并在收线时缓动回正。
/// </summary>
public void UpdateRotation(Transform plugTransform, bool active)
{
UpdateRotation(plugTransform, active, 1f);
}
/// <summary>拖拽/插接中朝拉力方向施加扭矩;闲置时缓动回正。</summary>
public void UpdateRotation(bool active, float tautness = 1f)
{
if (cablePanel == null || cablePanel.PlugRef == null) return;
UpdateRotation(cablePanel.PlugRef.transform, active, tautness);
}
private void UpdateRotation(Transform plugTransform, bool active, float tautness)
{
if (plugTransform == null) return;
if (!active)
{
angularVelocity = 0f;
currentAngle = Mathf.LerpAngle(currentAngle, 0f, returnSpeed * Time.deltaTime);
ApplyRotation();
return;
}
// 松弛时不驱动转盘,并缓动回正,避免出线口对着插头“预判”朝向
if (tautness <= 0f)
{
angularVelocity = 0f;
currentAngle = Mathf.LerpAngle(currentAngle, 0f, returnSpeed * Time.deltaTime);
ApplyRotation();
return;
}
Vector2 center = transform.position;
Vector2 outlet = outletPos;
Vector2 force = (Vector2)plugTransform.position - outlet;
Vector2 r = outlet - center;
float torque = (r.x * force.y - r.y * force.x) * tautness;
angularVelocity += torque * torqueStrength * Time.deltaTime;
angularVelocity *= Mathf.Exp(-angularDamping * Time.deltaTime);
currentAngle += angularVelocity * Time.deltaTime;
currentAngle = Mathf.Clamp(currentAngle, -maxHalfAngle, maxHalfAngle);
if (currentAngle <= -maxHalfAngle && angularVelocity < 0f) angularVelocity = 0f;
if (currentAngle >= maxHalfAngle && angularVelocity > 0f) angularVelocity = 0f;
ApplyRotation();
}
private void ApplyRotation()
{
transform.rotation = Quaternion.Euler(0, 0, currentAngle);
UpdateOutletPosition();
}
}
}