Files
Fishing2NetTest/Assets/Scripts/Common/Utils/NewFile1.txt
2026-03-05 18:07:55 +08:00

223 lines
8.0 KiB
Plaintext
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 UnityEngine;
using System.Collections.Generic;
namespace NBF
{
[System.Serializable]
public struct FishingCastInput
{
[Range(0, 1)] public float power;
[Range(0, 50)] public float windStrength; // 单位 m/s
public Vector3 windDirection;
[Range(5, 30)] public float lureWeight; // 单位 g
[Range(0, 30)] public float spiralAngularSpeed;
}
public class LureTrajectorySimulator : MonoBehaviour
{
[Header("基础参数")] public int maxSimulationSteps = 1000;
public float simulationDuration = 10f;
public float timeStep = 0.02f;
[Header("抛投力度")] public float minThrowPower = 15f;
public float maxThrowPower = 45f;
[Header("空气阻力参数")] [Tooltip("阻力系数,非流线钓饵建议 0.8~1.2")]
public float dragCoefficient = 0.1f;
[Tooltip("迎风面积0.005m² ≈ 5cm²")] public float lureArea = 0.001f;
[Header("螺旋轨迹参数")] public float spiralRadius = 0.3f; // 初始螺旋半径(单位:米)
[Range(0f, 2f)] public float spiralDecay = 1f; // 螺旋逐渐减弱的衰减因子
/// <summary>
/// 加入了风
/// </summary>
/// <param name="input"></param>
/// <param name="startPosition"></param>
/// <param name="castDirection"></param>
/// <returns></returns>
public List<Vector3> CalculateTrajectory(FishingCastInput input, Vector3 startPosition, Vector3 castDirection)
{
List<Vector3> trajectory = new List<Vector3>();
Vector3 position = startPosition;
Vector3 direction = castDirection.normalized;
float throwPower = Mathf.Lerp(minThrowPower, maxThrowPower, input.power);
Vector3 velocity = direction * throwPower;
float lureMass = input.lureWeight / 1000f; // 转 kg
Vector3 windDir = input.windDirection.normalized;
float windStrength = input.windStrength;
float currentTime = 0f;
int steps = 0;
while (currentTime < simulationDuration && steps < maxSimulationSteps)
{
if (position.y <= 0f) break;
// 模拟风力逐渐生效
float windInfluenceFactor = Mathf.Clamp01(currentTime / 1.5f); // 1.5秒内增长
Vector3 windVelocity = windDir * windStrength * windInfluenceFactor;
// 真实空气阻力模型
Vector3 relVelocity = velocity - windVelocity;
// 空气阻力
float dragMag = 0.5f * PhysicsHelper.AirDensity *
relVelocity.sqrMagnitude *
dragCoefficient * lureArea;
Vector3 dragForce = -relVelocity.normalized * dragMag;
// 合力 = 重力 + 空气阻力
Vector3 acceleration = (Physics.gravity + dragForce / lureMass);
velocity += acceleration * timeStep;
position += velocity * timeStep;
// // 当前角度(代替原来的 spiralAngle 计算)
// float spiralAngle = currentTime * input.spiralAngularSpeed;
//
// float spiralFalloff = Mathf.Exp(-spiralDecay * currentTime);
// float radiusNow = spiralRadius * spiralFalloff;
//
// // 构造绕投掷方向垂直平面上的偏移
// Vector3 right = Vector3.Cross(direction, Vector3.up).normalized;
// if (right.sqrMagnitude < 0.001f)
// right = Vector3.Cross(direction, Vector3.forward).normalized; // 防止方向与up重合
// Vector3 up = Vector3.Cross(direction, right).normalized;
// Vector3 spiralOffset = (right * Mathf.Cos(spiralAngle) + up * Mathf.Sin(spiralAngle)) * radiusNow;
//
// position += spiralOffset;
trajectory.Add(position);
currentTime += timeStep;
steps++;
}
return trajectory;
}
// 示例调用
private List<Vector3> _trajectory;
private int _windIndex;
public List<Vector3> Test(Transform cameraTransform)
{
Vector3[] directions =
{
Vector3.forward,
Vector3.back,
Vector3.right,
Vector3.left,
(Vector3.forward + Vector3.right).normalized,
(Vector3.forward + Vector3.left).normalized,
(Vector3.back + Vector3.right).normalized,
(Vector3.back + Vector3.left).normalized
};
FishingCastInput baseInput = new FishingCastInput
{
power = 1f,
lureWeight = 2f,
windStrength = 6f, // 风力大小
spiralAngularSpeed = 15
};
Vector3 startPos = cameraTransform.position;
Vector3 throwDir = cameraTransform.forward.normalized;
baseInput.windDirection = directions[_windIndex]; //directions[_windIndex]; (-transform.forward).normalized;
_trajectory = CalculateTrajectory(baseInput, startPos, throwDir);
_windIndex++;
if (_windIndex >= directions.Length)
{
_windIndex = 0;
}
var length = CalculateTrajectoryLength(_trajectory);
var distance = CalculateHorizontalDistance(_trajectory);
Debug.LogError($"轨迹点位数={_trajectory.Count} length={length} distance={distance}");
SceneSettings.Instance.LineRenderer.startWidth = 0.1f;
SceneSettings.Instance.LineRenderer.endWidth = 0.1f;
SceneSettings.Instance.LineRenderer.positionCount = _trajectory.Count;
SceneSettings.Instance.LineRenderer.useWorldSpace = true;
SceneSettings.Instance.LineRenderer.SetPositions(_trajectory.ToArray());
return _trajectory;
}
/// <summary>
/// 计算轨迹总长度(线的实际长度)
/// </summary>
public float CalculateTrajectoryLength(List<Vector3> trajectory)
{
if (trajectory == null || trajectory.Count < 2)
return 0f;
float totalLength = 0f;
for (int i = 1; i < trajectory.Count; i++)
{
totalLength += Vector3.Distance(trajectory[i - 1], trajectory[i]);
}
return totalLength;
}
/// <summary>
/// 计算水平距离XZ平面上的直线距离
/// </summary>
public float CalculateHorizontalDistance(List<Vector3> trajectory)
{
if (trajectory == null || trajectory.Count == 0)
return 0f;
Vector3 startPoint = trajectory[0];
Vector3 endPoint = trajectory[trajectory.Count - 1];
// 将Y坐标设为相同地面高度
startPoint.y = 0;
endPoint.y = 0;
return Vector3.Distance(startPoint, endPoint);
}
private void OnDrawGizmos()
{
if (_trajectory == null) return;
Gizmos.color = Color.cyan;
for (int i = 0; i < _trajectory.Count - 1; i++)
{
Gizmos.DrawLine(_trajectory[i], _trajectory[i + 1]);
}
if (_trajectory.Count > 0)
{
Gizmos.color = Color.green;
Gizmos.DrawSphere(_trajectory[0], 0.1f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(_trajectory[_trajectory.Count - 1], 0.1f);
for (int i = 1; i < _trajectory.Count; i += 10)
{
Gizmos.color = Color.Lerp(Color.green, Color.red, i / (float)_trajectory.Count);
Gizmos.DrawSphere(_trajectory[i], 0.05f);
}
}
}
}
public static class PhysicsHelper
{
public const float AirDensity = 1.225f;
}
}