目录调整,旧钓鱼逻辑全部注释

This commit is contained in:
2025-08-22 00:09:05 +08:00
parent 2f8251fe63
commit 6767dc7019
154 changed files with 937 additions and 483 deletions

View File

@@ -1,257 +1,257 @@
using UnityEngine;
using System.Collections.Generic;
namespace NBF
{
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.2f;
[Tooltip("迎风面积0.005m² ≈ 5cm²")] public float lureArea = 0.001f;
public List<Vector3> CalculateTrajectory(FishingLureCastInput 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;
// --- 钓线空气阻力模拟 ---
// 假设飞行中展开的线长度近似为当前位置的XZ平面长度
float lineLength = Vector3.Distance(new Vector3(position.x, 0, position.z),
new Vector3(startPosition.x, 0, startPosition.z));
float lineRadius = input.lineDiameter / 2000f; // mm转m再除以2得到半径
// 钓线的迎风面积估算:长度 * 直径
float lineArea = lineLength * (lineRadius * 2f); // 近似为圆柱体侧面积的一部分
// 简化模型:线的附加空气阻力方向与当前速度方向相反
float lineDragMag = 0.5f * PhysicsHelper.AirDensity * velocity.sqrMagnitude * dragCoefficient *
lineArea;
Vector3 lineDragForce = -velocity.normalized * lineDragMag;
Vector3 dragForce = -relVelocity.normalized * dragMag;
// 合力 = 重力 + 空气阻力
// Vector3 acceleration = (Physics.gravity + dragForce / lureMass);
Vector3 totalForce = dragForce + lineDragForce;
// 合力 = 重力 + 空气阻力 + 线阻力
Vector3 acceleration = (Physics.gravity + totalForce / lureMass);
velocity += acceleration * timeStep;
position += velocity * timeStep;
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
};
FishingLureCastInput baseInput = new FishingLureCastInput
{
power = 1f,
lureWeight = 2.2f,
windStrength = 0f, // 风力大小
lineDiameter = 0.14f
};
Vector3 startPos = cameraTransform.position;
Vector3 throwDir = cameraTransform.forward.normalized;
baseInput.windDirection = directions[_windIndex];
_trajectory = CalculateTrajectory(baseInput, startPos, throwDir);
_trajectory = SimplifyTrajectoryRDP(_trajectory, 0.1f);
_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 List<Vector3> SimplifyTrajectoryRDP(List<Vector3> points, float tolerance)
{
if (points == null || points.Count < 3)
return new List<Vector3>(points);
List<Vector3> result = new List<Vector3>();
SimplifySection(points, 0, points.Count - 1, tolerance, result);
result.Add(points[points.Count - 1]);
return result;
}
private static void SimplifySection(List<Vector3> points, int start, int end, float tolerance,
List<Vector3> result)
{
if (end <= start + 1)
return;
float maxDistance = -1f;
int index = -1;
Vector3 startPoint = points[start];
Vector3 endPoint = points[end];
for (int i = start + 1; i < end; i++)
{
float distance = PerpendicularDistance(points[i], startPoint, endPoint);
if (distance > maxDistance)
{
maxDistance = distance;
index = i;
}
}
if (maxDistance > tolerance)
{
SimplifySection(points, start, index, tolerance, result);
result.Add(points[index]);
SimplifySection(points, index, end, tolerance, result);
}
}
private static float PerpendicularDistance(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
{
if (lineStart == lineEnd) return Vector3.Distance(point, lineStart);
Vector3 projected = Vector3.Project(point - lineStart, lineEnd - lineStart);
Vector3 closest = lineStart + projected;
return Vector3.Distance(point, closest);
}
}
public static class PhysicsHelper
{
public const float AirDensity = 1.225f;
}
}
// using UnityEngine;
// using System.Collections.Generic;
//
// namespace NBF
// {
// 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.2f;
//
// [Tooltip("迎风面积0.005m² ≈ 5cm²")] public float lureArea = 0.001f;
//
//
// public List<Vector3> CalculateTrajectory(FishingLureCastInput 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;
//
//
// // --- 钓线空气阻力模拟 ---
// // 假设飞行中展开的线长度近似为当前位置的XZ平面长度
// float lineLength = Vector3.Distance(new Vector3(position.x, 0, position.z),
// new Vector3(startPosition.x, 0, startPosition.z));
// float lineRadius = input.lineDiameter / 2000f; // mm转m再除以2得到半径
//
// // 钓线的迎风面积估算:长度 * 直径
// float lineArea = lineLength * (lineRadius * 2f); // 近似为圆柱体侧面积的一部分
//
// // 简化模型:线的附加空气阻力方向与当前速度方向相反
// float lineDragMag = 0.5f * PhysicsHelper.AirDensity * velocity.sqrMagnitude * dragCoefficient *
// lineArea;
// Vector3 lineDragForce = -velocity.normalized * lineDragMag;
//
//
// Vector3 dragForce = -relVelocity.normalized * dragMag;
//
// // 合力 = 重力 + 空气阻力
// // Vector3 acceleration = (Physics.gravity + dragForce / lureMass);
// Vector3 totalForce = dragForce + lineDragForce;
// // 合力 = 重力 + 空气阻力 + 线阻力
// Vector3 acceleration = (Physics.gravity + totalForce / lureMass);
//
//
// velocity += acceleration * timeStep;
// position += velocity * timeStep;
//
// 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
// };
//
// FishingLureCastInput baseInput = new FishingLureCastInput
// {
// power = 1f,
// lureWeight = 2.2f,
// windStrength = 0f, // 风力大小
// lineDiameter = 0.14f
// };
//
//
// Vector3 startPos = cameraTransform.position;
// Vector3 throwDir = cameraTransform.forward.normalized;
//
// baseInput.windDirection = directions[_windIndex];
// _trajectory = CalculateTrajectory(baseInput, startPos, throwDir);
// _trajectory = SimplifyTrajectoryRDP(_trajectory, 0.1f);
// _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 List<Vector3> SimplifyTrajectoryRDP(List<Vector3> points, float tolerance)
// {
// if (points == null || points.Count < 3)
// return new List<Vector3>(points);
//
// List<Vector3> result = new List<Vector3>();
// SimplifySection(points, 0, points.Count - 1, tolerance, result);
// result.Add(points[points.Count - 1]);
// return result;
// }
//
// private static void SimplifySection(List<Vector3> points, int start, int end, float tolerance,
// List<Vector3> result)
// {
// if (end <= start + 1)
// return;
//
// float maxDistance = -1f;
// int index = -1;
// Vector3 startPoint = points[start];
// Vector3 endPoint = points[end];
//
// for (int i = start + 1; i < end; i++)
// {
// float distance = PerpendicularDistance(points[i], startPoint, endPoint);
// if (distance > maxDistance)
// {
// maxDistance = distance;
// index = i;
// }
// }
//
// if (maxDistance > tolerance)
// {
// SimplifySection(points, start, index, tolerance, result);
// result.Add(points[index]);
// SimplifySection(points, index, end, tolerance, result);
// }
// }
//
// private static float PerpendicularDistance(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
// {
// if (lineStart == lineEnd) return Vector3.Distance(point, lineStart);
// Vector3 projected = Vector3.Project(point - lineStart, lineEnd - lineStart);
// Vector3 closest = lineStart + projected;
// return Vector3.Distance(point, closest);
// }
// }
//
// public static class PhysicsHelper
// {
// public const float AirDensity = 1.225f;
// }
// }

View File

@@ -4,156 +4,156 @@ namespace NBF
{
public static class PrefabCreator
{
#region
// #region
//
// public static ReelAsset Create(this GameReels self, Transform parent, bool isPreview = false)
// {
// ReelAsset ret = null;
// var prefab = self.Instantiate(parent);
//
// prefab.transform.localPosition = Vector3.zero;
// prefab.transform.localRotation = Quaternion.identity;
//
// if (prefab.TryGetComponent<ReelAsset>(out var reel))
// {
// ret = reel;
//
// if (!isPreview)
// {
// prefab.AddComponent<FReel>();
// // prefab.AddJoint();
// // var dis = prefab.AddComponent<FWaterDisplacement>();
// // dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
// // dis.objectDisplacement = 2;
// // dis.outwaterMass = 0.1f;
// }
// }
//
// return ret;
// }
//
// #endregion
public static ReelAsset Create(this GameReels self, Transform parent, bool isPreview = false)
{
ReelAsset ret = null;
var prefab = self.Instantiate(parent);
prefab.transform.localPosition = Vector3.zero;
prefab.transform.localRotation = Quaternion.identity;
if (prefab.TryGetComponent<ReelAsset>(out var reel))
{
ret = reel;
if (!isPreview)
{
prefab.AddComponent<FReel>();
// prefab.AddJoint();
// var dis = prefab.AddComponent<FWaterDisplacement>();
// dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
// dis.objectDisplacement = 2;
// dis.outwaterMass = 0.1f;
}
}
return ret;
}
#endregion
#region
public static BobberAsset Create(this GameFloats self, Transform parent, bool isPreview = false)
{
BobberAsset ret = null;
var prefab = self.Instantiate(parent);
prefab.transform.localPosition = Vector3.zero;
prefab.transform.localRotation = Quaternion.identity;
if (prefab.TryGetComponent<BobberAsset>(out var lure))
{
ret = lure;
if (!isPreview)
{
prefab.AddComponent<FFloat>();
prefab.AddJoint();
var dis = prefab.AddComponent<FWaterDisplacement>();
dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
dis.objectDisplacement = 2;
dis.outwaterMass = 0.1f;
}
}
return ret;
}
#endregion
#region
public static LureAsset Create(this GameLures self, Transform parent, bool isPreview = false)
{
LureAsset ret = null;
var prefab = self.Instantiate(parent);
if (prefab.TryGetComponent<LureAsset>(out var lure))
{
ret = lure;
if (!isPreview)
{
prefab.AddComponent<FLure>();
prefab.AddJoint();
var rigidbody = prefab.GetComponent<Rigidbody>();
rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
rigidbody.linearDamping = 0.5f;
var dis = prefab.AddComponent<FWaterDisplacement>();
// dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
// dis.objectDisplacement = 2;
dis.outwaterMass = 0.5f;
}
if (lure.hookPoints != null && lure.hookPoints.Length > 0)
{
for (int i = 0; i < lure.hookPoints.Length; i++)
{
var hookPoint = lure.hookPoints[i];
var hook = self.hook[0];
var hookConfig = GameHooks.Get(hook);
var hookAsset = hookConfig.Create(hookPoint, true);
hookAsset.transform.localPosition = Vector3.zero;
hookAsset.transform.localRotation = Quaternion.identity;
var configurableJoint = hookAsset.GetComponent<ConfigurableJoint>();
configurableJoint.connectedBody = prefab.GetComponent<Rigidbody>();
}
}
}
return ret;
}
public static BaitAsset Create(this GameBaits self, Transform parent, bool isPreview = false)
{
var prefab = self.Instantiate(parent);
BaitAsset ret = null;
if (prefab.TryGetComponent<BaitAsset>(out var hook))
{
ret = hook;
}
prefab.transform.localPosition = Vector3.zero;
prefab.transform.localRotation = Quaternion.identity;
if (!isPreview)
{
prefab.AddComponent<FBait>();
}
return ret;
}
#endregion
#region
public static HookAsset Create(this GameHooks self, Transform parent, bool isPreview = false)
{
var prefab = self.Instantiate(parent);
HookAsset ret = null;
if (prefab.TryGetComponent<HookAsset>(out var hook))
{
ret = hook;
}
prefab.transform.localPosition = Vector3.zero;
prefab.transform.localRotation = Quaternion.identity;
if (!isPreview)
{
prefab.AddComponent<FHook>();
var d = prefab.AddComponent<FWaterDisplacement>();
d.outwaterMass = 0.1f;
}
return ret;
}
#endregion
// #region 浮漂
//
// public static BobberAsset Create(this GameFloats self, Transform parent, bool isPreview = false)
// {
// BobberAsset ret = null;
// var prefab = self.Instantiate(parent);
//
// prefab.transform.localPosition = Vector3.zero;
// prefab.transform.localRotation = Quaternion.identity;
//
// if (prefab.TryGetComponent<BobberAsset>(out var lure))
// {
// ret = lure;
//
// if (!isPreview)
// {
// prefab.AddComponent<FFloat>();
// prefab.AddJoint();
// var dis = prefab.AddComponent<FWaterDisplacement>();
// dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
// dis.objectDisplacement = 2;
// dis.outwaterMass = 0.1f;
// }
// }
//
// return ret;
// }
//
// #endregion
//
//
// #region 饵
//
// public static LureAsset Create(this GameLures self, Transform parent, bool isPreview = false)
// {
// LureAsset ret = null;
// var prefab = self.Instantiate(parent);
//
//
// if (prefab.TryGetComponent<LureAsset>(out var lure))
// {
// ret = lure;
//
// if (!isPreview)
// {
// prefab.AddComponent<FLure>();
// prefab.AddJoint();
// var rigidbody = prefab.GetComponent<Rigidbody>();
// rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
// rigidbody.linearDamping = 0.5f;
// var dis = prefab.AddComponent<FWaterDisplacement>();
// // dis.moveCharacteristic = FWaterDisplacement.MoveCharacteristic.Custom;
// // dis.objectDisplacement = 2;
// dis.outwaterMass = 0.5f;
// }
//
// if (lure.hookPoints != null && lure.hookPoints.Length > 0)
// {
// for (int i = 0; i < lure.hookPoints.Length; i++)
// {
// var hookPoint = lure.hookPoints[i];
// var hook = self.hook[0];
// var hookConfig = GameHooks.Get(hook);
// var hookAsset = hookConfig.Create(hookPoint, true);
// hookAsset.transform.localPosition = Vector3.zero;
// hookAsset.transform.localRotation = Quaternion.identity;
// var configurableJoint = hookAsset.GetComponent<ConfigurableJoint>();
// configurableJoint.connectedBody = prefab.GetComponent<Rigidbody>();
// }
// }
// }
//
// return ret;
// }
//
// public static BaitAsset Create(this GameBaits self, Transform parent, bool isPreview = false)
// {
// var prefab = self.Instantiate(parent);
// BaitAsset ret = null;
// if (prefab.TryGetComponent<BaitAsset>(out var hook))
// {
// ret = hook;
// }
//
// prefab.transform.localPosition = Vector3.zero;
// prefab.transform.localRotation = Quaternion.identity;
// if (!isPreview)
// {
// prefab.AddComponent<FBait>();
// }
//
// return ret;
// }
//
// #endregion
//
// #region 钩
//
// public static HookAsset Create(this GameHooks self, Transform parent, bool isPreview = false)
// {
// var prefab = self.Instantiate(parent);
// HookAsset ret = null;
// if (prefab.TryGetComponent<HookAsset>(out var hook))
// {
// ret = hook;
// }
//
// prefab.transform.localPosition = Vector3.zero;
// prefab.transform.localRotation = Quaternion.identity;
// if (!isPreview)
// {
// prefab.AddComponent<FHook>();
// var d = prefab.AddComponent<FWaterDisplacement>();
// d.outwaterMass = 0.1f;
// }
//
// return ret;
// }
//
// #endregion
#region