111 lines
4.1 KiB
C#
111 lines
4.1 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>();
|
|
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>拖拽/插接中朝拉力方向施加扭矩;闲置时缓动回正。</summary>
|
|
public void UpdateRotation(bool active, float tautness = 1f)
|
|
{
|
|
if (cablePanel == null || cablePanel.PlugRef == null) return;
|
|
|
|
if (!active)
|
|
{
|
|
angularVelocity = 0f;
|
|
currentAngle = Mathf.LerpAngle(currentAngle, 0f, returnSpeed * Time.deltaTime);
|
|
ApplyRotation();
|
|
return;
|
|
}
|
|
|
|
// 线缆还有余量时不驱动转盘,避免"还没拉紧就先转"
|
|
if (tautness <= 0f)
|
|
{
|
|
angularVelocity *= Mathf.Exp(-angularDamping * Time.deltaTime);
|
|
ApplyRotation();
|
|
return;
|
|
}
|
|
|
|
Vector2 center = transform.position;
|
|
Vector2 outlet = outletPos;
|
|
Vector2 force = (Vector2)cablePanel.PlugRef.transform.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();
|
|
}
|
|
}
|
|
} |