Files
Fishing2/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs
Bob.Song d432c468b1 接入新逻辑
# Conflicts:
#	Assets/Scenes/RopeTest.unity
#	Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs
#	Assets/Scripts/Fishing/Rope/Rope.cs
#	Assets/Scripts/Fishing/Rope/Rope.cs.meta
2026-04-26 14:44:06 +08:00

349 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
namespace NBF
{
/// <summary>
/// 硬线系统测试脚本,直接读取 FLine 已配置的节点。
/// </summary>
public class FLineTest : MonoBehaviour
{
[Header("测试控制")] [SerializeField] private KeyCode fixMiddleKey = KeyCode.M;
[SerializeField] private KeyCode applyForceKey = KeyCode.F;
[SerializeField] private Vector3 testForce = new Vector3(0f, 10f, 0f);
[Header("动态间距控制")]
// [SerializeField] private KeyCode extendKey = KeyCode.UpArrow;
// [SerializeField] private KeyCode contractKey = KeyCode.DownArrow;
[SerializeField]
private KeyCode resetKey = KeyCode.Alpha0;
[SerializeField] private KeyCode pullFirstKey = KeyCode.UpArrow;
[SerializeField] private KeyCode relaxFirstKey = KeyCode.DownArrow;
[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.OnLineBreakRequested += OnLineBreakRequested;
}
private void OnLineBreakRequested(FLine lineSolver)
{
Debug.LogError($"当前拉力达到极限,切线,极限时间={lineSolver.LimitStateTime}");
var nodes = line.GetLineNodes();
nodes[^1].Rigidbody.isKinematic = false;
// line.Body.isKinematic = false;
}
private void Update()
{
if (!EnsureCable())
return;
RefreshInitialLengths();
HandleInput();
if (line.CurrentBreakStretchPercent > 10f)
{
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[segmentCount];
for (int i = 0; i < segmentCount; i++)
{
float configuredLength = line.GetSegmentMaxLength(i);
if (configuredLength <= 0f)
configuredLength = Mathf.Max(0.01f, line.GetCurrentSegmentLength(i));
initialLengths[i] = Mathf.Max(0.01f, configuredLength);
}
}
private float GetCurrentMaxLength(int segmentIndex)
{
float length = line.GetSegmentMaxLength(segmentIndex);
return Mathf.Max(0.01f, length);
}
private float GetTargetMaxLength(int segmentIndex)
{
float length = line.GetTargetMaxLength(segmentIndex);
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;
middleNode.SetFixed(newState);
Debug.Log($"中间节点({middleIndex}) {(newState ? "" : "")} - 观察其他节点变化");
}
}
if (Input.GetKeyDown(applyForceKey) && nodes.Count > 2)
{
int randomIndex = Random.Range(1, nodes.Count - 1);
FLineLogicNode targetNode = nodes[randomIndex];
Rigidbody targetRb = targetNode ? targetNode.Rigidbody : null;
if (targetNode && targetRb && !targetRb.isKinematic)
{
targetNode.ApplyForce(testForce, ForceMode.Impulse);
Debug.Log($"对节点{randomIndex}施加力: {testForce} - 观察传递效果");
}
}
}
private void HandleDynamicDistanceControls()
{
if (line == null || initialLengths == null || initialLengths.Length == 0)
return;
// HandleLengthAdjustInput();
if (Input.GetKeyDown(resetKey))
ResetAllSegments();
if (Input.GetKeyDown(pullFirstKey))
PullFirstSegment(extendAmount * 0.5f);
if (Input.GetKeyDown(relaxFirstKey))
RelaxFirstSegment(extendAmount * 0.5f);
if (Input.mouseScrollDelta.y != 0f && Input.GetKey(KeyCode.LeftShift))
AdjustNearestSegment(Input.mouseScrollDelta.y * 0.1f);
}
private void ApplySegmentTargetLength(int segmentIndex, float targetLength)
{
line.SetSegmentMaxLength(segmentIndex, targetLength, transitionSpeed);
}
private void ResetAllSegments()
{
for (int i = 0; i < GetSegmentCount(); i++)
{
ApplySegmentTargetLength(i, initialLengths[i]);
}
Debug.Log("重置绳索到 FLine 初始节点配置");
}
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 AdjustNearestSegment(float amount)
{
int nearestSegment = FindNearestSegmentToCamera();
if (nearestSegment < 0 || nearestSegment >= GetSegmentCount())
return;
float targetLength = Mathf.Max(0.1f, GetTargetMaxLength(nearestSegment) + amount);
ApplySegmentTargetLength(nearestSegment, targetLength);
Debug.Log($"调整段{nearestSegment}到 {targetLength:F2}");
}
private int FindNearestSegmentToCamera()
{
Camera cam = Camera.main;
List<FLineLogicNode> nodes = GetNodes();
if (cam == null || nodes == null || nodes.Count < 2)
return -1;
int nearestSegment = -1;
float nearestDistance = float.MaxValue;
for (int i = 0; i < nodes.Count - 1; i++)
{
Rigidbody bodyA = nodes[i] ? nodes[i].Rigidbody : null;
Rigidbody bodyB = nodes[i + 1] ? nodes[i + 1].Rigidbody : null;
if (!bodyA || !bodyB)
continue;
Vector3 midPoint = (bodyA.position + bodyB.position) * 0.5f;
Vector3 screenPoint = cam.WorldToScreenPoint(midPoint);
Vector3 mousePos = Input.mousePosition;
float distance = Vector2.Distance(
new Vector2(screenPoint.x, screenPoint.y),
new Vector2(mousePos.x, mousePos.y)
);
if (distance < nearestDistance)
{
nearestDistance = distance;
nearestSegment = i;
}
}
return nearestSegment;
}
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.Label($" {applyForceKey} - 随机施加力");
GUILayout.Space(10f);
GUILayout.Label("动态间距控制:");
GUILayout.Label($" {resetKey} - 重置到初始节点配置");
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();
}
}
}