268 lines
9.1 KiB
C#
268 lines
9.1 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace NBF
|
||
{
|
||
/// <summary>
|
||
/// 硬线系统测试脚本,直接读取 FLine 已配置的节点。
|
||
/// </summary>
|
||
public class FLineTest : MonoBehaviour
|
||
{
|
||
[Header("测试控制")] [SerializeField] private KeyCode fixMiddleKey = KeyCode.M;
|
||
|
||
[Header("动态间距控制")] [SerializeField] private KeyCode pullFirstKey = KeyCode.UpArrow;
|
||
[SerializeField] private KeyCode relaxFirstKey = KeyCode.DownArrow;
|
||
[SerializeField] private KeyCode fixedKey = KeyCode.F;
|
||
[SerializeField] private KeyCode debugKey = KeyCode.D;
|
||
[SerializeField, Min(0.01f)] private float extendAmount = 0.5f;
|
||
[SerializeField, Min(0.01f)] private float holdAdjustSpeed = 1f;
|
||
[SerializeField, Min(0.01f)] private float transitionSpeed = 2f;
|
||
[SerializeField] private bool smoothTransition = true;
|
||
|
||
[SerializeField] private FLine line;
|
||
private float[] initialLengths;
|
||
|
||
private void OnValidate()
|
||
{
|
||
extendAmount = Mathf.Max(0.01f, extendAmount);
|
||
holdAdjustSpeed = Mathf.Max(0.01f, holdAdjustSpeed);
|
||
transitionSpeed = Mathf.Max(0.01f, transitionSpeed);
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
RefreshInitialLengths(true);
|
||
line.SetLenght(0.2f);
|
||
line.SetLenght(0.2f, FLineLogicNodeType.End);
|
||
}
|
||
|
||
|
||
private void Update()
|
||
{
|
||
if (!EnsureCable())
|
||
return;
|
||
|
||
RefreshInitialLengths();
|
||
HandleInput();
|
||
|
||
// if (line.CurrentBreakStretchPercent > 10f)
|
||
// {
|
||
// if (line.LineMode == LineMode.Constraint)
|
||
// Debug.LogError(
|
||
// $"当前极限情况,CurrentBreakStretchPercent={line.CurrentBreakStretchPercent} CurrentStretchLength={line.CurrentStretchLength} TotalLength={line.TotalLength} LimitStateTime={line.LimitStateTime}");
|
||
// }
|
||
}
|
||
|
||
private bool EnsureCable()
|
||
{
|
||
if (line)
|
||
return true;
|
||
|
||
line = GetComponent<FLine>();
|
||
return line != null;
|
||
}
|
||
|
||
private List<FLineLogicNode> GetNodes()
|
||
{
|
||
return line != null ? line.GetLineNodes() : null;
|
||
}
|
||
|
||
private void RefreshInitialLengths(bool force = false)
|
||
{
|
||
List<FLineLogicNode> nodes = GetNodes();
|
||
int segmentCount = nodes != null ? Mathf.Max(0, nodes.Count - 1) : 0;
|
||
|
||
if (!force && initialLengths != null && initialLengths.Length == segmentCount)
|
||
return;
|
||
|
||
initialLengths = new float[nodes.Count];
|
||
|
||
for (var i = 0; i < nodes.Count; i++)
|
||
{
|
||
var node = nodes[i];
|
||
initialLengths[i] = Mathf.Max(0.01f, node.Lenght);
|
||
}
|
||
}
|
||
|
||
private float GetCurrentMaxLength(int segmentIndex)
|
||
{
|
||
var nodes = line.GetLineNodes();
|
||
var node = nodes[segmentIndex];
|
||
// float length = line.GetSegmentMaxLength(segmentIndex);
|
||
return Mathf.Max(0.01f, node.Lenght);
|
||
}
|
||
|
||
private float GetTargetMaxLength(int segmentIndex)
|
||
{
|
||
var nodes = line.GetLineNodes();
|
||
var node = nodes[segmentIndex];
|
||
float length = node.Lenght;
|
||
// if (length <= 0f)
|
||
// length = line.GetSegmentMaxLength(segmentIndex);
|
||
|
||
return Mathf.Max(0.01f, length);
|
||
}
|
||
|
||
private int GetSegmentCount()
|
||
{
|
||
return initialLengths != null ? initialLengths.Length : 0;
|
||
}
|
||
|
||
private void HandleInput()
|
||
{
|
||
HandleOriginalControls();
|
||
HandleDynamicDistanceControls();
|
||
}
|
||
|
||
private void HandleOriginalControls()
|
||
{
|
||
List<FLineLogicNode> nodes = GetNodes();
|
||
if (nodes == null)
|
||
return;
|
||
|
||
if (Input.GetKeyDown(fixMiddleKey) && nodes.Count >= 3)
|
||
{
|
||
int middleIndex = nodes.Count / 2;
|
||
FLineLogicNode middleNode = nodes[middleIndex];
|
||
Rigidbody middleRb = middleNode ? middleNode.Rigidbody : null;
|
||
|
||
if (middleNode && middleRb)
|
||
{
|
||
bool newState = !middleRb.isKinematic;
|
||
Debug.Log($"中间节点({middleIndex}) {(newState ? "固定" : "释放")} - 观察其他节点变化");
|
||
}
|
||
}
|
||
}
|
||
|
||
private void HandleDynamicDistanceControls()
|
||
{
|
||
if (line == null || initialLengths == null || initialLengths.Length == 0)
|
||
return;
|
||
|
||
if (Input.GetKeyDown(pullFirstKey))
|
||
PullFirstSegment(extendAmount * 0.5f);
|
||
|
||
if (Input.GetKeyDown(relaxFirstKey))
|
||
RelaxFirstSegment(extendAmount * 0.5f);
|
||
|
||
if (Input.GetKeyDown(fixedKey))
|
||
{
|
||
if (line.LineMode == LineMode.Joint) line.ChangeMode(LineMode.Constraint);
|
||
else line.ChangeMode(LineMode.Joint);
|
||
}
|
||
|
||
if (Input.GetKeyDown(debugKey))
|
||
{
|
||
line.Print();
|
||
}
|
||
}
|
||
|
||
private void ApplySegmentTargetLength(FLineLogicNodeType type, float targetLength)
|
||
{
|
||
line.SetLenght(targetLength, type);
|
||
}
|
||
|
||
private void PullFirstSegment(float amount)
|
||
{
|
||
if (GetSegmentCount() <= 0)
|
||
return;
|
||
|
||
float targetLength = Mathf.Max(0.1f, GetTargetMaxLength(0) - amount);
|
||
ApplySegmentTargetLength(0, targetLength);
|
||
Debug.Log($"拉紧第一段到 {targetLength:F2}");
|
||
}
|
||
|
||
private void RelaxFirstSegment(float amount)
|
||
{
|
||
if (GetSegmentCount() <= 0)
|
||
return;
|
||
|
||
float targetLength = GetTargetMaxLength(0) + amount;
|
||
ApplySegmentTargetLength(0, targetLength);
|
||
Debug.Log($"放松第一段到 {targetLength:F2}");
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
if (!EnsureCable())
|
||
return;
|
||
|
||
RefreshInitialLengths();
|
||
|
||
List<FLineLogicNode> nodes = GetNodes();
|
||
int nodeCount = nodes != null ? nodes.Count : 0;
|
||
|
||
GUILayout.BeginArea(new Rect(10f, 10f, 360f, 260f));
|
||
GUILayout.Label("=== 硬线系统测试控制 ===");
|
||
GUILayout.Label("原始控制:");
|
||
GUILayout.Label($" {fixMiddleKey} - 固定/释放中间节点");
|
||
GUILayout.Space(10f);
|
||
GUILayout.Label("动态间距控制:");
|
||
GUILayout.Label($" {pullFirstKey} - 拉紧第一段");
|
||
GUILayout.Label($" {relaxFirstKey} - 放松第一段");
|
||
GUILayout.Label(" Shift+滚轮 - 调整最近段");
|
||
GUILayout.Space(10f);
|
||
GUILayout.Label("设置:");
|
||
GUILayout.Label($" 节点数: {nodeCount}");
|
||
GUILayout.Label(" 初始长度来源: FLine 节点配置");
|
||
GUILayout.Label($" 过渡模式: {(smoothTransition ? "平滑" : "即时")}");
|
||
if (smoothTransition)
|
||
GUILayout.Label($" 过渡速度: {transitionSpeed:F1}");
|
||
|
||
GUILayout.EndArea();
|
||
|
||
GUILayout.BeginArea(new Rect(10f, 280f, 360f, 220f));
|
||
GUILayout.Label("=== 各段实际长度 ===");
|
||
|
||
// for (int i = 0; i < Mathf.Min(GetSegmentCount(), 10); i++)
|
||
// {
|
||
// Rigidbody bodyA = nodes[i] ? nodes[i].Rigidbody : null;
|
||
// Rigidbody bodyB = nodes[i + 1] ? nodes[i + 1].Rigidbody : null;
|
||
// if (!bodyA || !bodyB)
|
||
// continue;
|
||
//
|
||
// float actualDistance = Vector3.Distance(bodyA.position, bodyB.position);
|
||
// float currentLimit = GetCurrentMaxLength(i);
|
||
// float targetLimit = GetTargetMaxLength(i);
|
||
//
|
||
// string segmentInfo = $"段{i}: {actualDistance:F2} (限制: {currentLimit:F2}";
|
||
// if (line.IsSegmentTransitioning(i))
|
||
// segmentInfo += $" -> {targetLimit:F2}";
|
||
//
|
||
// segmentInfo += ")";
|
||
//
|
||
// if (actualDistance > targetLimit * 1.1f)
|
||
// {
|
||
// GUI.color = Color.red;
|
||
// }
|
||
// else if (line.IsSegmentTransitioning(i))
|
||
// {
|
||
// GUI.color = Color.yellow;
|
||
// }
|
||
// else
|
||
// {
|
||
// GUI.color = Color.green;
|
||
// }
|
||
//
|
||
// GUILayout.Label(segmentInfo);
|
||
// }
|
||
|
||
GUI.color = Color.white;
|
||
|
||
bool anyTransitioning = false;
|
||
for (int i = 0; i < GetSegmentCount(); i++)
|
||
{
|
||
if (line.IsSegmentTransitioning(i))
|
||
{
|
||
anyTransitioning = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (anyTransitioning)
|
||
GUILayout.Label("状态: 过渡中...");
|
||
|
||
GUILayout.EndArea();
|
||
}
|
||
}
|
||
} |