接入新逻辑
# 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
This commit is contained in:
349
Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs
Normal file
349
Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs
Normal file
@@ -0,0 +1,349 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user