去掉obi,使用自写绳索
This commit is contained in:
57
Assets/Scripts/Editor/RopeEditor.cs
Normal file
57
Assets/Scripts/Editor/RopeEditor.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(Rope))]
|
||||
public class RopeFishLineEditor : Editor
|
||||
{
|
||||
private Rope _target;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
_target = target as Rope;
|
||||
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
if (GUILayout.Button("增加0.5长度"))
|
||||
{
|
||||
_target.AddTargetLength(0.5f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("减小0.5长度"))
|
||||
{
|
||||
_target.AddTargetLength(-0.5f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("增加0.1长度"))
|
||||
{
|
||||
_target.AddTargetLength(0.1f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("减小0.1长度"))
|
||||
{
|
||||
_target.AddTargetLength(-0.1f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("增加0.01长度"))
|
||||
{
|
||||
_target.AddTargetLength(0.01f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("减小0.01长度"))
|
||||
{
|
||||
_target.AddTargetLength(-0.01f);
|
||||
}
|
||||
|
||||
|
||||
if (GUILayout.Button("打印总长度"))
|
||||
{
|
||||
Debug.Log($"总长度={_target.GetCurrentLength()} 目标长度={_target.GetTargetLength()}");
|
||||
}
|
||||
// serializedObject.Update();
|
||||
// EditorGUILayout.PropertyField(lookAtPoint);
|
||||
// serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/RopeEditor.cs.meta
Normal file
3
Assets/Scripts/Editor/RopeEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f24add4ba0ae4e76acd98c4a5512c366
|
||||
timeCreated: 1771850618
|
||||
@@ -1,9 +1,9 @@
|
||||
using Obi;
|
||||
// using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
public class RodLine : MonoBehaviour
|
||||
{
|
||||
private ObiRope obiRope;
|
||||
// private ObiRope obiRope;
|
||||
|
||||
private LineRenderer lineRenderer;
|
||||
|
||||
|
||||
@@ -1,44 +1,512 @@
|
||||
using NBC;
|
||||
using NBF;
|
||||
using Obi;
|
||||
using NBF;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(LineRenderer))]
|
||||
public class Rope : MonoBehaviour
|
||||
{
|
||||
private FRod _rod;
|
||||
public bool isFloatRope;
|
||||
[SerializeField] private ObiRope rope;
|
||||
[Header("Anchors")] [SerializeField] public Rigidbody startAnchor;
|
||||
[SerializeField] public Rigidbody endAnchor;
|
||||
|
||||
[SerializeField] private ObiRopeCursor cursor;
|
||||
[Header("Physics (Dynamic Nodes, Fixed Segment Len)")] [SerializeField, Min(0.01f), Tooltip("物理每段固定长度(越小越细致越耗)")]
|
||||
private float physicsSegmentLen = 0.15f;
|
||||
|
||||
[SerializeField] private float percentageElasticity = 0.2f;
|
||||
[SerializeField, Range(2, 200)] private int minPhysicsNodes = 12;
|
||||
|
||||
[SerializeField, Range(2, 400)] [Tooltip("物理节点上限(仅用于性能保护;与“最大长度不限制”不是一回事)")]
|
||||
private int maxPhysicsNodes = 120;
|
||||
|
||||
[SerializeField] private float gravityStrength = 2.0f;
|
||||
[SerializeField, Range(0f, 1f)] private float velocityDampen = 0.95f;
|
||||
|
||||
[SerializeField, Range(0.0f, 1.0f)] [Tooltip("约束修正强度,越大越硬。0.6~0.9 常用")]
|
||||
private float stiffness = 0.8f;
|
||||
|
||||
[SerializeField, Range(1, 80)] [Tooltip("迭代次数。鱼线 10~30 通常够用")]
|
||||
private int iterations = 20;
|
||||
|
||||
[Header("Length Control (No Min/Max Clamp)")]
|
||||
[Tooltip("初始总长度(米)。如果为 0,则用 physicsSegmentLen*(minPhysicsNodes-1) 作为初始长度")]
|
||||
[SerializeField, Min(0f)]
|
||||
private float initialLength = 0f;
|
||||
|
||||
[Tooltip("长度变化平滑时间(越小越跟手,越大越稳)")] [SerializeField, Min(0.0001f)]
|
||||
private float lengthSmoothTime = 0.15f;
|
||||
|
||||
[Tooltip("当长度在变化时,额外把速度压掉一些(防抖)。0=不额外处理,1=变化时几乎清速度")] [SerializeField, Range(0f, 1f)]
|
||||
private float lengthChangeVelocityKill = 0.6f;
|
||||
|
||||
[Tooltip("允许的最小松弛余量(避免目标长度刚好等于锚点距离时抖动)")] [SerializeField, Min(0f)]
|
||||
private float minSlack = 0.002f;
|
||||
|
||||
[Header("Head Segment Clamp")] [Tooltip("第一段(起点->第1节点)允许的最小长度,避免收线时第一段被压到0导致数值炸")] [SerializeField, Min(0.0001f)]
|
||||
private float headMinLen = 0.01f;
|
||||
|
||||
[Header("Simple Ground/Water Constraint (Cheap)")] [SerializeField]
|
||||
private bool constrainToGround = true;
|
||||
|
||||
[SerializeField] private LayerMask groundMask = ~0;
|
||||
[SerializeField, Min(0f)] private float groundRadius = 0.01f;
|
||||
[SerializeField, Min(0f)] private float groundCastHeight = 1.0f;
|
||||
[SerializeField, Min(0.01f)] private float groundCastDistance = 2.5f;
|
||||
|
||||
[SerializeField] private bool constrainToWater = false;
|
||||
[SerializeField] private float waterHeight = 0f;
|
||||
[SerializeField, Min(0f)] private float waterRadius = 0.01f;
|
||||
|
||||
[Header("Render (High Resolution)")] [SerializeField, Min(1), Tooltip("每段物理线段插值加密的数量(越大越顺,越耗)")]
|
||||
private int renderSubdivisions = 6;
|
||||
|
||||
[SerializeField, Tooltip("是否使用 Catmull-Rom 平滑(推荐开启)")]
|
||||
private bool smooth = true;
|
||||
|
||||
[SerializeField, Min(0.0001f)] private float lineWidth = 0.002f;
|
||||
|
||||
private LineRenderer lr;
|
||||
|
||||
// physics
|
||||
private int physicsNodes;
|
||||
private Vector3[] pCurr;
|
||||
private Vector3[] pPrev;
|
||||
|
||||
// render
|
||||
private Vector3[] rPoints;
|
||||
private int rCountCached = -1;
|
||||
|
||||
private Vector3 gravity;
|
||||
|
||||
// length control runtime
|
||||
private float targetLength;
|
||||
private float currentLength;
|
||||
private float lengthSmoothVel;
|
||||
|
||||
// Only-head-change trick:
|
||||
// Total rest length = headRestLen + (physicsNodes - 2) * physicsSegmentLen
|
||||
private float headRestLen;
|
||||
|
||||
private float stretchScale;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rope = GetComponent<ObiRope>();
|
||||
lr = GetComponent<LineRenderer>();
|
||||
gravity = new Vector3(0f, -gravityStrength, 0f);
|
||||
|
||||
InitLengthSystem();
|
||||
AllocateAndInitNodes();
|
||||
RebuildRenderBufferIfNeeded();
|
||||
}
|
||||
|
||||
private FRod _rod;
|
||||
|
||||
public void Init(FRod rod)
|
||||
{
|
||||
_rod = rod;
|
||||
}
|
||||
|
||||
public void LineLength_OnValueChanged(float length)
|
||||
private void OnValidate()
|
||||
{
|
||||
cursor = cursor == null ? GetComponent<ObiRopeCursor>() : cursor;
|
||||
var old = stretchScale;
|
||||
stretchScale = Mathf.Clamp(length - percentageElasticity, 0f, float.PositiveInfinity);
|
||||
// cursor.ChangeLength(length);
|
||||
if (stretchScale != old)
|
||||
renderSubdivisions = Mathf.Max(renderSubdivisions, 1);
|
||||
iterations = Mathf.Clamp(iterations, 1, 80);
|
||||
groundCastDistance = Mathf.Max(groundCastDistance, 0.01f);
|
||||
groundCastHeight = Mathf.Max(groundCastHeight, 0f);
|
||||
lineWidth = Mathf.Max(lineWidth, 0.0001f);
|
||||
|
||||
lengthSmoothTime = Mathf.Max(lengthSmoothTime, 0.0001f);
|
||||
|
||||
physicsSegmentLen = Mathf.Max(physicsSegmentLen, 0.01f);
|
||||
minPhysicsNodes = Mathf.Max(minPhysicsNodes, 2);
|
||||
maxPhysicsNodes = Mathf.Max(maxPhysicsNodes, minPhysicsNodes);
|
||||
|
||||
headMinLen = Mathf.Max(headMinLen, 0.0001f);
|
||||
}
|
||||
|
||||
private void InitLengthSystem()
|
||||
{
|
||||
// 没有 min/max 长度限制:初始长度只做一个“非负”保障
|
||||
float defaultLen = physicsSegmentLen * (Mathf.Max(minPhysicsNodes, 2) - 1);
|
||||
currentLength = (initialLength > 0f) ? initialLength : defaultLen;
|
||||
targetLength = currentLength;
|
||||
}
|
||||
|
||||
private void AllocateAndInitNodes()
|
||||
{
|
||||
// 若锚点存在:最小长度就是两锚点直线距离 + minSlack(防抖)
|
||||
if (startAnchor && endAnchor)
|
||||
{
|
||||
Log.Info($"rope name={gameObject.name} stretchScale={stretchScale}");
|
||||
float minFeasible = Vector3.Distance(startAnchor.position, endAnchor.position) + minSlack;
|
||||
currentLength = Mathf.Max(currentLength, minFeasible);
|
||||
targetLength = Mathf.Max(targetLength, minFeasible);
|
||||
}
|
||||
|
||||
physicsNodes = Mathf.Clamp(ComputeDesiredNodes(currentLength), 2, maxPhysicsNodes);
|
||||
pCurr = new Vector3[physicsNodes];
|
||||
pPrev = new Vector3[physicsNodes];
|
||||
|
||||
// 初始从起点往下排
|
||||
Vector3 start = startAnchor ? startAnchor.position : transform.position;
|
||||
Vector3 dir = Vector3.down;
|
||||
|
||||
for (int i = 0; i < physicsNodes; i++)
|
||||
{
|
||||
Vector3 pos = start + dir * (physicsSegmentLen * i);
|
||||
pCurr[i] = pos;
|
||||
pPrev[i] = pos;
|
||||
}
|
||||
|
||||
UpdateHeadRestLenFromCurrentLength();
|
||||
|
||||
if (startAnchor && endAnchor)
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private int ComputeDesiredNodes(float lengthMeters)
|
||||
{
|
||||
// nodes = floor(length/segLen)+1
|
||||
int desired = Mathf.FloorToInt(Mathf.Max(0f, lengthMeters) / physicsSegmentLen) + 1;
|
||||
desired = Mathf.Clamp(desired, minPhysicsNodes, maxPhysicsNodes);
|
||||
return desired;
|
||||
}
|
||||
|
||||
/// <summary>设置目标总长度(米)。不做最小/最大长度限制(最小可行由锚点距离决定)。</summary>
|
||||
public void SetTargetLength(float lengthMeters)
|
||||
{
|
||||
targetLength = Mathf.Max(0f, lengthMeters);
|
||||
}
|
||||
|
||||
/// <summary>增加/减少目标总长度(米)。正数放线,负数收线。</summary>
|
||||
public void AddTargetLength(float deltaMeters)
|
||||
{
|
||||
SetTargetLength(targetLength + deltaMeters);
|
||||
}
|
||||
|
||||
public float GetCurrentLength() => currentLength;
|
||||
public float GetTargetLength() => targetLength;
|
||||
|
||||
public float GetAnchorDistance()
|
||||
{
|
||||
if (startAnchor != null && endAnchor != null)
|
||||
{
|
||||
return Vector3.Distance(startAnchor.position, endAnchor.position);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private void FixedUpdate2()
|
||||
{
|
||||
if (!startAnchor || !endAnchor)
|
||||
return;
|
||||
|
||||
gravity.y = -gravityStrength;
|
||||
|
||||
UpdateLengthSmooth(); // 只保证 >= 锚点直线距离 + minSlack
|
||||
UpdateNodesFromLength(); // 只从头部增/减节点
|
||||
UpdateHeadRestLenFromCurrentLength(); // 第一段补余量 => 变化集中在头部
|
||||
|
||||
Simulate();
|
||||
|
||||
for (int it = 0; it < iterations; it++)
|
||||
{
|
||||
SolveDistanceConstraints_HeadOnly();
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
if (constrainToWater || constrainToGround)
|
||||
ConstrainToGroundAndWater();
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
DrawHighResLine();
|
||||
FixedUpdate2();
|
||||
}
|
||||
|
||||
private void UpdateLengthSmooth()
|
||||
{
|
||||
float anchorDist = Vector3.Distance(startAnchor.position, endAnchor.position);
|
||||
float minFeasible = anchorDist + minSlack;
|
||||
|
||||
// ✅ 最小长度 = 起点终点直线距离(+slack),最大不限制
|
||||
float desired = Mathf.Max(targetLength, minFeasible);
|
||||
|
||||
float prevLen = currentLength;
|
||||
|
||||
currentLength = Mathf.SmoothDamp(
|
||||
currentLength,
|
||||
desired,
|
||||
ref lengthSmoothVel,
|
||||
lengthSmoothTime,
|
||||
Mathf.Infinity,
|
||||
Time.fixedDeltaTime
|
||||
);
|
||||
|
||||
float lenDelta = Mathf.Abs(currentLength - prevLen);
|
||||
if (lenDelta > 1e-5f && lengthChangeVelocityKill > 0f && pPrev != null)
|
||||
{
|
||||
float kill = Mathf.Clamp01(lengthChangeVelocityKill);
|
||||
for (int i = 1; i < physicsNodes - 1; i++)
|
||||
pPrev[i] = Vector3.Lerp(pPrev[i], pCurr[i], kill);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
private void UpdateNodesFromLength()
|
||||
{
|
||||
rope.stretchingScale = stretchScale;
|
||||
int desired = ComputeDesiredNodes(currentLength);
|
||||
if (desired == physicsNodes) return;
|
||||
|
||||
while (physicsNodes < desired)
|
||||
AddNodeAtStart();
|
||||
|
||||
while (physicsNodes > desired)
|
||||
RemoveNodeAtStart();
|
||||
|
||||
RebuildRenderBufferIfNeeded();
|
||||
}
|
||||
|
||||
private void AddNodeAtStart()
|
||||
{
|
||||
int newCount = Mathf.Min(physicsNodes + 1, maxPhysicsNodes);
|
||||
if (newCount == physicsNodes) return;
|
||||
|
||||
Vector3[] newCurr = new Vector3[newCount];
|
||||
Vector3[] newPrev = new Vector3[newCount];
|
||||
|
||||
newCurr[0] = pCurr[0];
|
||||
newPrev[0] = pPrev[0];
|
||||
|
||||
for (int i = 2; i < newCount; i++)
|
||||
{
|
||||
newCurr[i] = pCurr[i - 1];
|
||||
newPrev[i] = pPrev[i - 1];
|
||||
}
|
||||
|
||||
Vector3 s = startAnchor.position;
|
||||
Vector3 dir = Vector3.down;
|
||||
|
||||
if (physicsNodes >= 2)
|
||||
{
|
||||
Vector3 toOld1 = (pCurr[1] - s);
|
||||
if (toOld1.sqrMagnitude > 1e-6f) dir = toOld1.normalized;
|
||||
}
|
||||
|
||||
Vector3 pos = s + dir * physicsSegmentLen;
|
||||
newCurr[1] = pos;
|
||||
newPrev[1] = pos;
|
||||
|
||||
pCurr = newCurr;
|
||||
pPrev = newPrev;
|
||||
physicsNodes = newCount;
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void RemoveNodeAtStart()
|
||||
{
|
||||
int newCount = Mathf.Max(physicsNodes - 1, 2);
|
||||
if (newCount == physicsNodes) return;
|
||||
|
||||
Vector3[] newCurr = new Vector3[newCount];
|
||||
Vector3[] newPrev = new Vector3[newCount];
|
||||
|
||||
newCurr[0] = pCurr[0];
|
||||
newPrev[0] = pPrev[0];
|
||||
|
||||
for (int i = 1; i < newCount - 1; i++)
|
||||
{
|
||||
newCurr[i] = pCurr[i + 1];
|
||||
newPrev[i] = pPrev[i + 1];
|
||||
}
|
||||
|
||||
newCurr[newCount - 1] = pCurr[physicsNodes - 1];
|
||||
newPrev[newCount - 1] = pPrev[physicsNodes - 1];
|
||||
|
||||
pCurr = newCurr;
|
||||
pPrev = newPrev;
|
||||
physicsNodes = newCount;
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void UpdateHeadRestLenFromCurrentLength()
|
||||
{
|
||||
int fixedSegCount = Mathf.Max(0, physicsNodes - 2);
|
||||
float baseLen = fixedSegCount * physicsSegmentLen;
|
||||
|
||||
headRestLen = currentLength - baseLen;
|
||||
|
||||
// 第一段允许在一个合理范围内变动(太长会像橡皮筋,太短会炸)
|
||||
headRestLen = Mathf.Clamp(headRestLen, headMinLen, physicsSegmentLen * 1.5f);
|
||||
}
|
||||
|
||||
private void Simulate()
|
||||
{
|
||||
float dt = Time.fixedDeltaTime;
|
||||
|
||||
for (int i = 0; i < physicsNodes; i++)
|
||||
{
|
||||
Vector3 v = (pCurr[i] - pPrev[i]) * velocityDampen;
|
||||
pPrev[i] = pCurr[i];
|
||||
|
||||
pCurr[i] += v;
|
||||
pCurr[i] += gravity * dt;
|
||||
}
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void LockAnchorsHard()
|
||||
{
|
||||
if (!startAnchor || !endAnchor || pCurr == null || pPrev == null || physicsNodes < 2) return;
|
||||
float dt = Time.fixedDeltaTime;
|
||||
Vector3 s = startAnchor.position;
|
||||
Vector3 e = endAnchor.position;
|
||||
|
||||
pCurr[0] = s;
|
||||
pPrev[0] = s - startAnchor.linearVelocity * dt;
|
||||
|
||||
int last = physicsNodes - 1;
|
||||
pCurr[last] = e;
|
||||
pPrev[last] = e - endAnchor.linearVelocity * dt;
|
||||
}
|
||||
|
||||
private void SolveDistanceConstraints_HeadOnly()
|
||||
{
|
||||
for (int i = 0; i < physicsNodes - 1; i++)
|
||||
{
|
||||
float rest = (i == 0) ? headRestLen : physicsSegmentLen;
|
||||
|
||||
Vector3 a = pCurr[i];
|
||||
Vector3 b = pCurr[i + 1];
|
||||
|
||||
Vector3 delta = b - a;
|
||||
float dist = delta.magnitude;
|
||||
if (dist < 1e-6f) continue;
|
||||
|
||||
float diff = (dist - rest) / dist;
|
||||
Vector3 corr = delta * diff * stiffness;
|
||||
|
||||
if (i != 0)
|
||||
pCurr[i] += corr * 0.5f;
|
||||
|
||||
if (i + 1 != physicsNodes - 1)
|
||||
pCurr[i + 1] -= corr * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
private void ConstrainToGroundAndWater()
|
||||
{
|
||||
for (int i = 1; i < physicsNodes - 1; i++)
|
||||
{
|
||||
Vector3 p = pCurr[i];
|
||||
|
||||
if (constrainToWater)
|
||||
{
|
||||
float minY = waterHeight + waterRadius;
|
||||
if (p.y < minY) p.y = minY;
|
||||
}
|
||||
|
||||
if (constrainToGround)
|
||||
{
|
||||
Vector3 origin = p + Vector3.up * groundCastHeight;
|
||||
if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCastDistance, groundMask,
|
||||
QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
float minY = hit.point.y + groundRadius;
|
||||
if (p.y < minY) p.y = minY;
|
||||
}
|
||||
}
|
||||
|
||||
pCurr[i] = p;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHighResLine()
|
||||
{
|
||||
if (pCurr == null || physicsNodes < 2) return;
|
||||
|
||||
RebuildRenderBufferIfNeeded();
|
||||
|
||||
lr.startWidth = lineWidth;
|
||||
lr.endWidth = lineWidth;
|
||||
|
||||
if (!smooth)
|
||||
{
|
||||
lr.positionCount = physicsNodes;
|
||||
lr.SetPositions(pCurr);
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (int seg = 0; seg < physicsNodes - 1; seg++)
|
||||
{
|
||||
Vector3 p0 = pCurr[Mathf.Max(seg - 1, 0)];
|
||||
Vector3 p1 = pCurr[seg];
|
||||
Vector3 p2 = pCurr[seg + 1];
|
||||
Vector3 p3 = pCurr[Mathf.Min(seg + 2, physicsNodes - 1)];
|
||||
|
||||
for (int s = 0; s < renderSubdivisions; s++)
|
||||
{
|
||||
float t = s / (float)renderSubdivisions;
|
||||
Vector3 pt = CatmullRom_XZ_LinearY(p0, p1, p2, p3, t);
|
||||
|
||||
// 如果水面约束开启:渲染点也夹一下,避免视觉上又穿回去
|
||||
if (constrainToWater)
|
||||
{
|
||||
float minY = waterHeight + waterRadius;
|
||||
if (pt.y < minY) pt.y = minY;
|
||||
}
|
||||
|
||||
rPoints[idx++] = pt;
|
||||
}
|
||||
}
|
||||
|
||||
rPoints[idx++] = pCurr[physicsNodes - 1];
|
||||
|
||||
lr.positionCount = idx;
|
||||
lr.SetPositions(rPoints);
|
||||
}
|
||||
|
||||
private void RebuildRenderBufferIfNeeded()
|
||||
{
|
||||
int targetCount = (physicsNodes - 1) * renderSubdivisions + 1;
|
||||
if (rPoints == null || rCountCached != targetCount)
|
||||
{
|
||||
rPoints = new Vector3[targetCount];
|
||||
rCountCached = targetCount;
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
||||
{
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
|
||||
return 0.5f * (
|
||||
(2f * p1) +
|
||||
(-p0 + p2) * t +
|
||||
(2f * p0 - 5f * p1 + 4f * p2 - p3) * t2 +
|
||||
(-p0 + 3f * p1 - 3f * p2 + p3) * t3
|
||||
);
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (pCurr == null) return;
|
||||
Gizmos.color = Color.yellow;
|
||||
for (int i = 0; i < pCurr.Length; i++)
|
||||
Gizmos.DrawSphere(pCurr[i], 0.01f);
|
||||
}
|
||||
|
||||
private static Vector3 CatmullRom_XZ_LinearY(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
||||
{
|
||||
// XZ 做 Catmull-Rom
|
||||
Vector3 cr = CatmullRom(p0, p1, p2, p3, t);
|
||||
|
||||
// Y 不做样条,改成线性(不会过冲)
|
||||
cr.y = Mathf.Lerp(p1.y, p2.y, t);
|
||||
|
||||
return cr;
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Obi;
|
||||
// using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FLine : FGearBase
|
||||
{
|
||||
[SerializeField] private ObiParticleAttachment startParticleAttachment;
|
||||
// [SerializeField] private ObiParticleAttachment startParticleAttachment;
|
||||
[SerializeField] private bool isLureConnect;
|
||||
[SerializeField] private RodLine rodLine;
|
||||
[SerializeField] private Rope fishingRope;
|
||||
@@ -31,7 +31,7 @@ namespace NBF
|
||||
protected override void OnInit()
|
||||
{
|
||||
var tipRb = Rod.Asset.LineConnectorRigidbody;
|
||||
startParticleAttachment.target = tipRb.transform;
|
||||
// startParticleAttachment.target = tipRb.transform;
|
||||
if (isLureConnect)
|
||||
{
|
||||
Lure.SetJoint(tipRb);
|
||||
@@ -39,6 +39,7 @@ namespace NBF
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.startAnchor = tipRb;
|
||||
Bobber.SetJoint(tipRb);
|
||||
Lure.SetJoint(Bobber.rbody);
|
||||
Lure.gameObject.SetActive(true);
|
||||
@@ -78,15 +79,15 @@ namespace NBF
|
||||
|
||||
public void EnableLineRenderers()
|
||||
{
|
||||
foreach (ObiRopeExtrudedRenderer item in GetComponentsInChildren<ObiRopeExtrudedRenderer>().ToList())
|
||||
{
|
||||
item.enabled = true;
|
||||
}
|
||||
// foreach (ObiRopeExtrudedRenderer item in GetComponentsInChildren<ObiRopeExtrudedRenderer>().ToList())
|
||||
// {
|
||||
// item.enabled = true;
|
||||
// }
|
||||
}
|
||||
|
||||
public void SetObiRopeStretch(float value)
|
||||
{
|
||||
fishingRope.LineLength_OnValueChanged(value);
|
||||
fishingRope.SetTargetLength(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,194 +1,194 @@
|
||||
using NBF;
|
||||
using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
public class FLineHandler : MonoBehaviour
|
||||
{
|
||||
public enum LineType
|
||||
{
|
||||
None = 0,
|
||||
OneSegment = 1,
|
||||
TwoSegment = 2,
|
||||
ThereSegment = 3
|
||||
}
|
||||
|
||||
public LineType lineType = LineType.TwoSegment;
|
||||
|
||||
// public ObiParticleAttachment startParticleAttachment;
|
||||
|
||||
public ObiRope obiRopeSegment_1;
|
||||
|
||||
public ObiRope obiRopeSegment_2;
|
||||
|
||||
public ObiRope obiRopeSegment_3;
|
||||
|
||||
public FixedLine LineConnector_0;
|
||||
|
||||
public SpringJoint LineConnector_1;
|
||||
|
||||
public SpringJoint LineConnector_2;
|
||||
|
||||
public SpringJoint LineConnector_3;
|
||||
|
||||
// [HideInInspector] public FFishingLine currentRodFishingLineComponent;
|
||||
|
||||
// public ObiParticleAttachment toRodConnector;
|
||||
|
||||
// public float PhisicsLineOut { get; set; }
|
||||
|
||||
public float ObiLineOut;
|
||||
|
||||
[HideInInspector] public Rigidbody EndLineRigidbody_0;
|
||||
|
||||
[HideInInspector] public Rigidbody EndLineRigidbody_1;
|
||||
|
||||
[HideInInspector] public Rigidbody EndLineRigidbody_2;
|
||||
|
||||
[HideInInspector] public Rigidbody EndLineRigidbody_3;
|
||||
|
||||
// public JointPinchController pinchController;
|
||||
|
||||
public FRod Rod;
|
||||
|
||||
private Transform waterPlane;
|
||||
|
||||
|
||||
public LineRenderer LineRenderer1;
|
||||
public LineRenderer LineRenderer2;
|
||||
|
||||
// public float ropeToHookDistance;
|
||||
|
||||
void Start()
|
||||
{
|
||||
ObiLineOut = obiRopeSegment_1.stretchingScale;
|
||||
if ((bool)LineConnector_0)
|
||||
{
|
||||
EndLineRigidbody_0 = LineConnector_0.GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
if ((bool)LineConnector_1)
|
||||
{
|
||||
EndLineRigidbody_1 = LineConnector_1.GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
if ((bool)LineConnector_2)
|
||||
{
|
||||
EndLineRigidbody_2 = LineConnector_2.GetComponent<Rigidbody>();
|
||||
// var fixedJoint = LineConnector_2.GetComponent<FixedJoint>();
|
||||
// pinchController = LineConnector_2.gameObject.AddComponent<JointPinchController>();
|
||||
}
|
||||
|
||||
if ((bool)LineConnector_3)
|
||||
{
|
||||
EndLineRigidbody_3 = LineConnector_3.GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
waterPlane = GameObject.FindGameObjectWithTag("Water").transform;
|
||||
|
||||
Debug.LogError($"rope.restLength={obiRopeSegment_1.restLength} LineConnector_1={LineConnector_1.maxDistance}");
|
||||
}
|
||||
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!Rod) return;
|
||||
|
||||
|
||||
// ropeToHookDistance = Vector3.Distance(toRodConnector.transform.position, LineConnector_1.transform.position);
|
||||
|
||||
ObiLineOut = 0.1f + Rod.lineLength;
|
||||
float target = (0f - Mathf.Clamp(Rod.linelenghtDiferent, -1f, 0f)) * 0.1f;
|
||||
if (Rod.linelenghtDiferent >= 0f)
|
||||
{
|
||||
obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
Time.smoothDeltaTime * (1f * Rod.linelenghtDiferent));
|
||||
}
|
||||
else
|
||||
{
|
||||
obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
Time.smoothDeltaTime * 0.1f);
|
||||
}
|
||||
|
||||
if (Rod.lineLength == 0f)
|
||||
{
|
||||
obiRopeSegment_1.stretchCompliance = 0f;
|
||||
}
|
||||
|
||||
if ((bool)obiRopeSegment_2)
|
||||
{
|
||||
if (!Rod.currentFish)
|
||||
{
|
||||
obiRopeSegment_2.stretchCompliance = obiRopeSegment_2.stretchingScale * 0.004f;
|
||||
}
|
||||
else
|
||||
{
|
||||
obiRopeSegment_2.stretchCompliance = 0f;
|
||||
}
|
||||
|
||||
//TODO:TEST
|
||||
obiRopeSegment_2.stretchingScale = 0.13F;
|
||||
}
|
||||
|
||||
obiRopeSegment_1.stretchingScale = ObiLineOut;
|
||||
obiRopeSegment_1.stretchingScale = 1;
|
||||
LineConnector_1.maxDistance = 0.1f + Rod.lineLength;
|
||||
if (Input.GetKey(KeyCode.E))
|
||||
{
|
||||
// var speed = 1;
|
||||
// obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// Debug.Log(obiRopeSegment_1.restLength);
|
||||
}
|
||||
|
||||
// var addLength = LineConnector_1.maxDistance - obiRopeSegment_1.restLength;
|
||||
// if (Mathf.Abs(addLength) > 0.001f)
|
||||
// {
|
||||
// obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// }
|
||||
|
||||
// if (!Mathf.Approximately(LineConnector_1.maxDistance, obiRopeSegment_1.restLength))
|
||||
// {
|
||||
// obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// }
|
||||
|
||||
// obiRopeCursor_1.pos
|
||||
|
||||
|
||||
// LineConnector_1.minDistance = LineConnector_1.maxDistance;
|
||||
}
|
||||
|
||||
|
||||
public void SetSegmentTwoLenght(float lenght)
|
||||
{
|
||||
LineConnector_2.maxDistance = lenght;
|
||||
// obiRopeCursor_2.ChangeLength(lenght);
|
||||
// LineConnector_2.minDistance = LineConnector_2.maxDistance;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
// BindRod();
|
||||
LineWaterDisplacement();
|
||||
}
|
||||
|
||||
private void BindRod()
|
||||
{
|
||||
if (!Rod || !Rod.Asset) return;
|
||||
LineConnector_0.transform.position = Rod.Asset.lineConnector.position;
|
||||
}
|
||||
|
||||
private void LineWaterDisplacement()
|
||||
{
|
||||
if (!waterPlane)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < obiRopeSegment_1.activeParticleCount; i++)
|
||||
{
|
||||
if (obiRopeSegment_1.GetParticlePosition(i).y < waterPlane.position.y)
|
||||
{
|
||||
// obiRopeSegment_1.AddForceParticle(i, Vector3.up * 10f, ForceMode.Acceleration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// using NBF;
|
||||
// using Obi;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// public class FLineHandler : MonoBehaviour
|
||||
// {
|
||||
// public enum LineType
|
||||
// {
|
||||
// None = 0,
|
||||
// OneSegment = 1,
|
||||
// TwoSegment = 2,
|
||||
// ThereSegment = 3
|
||||
// }
|
||||
//
|
||||
// public LineType lineType = LineType.TwoSegment;
|
||||
//
|
||||
// // public ObiParticleAttachment startParticleAttachment;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_1;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_2;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_3;
|
||||
//
|
||||
// public FixedLine LineConnector_0;
|
||||
//
|
||||
// public SpringJoint LineConnector_1;
|
||||
//
|
||||
// public SpringJoint LineConnector_2;
|
||||
//
|
||||
// public SpringJoint LineConnector_3;
|
||||
//
|
||||
// // [HideInInspector] public FFishingLine currentRodFishingLineComponent;
|
||||
//
|
||||
// // public ObiParticleAttachment toRodConnector;
|
||||
//
|
||||
// // public float PhisicsLineOut { get; set; }
|
||||
//
|
||||
// public float ObiLineOut;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_0;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_1;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_2;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_3;
|
||||
//
|
||||
// // public JointPinchController pinchController;
|
||||
//
|
||||
// public FRod Rod;
|
||||
//
|
||||
// private Transform waterPlane;
|
||||
//
|
||||
//
|
||||
// public LineRenderer LineRenderer1;
|
||||
// public LineRenderer LineRenderer2;
|
||||
//
|
||||
// // public float ropeToHookDistance;
|
||||
//
|
||||
// void Start()
|
||||
// {
|
||||
// ObiLineOut = obiRopeSegment_1.stretchingScale;
|
||||
// if ((bool)LineConnector_0)
|
||||
// {
|
||||
// EndLineRigidbody_0 = LineConnector_0.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_1)
|
||||
// {
|
||||
// EndLineRigidbody_1 = LineConnector_1.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_2)
|
||||
// {
|
||||
// EndLineRigidbody_2 = LineConnector_2.GetComponent<Rigidbody>();
|
||||
// // var fixedJoint = LineConnector_2.GetComponent<FixedJoint>();
|
||||
// // pinchController = LineConnector_2.gameObject.AddComponent<JointPinchController>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_3)
|
||||
// {
|
||||
// EndLineRigidbody_3 = LineConnector_3.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// waterPlane = GameObject.FindGameObjectWithTag("Water").transform;
|
||||
//
|
||||
// Debug.LogError($"rope.restLength={obiRopeSegment_1.restLength} LineConnector_1={LineConnector_1.maxDistance}");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void Update()
|
||||
// {
|
||||
// if (!Rod) return;
|
||||
//
|
||||
//
|
||||
// // ropeToHookDistance = Vector3.Distance(toRodConnector.transform.position, LineConnector_1.transform.position);
|
||||
//
|
||||
// ObiLineOut = 0.1f + Rod.lineLength;
|
||||
// float target = (0f - Mathf.Clamp(Rod.linelenghtDiferent, -1f, 0f)) * 0.1f;
|
||||
// if (Rod.linelenghtDiferent >= 0f)
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
// Time.smoothDeltaTime * (1f * Rod.linelenghtDiferent));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
// Time.smoothDeltaTime * 0.1f);
|
||||
// }
|
||||
//
|
||||
// if (Rod.lineLength == 0f)
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = 0f;
|
||||
// }
|
||||
//
|
||||
// if ((bool)obiRopeSegment_2)
|
||||
// {
|
||||
// if (!Rod.currentFish)
|
||||
// {
|
||||
// obiRopeSegment_2.stretchCompliance = obiRopeSegment_2.stretchingScale * 0.004f;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// obiRopeSegment_2.stretchCompliance = 0f;
|
||||
// }
|
||||
//
|
||||
// //TODO:TEST
|
||||
// obiRopeSegment_2.stretchingScale = 0.13F;
|
||||
// }
|
||||
//
|
||||
// obiRopeSegment_1.stretchingScale = ObiLineOut;
|
||||
// obiRopeSegment_1.stretchingScale = 1;
|
||||
// LineConnector_1.maxDistance = 0.1f + Rod.lineLength;
|
||||
// if (Input.GetKey(KeyCode.E))
|
||||
// {
|
||||
// // var speed = 1;
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // Debug.Log(obiRopeSegment_1.restLength);
|
||||
// }
|
||||
//
|
||||
// // var addLength = LineConnector_1.maxDistance - obiRopeSegment_1.restLength;
|
||||
// // if (Mathf.Abs(addLength) > 0.001f)
|
||||
// // {
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // }
|
||||
//
|
||||
// // if (!Mathf.Approximately(LineConnector_1.maxDistance, obiRopeSegment_1.restLength))
|
||||
// // {
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // }
|
||||
//
|
||||
// // obiRopeCursor_1.pos
|
||||
//
|
||||
//
|
||||
// // LineConnector_1.minDistance = LineConnector_1.maxDistance;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void SetSegmentTwoLenght(float lenght)
|
||||
// {
|
||||
// LineConnector_2.maxDistance = lenght;
|
||||
// // obiRopeCursor_2.ChangeLength(lenght);
|
||||
// // LineConnector_2.minDistance = LineConnector_2.maxDistance;
|
||||
// }
|
||||
//
|
||||
// private void FixedUpdate()
|
||||
// {
|
||||
// // BindRod();
|
||||
// LineWaterDisplacement();
|
||||
// }
|
||||
//
|
||||
// private void BindRod()
|
||||
// {
|
||||
// if (!Rod || !Rod.Asset) return;
|
||||
// LineConnector_0.transform.position = Rod.Asset.lineConnector.position;
|
||||
// }
|
||||
//
|
||||
// private void LineWaterDisplacement()
|
||||
// {
|
||||
// if (!waterPlane)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// for (int i = 0; i < obiRopeSegment_1.activeParticleCount; i++)
|
||||
// {
|
||||
// if (obiRopeSegment_1.GetParticlePosition(i).y < waterPlane.position.y)
|
||||
// {
|
||||
// // obiRopeSegment_1.AddForceParticle(i, Vector3.up * 10f, ForceMode.Acceleration);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using NBC.Asset;
|
||||
using NBF.Utils;
|
||||
using Obi;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
@@ -295,7 +294,9 @@ namespace NBF
|
||||
Line.transform.position = Asset.lineConnector.position;
|
||||
Line.Init(this.Player, this);
|
||||
|
||||
var obiSolver = solver.GetComponent<ObiSolver>();
|
||||
// var obiSolver = solver.GetComponent<ObiSolver>();
|
||||
// obiSolver.parameters.ambientWind = Vector3.zero;
|
||||
// obiSolver.wind.
|
||||
// obiSolver.simulateWhenInvisible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47fc822e51a6b074bb4b6bd67e69a457
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,176 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
public class Bezier
|
||||
{
|
||||
private Vector3[] knots;
|
||||
|
||||
private Vector3[] firstControlPts;
|
||||
|
||||
private Vector3[] secondControlPts;
|
||||
|
||||
private int lastIndex = 1;
|
||||
|
||||
private float lengthCovered;
|
||||
|
||||
private float indexedLength;
|
||||
|
||||
private float totalLength;
|
||||
|
||||
public Bezier(List<PosOri> points)
|
||||
{
|
||||
Vector3[] array = new Vector3[points.Count];
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
array[i] = points[i].pos;
|
||||
}
|
||||
init(array);
|
||||
}
|
||||
|
||||
public Bezier(Vector3[] points)
|
||||
{
|
||||
init(points);
|
||||
}
|
||||
|
||||
private void init(Vector3[] points)
|
||||
{
|
||||
knots = new Vector3[points.Length];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
knots[i] = points[i];
|
||||
if (i != 0)
|
||||
{
|
||||
totalLength += (knots[i] - knots[i - 1]).magnitude;
|
||||
}
|
||||
}
|
||||
GetCurveControlPoints(knots, out firstControlPts, out secondControlPts);
|
||||
indexedLength = (knots[1] - knots[0]).magnitude;
|
||||
}
|
||||
|
||||
public float TotalLength()
|
||||
{
|
||||
return totalLength;
|
||||
}
|
||||
|
||||
public PosOri getNext(float deltaLen)
|
||||
{
|
||||
return new PosOri(getNextPos(deltaLen), Quaternion.identity);
|
||||
}
|
||||
|
||||
public Vector3 getNextPos(float deltaLen)
|
||||
{
|
||||
bool flag = false;
|
||||
float num = indexedLength;
|
||||
float num2 = indexedLength;
|
||||
while (!flag)
|
||||
{
|
||||
num = indexedLength;
|
||||
num2 = indexedLength - (knots[lastIndex] - knots[lastIndex - 1]).magnitude;
|
||||
if (lengthCovered + deltaLen > num)
|
||||
{
|
||||
lastIndex++;
|
||||
if (lastIndex == knots.Length)
|
||||
{
|
||||
flag = true;
|
||||
deltaLen = num - lengthCovered;
|
||||
lastIndex = knots.Length - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
indexedLength += (knots[lastIndex] - knots[lastIndex - 1]).magnitude;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
float num3 = (lengthCovered + deltaLen - num2) / (num - num2);
|
||||
Vector3 result = (float)Math.Pow(1f - num3, 3.0) * knots[lastIndex - 1] + 3f * (float)Math.Pow(1f - num3, 2.0) * num3 * firstControlPts[lastIndex - 1] + 3f * (1f - num3) * num3 * num3 * secondControlPts[lastIndex - 1] + num3 * num3 * num3 * knots[lastIndex];
|
||||
lengthCovered += deltaLen;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void GetCurveControlPoints(Vector3[] knots, out Vector3[] firstControlPoints, out Vector3[] secondControlPoints)
|
||||
{
|
||||
if (knots == null)
|
||||
{
|
||||
throw new ArgumentNullException("knots");
|
||||
}
|
||||
int num = knots.Length - 1;
|
||||
if (num < 1)
|
||||
{
|
||||
throw new ArgumentException("At least two knot points required", "knots");
|
||||
}
|
||||
if (num == 1)
|
||||
{
|
||||
firstControlPoints = new Vector3[1];
|
||||
firstControlPoints[0].x = (2f * knots[0].x + knots[1].x) / 3f;
|
||||
firstControlPoints[0].y = (2f * knots[0].y + knots[1].y) / 3f;
|
||||
firstControlPoints[0].z = (2f * knots[0].z + knots[1].z) / 3f;
|
||||
secondControlPoints = new Vector3[1];
|
||||
secondControlPoints[0].x = 2f * firstControlPoints[0].x - knots[0].x;
|
||||
secondControlPoints[0].y = 2f * firstControlPoints[0].y - knots[0].y;
|
||||
secondControlPoints[0].z = 2f * firstControlPoints[0].z - knots[0].z;
|
||||
return;
|
||||
}
|
||||
float[] array = new float[num];
|
||||
for (int i = 1; i < num - 1; i++)
|
||||
{
|
||||
array[i] = 4f * knots[i].x + 2f * knots[i + 1].x;
|
||||
}
|
||||
array[0] = knots[0].x + 2f * knots[1].x;
|
||||
array[num - 1] = (8f * knots[num - 1].x + knots[num].x) / 2f;
|
||||
float[] firstControlPoints2 = GetFirstControlPoints(array);
|
||||
for (int j = 1; j < num - 1; j++)
|
||||
{
|
||||
array[j] = 4f * knots[j].y + 2f * knots[j + 1].y;
|
||||
}
|
||||
array[0] = knots[0].y + 2f * knots[1].y;
|
||||
array[num - 1] = (8f * knots[num - 1].y + knots[num].y) / 2f;
|
||||
float[] firstControlPoints3 = GetFirstControlPoints(array);
|
||||
for (int k = 1; k < num - 1; k++)
|
||||
{
|
||||
array[k] = 4f * knots[k].z + 2f * knots[k + 1].z;
|
||||
}
|
||||
array[0] = knots[0].z + 2f * knots[1].z;
|
||||
array[num - 1] = (8f * knots[num - 1].z + knots[num].z) / 2f;
|
||||
float[] firstControlPoints4 = GetFirstControlPoints(array);
|
||||
firstControlPoints = new Vector3[num];
|
||||
secondControlPoints = new Vector3[num];
|
||||
for (int l = 0; l < num; l++)
|
||||
{
|
||||
firstControlPoints[l] = new Vector3(firstControlPoints2[l], firstControlPoints3[l], firstControlPoints4[l]);
|
||||
if (l < num - 1)
|
||||
{
|
||||
secondControlPoints[l] = new Vector3(2f * knots[l + 1].x - firstControlPoints2[l + 1], 2f * knots[l + 1].y - firstControlPoints3[l + 1], 2f * knots[l + 1].z - firstControlPoints4[l + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
secondControlPoints[l] = new Vector3((knots[num].x + firstControlPoints2[num - 1]) / 2f, (knots[num].y + firstControlPoints3[num - 1]) / 2f, (knots[num].z + firstControlPoints4[num - 1]) / 2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float[] GetFirstControlPoints(float[] rhs)
|
||||
{
|
||||
int num = rhs.Length;
|
||||
float[] array = new float[num];
|
||||
float[] array2 = new float[num];
|
||||
float num2 = 2f;
|
||||
array[0] = rhs[0] / num2;
|
||||
for (int i = 1; i < num; i++)
|
||||
{
|
||||
array2[i] = 1f / num2;
|
||||
num2 = ((i >= num - 1) ? 3.5f : 4f) - array2[i];
|
||||
array[i] = (rhs[i] - array[i - 1]) / num2;
|
||||
}
|
||||
for (int j = 1; j < num; j++)
|
||||
{
|
||||
array[num - j - 1] -= array2[num - j] * array[num - j];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c65206b6e7283d4396bb4c47f4ddf88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,18 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
internal class BoneSegment : Segment
|
||||
{
|
||||
public GameObject bone;
|
||||
|
||||
public Matrix4x4 initTransform;
|
||||
|
||||
public BoneSegment(string name, float len, Vector3 pos, Quaternion q, SegmentPropertiesBase segProperties, Rope r, GameObject b)
|
||||
: base(name, len, pos, q, segProperties, r)
|
||||
{
|
||||
bone = b;
|
||||
initTransform = seg.transform.worldToLocalMatrix * bone.transform.localToWorldMatrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 265d31d4ce3243c4cadb3a8ba8c80dae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class ControlPoint
|
||||
{
|
||||
[Tooltip("Optional: Object")]
|
||||
public GameObject obj;
|
||||
|
||||
[Tooltip("Position through which rope will pass... If Object is specified then it is the local to the object otherwise it is global position")]
|
||||
public Vector3 localPos;
|
||||
|
||||
[Range(1f, 5f)]
|
||||
[Tooltip("SlackFraction: How much of the rope length should be created between two control points... If it is more than 1 then a catenary is formed between the control points")]
|
||||
public float slackFraction;
|
||||
|
||||
[Tooltip("Specify whether it is attached to the control point or not")]
|
||||
public bool attached;
|
||||
|
||||
public ControlPoint()
|
||||
{
|
||||
obj = null;
|
||||
slackFraction = 1f;
|
||||
attached = true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ((!(obj != null)) ? "Object: null" : ("Object:" + obj.ToString())) + ", Position: " + localPos.ToString() + ", SlackFraction: " + slackFraction + ", Attached: " + attached;
|
||||
}
|
||||
|
||||
public bool compare(ControlPoint rhs)
|
||||
{
|
||||
if (obj != rhs.obj || localPos != rhs.localPos || slackFraction != rhs.slackFraction || attached != rhs.attached)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ControlPoint clone()
|
||||
{
|
||||
ControlPoint controlPoint = new ControlPoint();
|
||||
controlPoint.obj = obj;
|
||||
controlPoint.localPos = localPos;
|
||||
controlPoint.slackFraction = slackFraction;
|
||||
controlPoint.attached = attached;
|
||||
return controlPoint;
|
||||
}
|
||||
|
||||
public Vector3 globalPos(Rope rope)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return obj.transform.TransformPoint(localPos);
|
||||
}
|
||||
return rope.transform.TransformPoint(localPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c3919bd67247ecf47ac8b5970b70372
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,142 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
public class Joint
|
||||
{
|
||||
public UnityEngine.Joint joint;
|
||||
|
||||
public Joint(Segment seg1, Segment seg2, JointProperties prop, SegmentPropertiesBase segProperties, Quaternion twistOffset)
|
||||
{
|
||||
if (seg2 == null)
|
||||
{
|
||||
}
|
||||
seg2.seg.transform.rotation = seg2.seg.transform.rotation * twistOffset;
|
||||
switch (prop.type)
|
||||
{
|
||||
case JointProperties.Type.HINGE_JOINT:
|
||||
{
|
||||
HingeJoint hingeJoint = seg1.seg.AddComponent<HingeJoint>();
|
||||
hingeJoint.autoConfigureConnectedAnchor = false;
|
||||
joint = hingeJoint;
|
||||
JointLimits limits = new JointLimits
|
||||
{
|
||||
min = 0f - prop.swingLimitDeg,
|
||||
max = prop.swingLimitDeg
|
||||
};
|
||||
joint.axis = new Vector3(0f, 0f, 1f);
|
||||
hingeJoint.limits = limits;
|
||||
break;
|
||||
}
|
||||
case JointProperties.Type.CONFIGURABLE_JOINT:
|
||||
{
|
||||
ConfigurableJoint configurableJoint = seg1.seg.AddComponent<ConfigurableJoint>();
|
||||
configurableJoint.enableCollision = false;
|
||||
configurableJoint.xMotion = ConfigurableJointMotion.Locked;
|
||||
configurableJoint.yMotion = ConfigurableJointMotion.Locked;
|
||||
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
|
||||
configurableJoint.angularXMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.angularYMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.angularZMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.autoConfigureConnectedAnchor = false;
|
||||
configurableJoint.lowAngularXLimit = new SoftJointLimit
|
||||
{
|
||||
limit = 0f - prop.twistLimitDeg
|
||||
};
|
||||
configurableJoint.highAngularXLimit = new SoftJointLimit
|
||||
{
|
||||
limit = prop.twistLimitDeg
|
||||
};
|
||||
configurableJoint.projectionMode = JointProjectionMode.PositionAndRotation;
|
||||
configurableJoint.projectionDistance = prop.projectionDistance;
|
||||
SoftJointLimit softJointLimit = new SoftJointLimit
|
||||
{
|
||||
limit = prop.swingLimitDeg
|
||||
};
|
||||
configurableJoint.angularYLimit = softJointLimit;
|
||||
configurableJoint.angularZLimit = softJointLimit;
|
||||
joint = configurableJoint;
|
||||
joint.axis = new Vector3(0f, 1f, 0f);
|
||||
if (prop.breakingForce != 0f)
|
||||
{
|
||||
configurableJoint.breakForce = prop.breakingForce;
|
||||
}
|
||||
configurableJoint.enablePreprocessing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segProperties is SegmentPropertiesCylinder)
|
||||
{
|
||||
joint.anchor = new Vector3(0f, 1f - prop.offsetScale, 0f);
|
||||
joint.connectedAnchor = new Vector3(0f, -1f + prop.offsetScale, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
joint.anchor = new Vector3(0f, (1f - prop.offsetScale) / 2f, 0f);
|
||||
joint.connectedAnchor = new Vector3(0f, (-1f + prop.offsetScale) / 2f, 0f);
|
||||
}
|
||||
joint.connectedBody = seg2.seg.GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
public Joint(GameObject seg1, GameObject seg2, Vector3 vGlobalAnchor, Vector3 vGlobalAxis, JointProperties prop, Rope r, int jtPos)
|
||||
{
|
||||
ConfigurableJoint configurableJoint = seg1.AddComponent<ConfigurableJoint>();
|
||||
configurableJoint.enableCollision = false;
|
||||
configurableJoint.xMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.yMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.zMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.angularXMotion = ConfigurableJointMotion.Limited;
|
||||
configurableJoint.angularYMotion = ConfigurableJointMotion.Free;
|
||||
configurableJoint.angularZMotion = ConfigurableJointMotion.Free;
|
||||
configurableJoint.anchor = seg1.transform.InverseTransformPoint(vGlobalAnchor);
|
||||
configurableJoint.axis = seg1.transform.InverseTransformDirection(vGlobalAxis);
|
||||
if (seg2 != null)
|
||||
{
|
||||
configurableJoint.connectedBody = seg2.GetComponent<Rigidbody>();
|
||||
}
|
||||
SoftJointLimit linearLimit = new SoftJointLimit
|
||||
{
|
||||
limit = 0.01f
|
||||
};
|
||||
SoftJointLimitSpring linearLimitSpring = default(SoftJointLimitSpring);
|
||||
switch (jtPos)
|
||||
{
|
||||
case 0:
|
||||
linearLimitSpring = r.getStartJtSpring();
|
||||
break;
|
||||
case 1:
|
||||
linearLimitSpring = r.getEndJtSpring();
|
||||
break;
|
||||
default:
|
||||
{
|
||||
float damper = (linearLimitSpring.spring = 0f);
|
||||
linearLimitSpring.damper = damper;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (linearLimitSpring.spring == 0f)
|
||||
{
|
||||
linearLimit.limit = 0f;
|
||||
}
|
||||
configurableJoint.linearLimitSpring = linearLimitSpring;
|
||||
configurableJoint.linearLimit = linearLimit;
|
||||
configurableJoint.projectionMode = JointProjectionMode.PositionAndRotation;
|
||||
configurableJoint.projectionDistance = prop.projectionDistanceFirst;
|
||||
configurableJoint.lowAngularXLimit = new SoftJointLimit
|
||||
{
|
||||
limit = 0f - prop.twistLimitDeg
|
||||
};
|
||||
configurableJoint.highAngularXLimit = new SoftJointLimit
|
||||
{
|
||||
limit = prop.twistLimitDeg
|
||||
};
|
||||
if (prop.breakingForce != 0f)
|
||||
{
|
||||
configurableJoint.breakForce = prop.breakingForce;
|
||||
}
|
||||
joint = configurableJoint;
|
||||
configurableJoint.autoConfigureConnectedAnchor = false;
|
||||
configurableJoint.enablePreprocessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e680fa725d3066a2472a42dc6f1ba88
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class JointProperties
|
||||
{
|
||||
[Serializable]
|
||||
public enum Type
|
||||
{
|
||||
CONFIGURABLE_JOINT = 0,
|
||||
HINGE_JOINT = 1
|
||||
}
|
||||
|
||||
public Type type;
|
||||
|
||||
[Range(0f, 180f)]
|
||||
public float twistLimitDeg;
|
||||
|
||||
[Range(0f, 180f)]
|
||||
public float swingLimitDeg;
|
||||
|
||||
[Range(0f, 0.5f)]
|
||||
public float offsetScale;
|
||||
|
||||
[Range(0f, 90f)]
|
||||
public float twistOffsetDeg;
|
||||
|
||||
public float breakingForce;
|
||||
|
||||
public float projectionDistance;
|
||||
|
||||
public float projectionDistanceFirst;
|
||||
|
||||
public JointProperties()
|
||||
{
|
||||
type = Type.CONFIGURABLE_JOINT;
|
||||
twistLimitDeg = 10f;
|
||||
swingLimitDeg = 50f;
|
||||
offsetScale = 0f;
|
||||
twistOffsetDeg = 0f;
|
||||
breakingForce = 0f;
|
||||
projectionDistance = 0.1f;
|
||||
projectionDistanceFirst = 0.001f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0a2d569b86ab9e4f96ae4345b0340de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class LinkMesh
|
||||
{
|
||||
[HideInInspector]
|
||||
public Mesh modifiedMesh;
|
||||
|
||||
[HideInInspector]
|
||||
public Matrix4x4 transform;
|
||||
|
||||
[HideInInspector]
|
||||
public Mesh defaultMesh;
|
||||
|
||||
[HideInInspector]
|
||||
public Material defaultMeshMaterial;
|
||||
|
||||
[HideInInspector]
|
||||
public Matrix4x4 defaultTransform;
|
||||
|
||||
public Mesh mesh;
|
||||
|
||||
public Material meshMaterial;
|
||||
|
||||
public Vector3 position;
|
||||
|
||||
public Vector3 rotation;
|
||||
|
||||
public Vector3 scale;
|
||||
|
||||
public LinkMesh()
|
||||
{
|
||||
mesh = null;
|
||||
position = new Vector3(0f, 0f, 0f);
|
||||
rotation = new Vector3(0f, 0f, 0f);
|
||||
scale = new Vector3(1f, 1f, 1f);
|
||||
defaultTransform = default(Matrix4x4);
|
||||
defaultTransform.SetTRS(position, Quaternion.Euler(rotation), scale);
|
||||
transform = default(Matrix4x4);
|
||||
transform.SetTRS(position, Quaternion.Euler(rotation), scale);
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if (mesh == null)
|
||||
{
|
||||
mesh = defaultMesh;
|
||||
transform = defaultTransform;
|
||||
Quaternion rot;
|
||||
Utility.MatrixToTRS(transform, out position, out rot, out scale);
|
||||
rotation = rot.eulerAngles;
|
||||
}
|
||||
if (mesh != null)
|
||||
{
|
||||
modifiedMesh = UnityEngine.Object.Instantiate(mesh);
|
||||
}
|
||||
if (modifiedMesh != null)
|
||||
{
|
||||
transform.SetTRS(position, Quaternion.Euler(rotation), scale);
|
||||
ScaleMesh();
|
||||
}
|
||||
}
|
||||
|
||||
public void ScaleMesh()
|
||||
{
|
||||
Vector3[] vertices = modifiedMesh.vertices;
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
Vector3 point = vertices[i];
|
||||
point = transform.MultiplyPoint(point);
|
||||
vertices[i] = point;
|
||||
}
|
||||
modifiedMesh.vertices = vertices;
|
||||
}
|
||||
|
||||
public Mesh getMesh()
|
||||
{
|
||||
return modifiedMesh;
|
||||
}
|
||||
|
||||
public Material getMaterial()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88218b6dac3a1d87d3867523046c804d
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class PosOri
|
||||
{
|
||||
public Vector3 pos;
|
||||
|
||||
public Quaternion rot;
|
||||
|
||||
public PosOri(Vector3 p, Quaternion q)
|
||||
{
|
||||
pos = p;
|
||||
rot = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0da6209e0750de846b70cb074a64d5bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d8b3d7293da4ed8736330164944ddd3
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,26 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
internal class SCapsulePos
|
||||
{
|
||||
public Vector3 vPos;
|
||||
|
||||
public Vector3 vDir;
|
||||
|
||||
public Vector3 vPrevPos;
|
||||
|
||||
public Vector3 vPrevDir;
|
||||
|
||||
public float fLen;
|
||||
|
||||
public SCapsulePos()
|
||||
{
|
||||
vPos = new Vector3(0f, 0f, 0f);
|
||||
vDir = new Vector3(0f, 0f, 0f);
|
||||
vPrevPos = new Vector3(0f, 0f, 0f);
|
||||
vPrevDir = new Vector3(0f, 0f, 0f);
|
||||
fLen = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3881b5b71590e5142bc7910fe64dbc69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,58 +0,0 @@
|
||||
// using UltimateWater;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
public class Segment
|
||||
{
|
||||
public GameObject seg;
|
||||
|
||||
public Rigidbody body;
|
||||
|
||||
public Joint prev;
|
||||
|
||||
public Joint next;
|
||||
|
||||
public CapsuleCollider capsuleCollider;
|
||||
|
||||
public MeshFilter meshFilter;
|
||||
|
||||
public MeshRenderer meshRenderer;
|
||||
|
||||
// public WaterInteractive waterInteractive;
|
||||
|
||||
public Segment(string name, float len, Vector3 pos, Quaternion q, SegmentPropertiesBase segProperties, Rope r)
|
||||
{
|
||||
SegmentPropertiesCylinder segmentPropertiesCylinder = (SegmentPropertiesCylinder)segProperties;
|
||||
float radius = segmentPropertiesCylinder.radius;
|
||||
seg = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||||
capsuleCollider = seg.GetComponent<CapsuleCollider>();
|
||||
meshFilter = seg.GetComponent<MeshFilter>();
|
||||
meshRenderer = seg.GetComponent<MeshRenderer>();
|
||||
body = seg.AddComponent<Rigidbody>();
|
||||
capsuleCollider.sharedMaterial = r.ropeMaterial;
|
||||
capsuleCollider.enabled = r.useColliders;
|
||||
r.lstComponentsCreated.Add(seg);
|
||||
seg.hideFlags = (r.HideChildren ? HideFlags.HideInHierarchy : HideFlags.None);
|
||||
meshRenderer.enabled = true;
|
||||
r.linkMesh.defaultMesh = meshFilter.sharedMesh;
|
||||
r.linkMesh.defaultMeshMaterial = meshRenderer.sharedMaterial;
|
||||
r.linkMesh.defaultTransform = Matrix4x4.identity;
|
||||
if (r.linkMesh.getMesh() != null)
|
||||
{
|
||||
meshFilter.sharedMesh = r.linkMesh.getMesh();
|
||||
meshRenderer.sharedMaterial = r.linkMesh.meshMaterial;
|
||||
}
|
||||
seg.name = name;
|
||||
seg.transform.localScale = new Vector3(radius * 2f, len / 2f, radius * 2f);
|
||||
seg.transform.localPosition = pos;
|
||||
seg.transform.localRotation = q;
|
||||
body.maxAngularVelocity = 1f;
|
||||
body.angularDamping = segmentPropertiesCylinder.angularDamping;
|
||||
body.linearDamping = segmentPropertiesCylinder.linearDamping;
|
||||
body.mass = segmentPropertiesCylinder.massPerUnitLength * segmentPropertiesCylinder.length;
|
||||
body.solverIterations = segmentPropertiesCylinder.solverCount;
|
||||
body.isKinematic = r.kinematic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b876b665f2164469858aa78787017d4d
|
||||
timeCreated: 1771646563
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class SegmentProperties
|
||||
{
|
||||
[Serializable]
|
||||
public enum Type
|
||||
{
|
||||
CYLINDER = 0,
|
||||
BOX = 1
|
||||
}
|
||||
|
||||
public Type type;
|
||||
|
||||
public SegmentPropertiesBase properties;
|
||||
|
||||
public SegmentProperties()
|
||||
{
|
||||
properties = new SegmentPropertiesCylinder();
|
||||
type = Type.CYLINDER;
|
||||
}
|
||||
|
||||
public void setType(Type t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case Type.BOX:
|
||||
properties = new SegmentPropertiesBox();
|
||||
break;
|
||||
case Type.CYLINDER:
|
||||
properties = new SegmentPropertiesCylinder();
|
||||
break;
|
||||
}
|
||||
type = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4cc846e1c08f18140bdf8f716aff9d45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class SegmentPropertiesBase
|
||||
{
|
||||
public float massPerUnitLength;
|
||||
|
||||
public int solverCount;
|
||||
|
||||
public float length;
|
||||
|
||||
public float linearDamping;
|
||||
|
||||
public float angularDamping;
|
||||
|
||||
public SegmentPropertiesBase()
|
||||
{
|
||||
massPerUnitLength = 10f;
|
||||
solverCount = 255;
|
||||
length = 1f;
|
||||
linearDamping = 0.01f;
|
||||
angularDamping = 0.01f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: adbcbbf68b6c67b4a919921e96801c2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class SegmentPropertiesBox : SegmentPropertiesBase
|
||||
{
|
||||
public float width;
|
||||
|
||||
public float height;
|
||||
|
||||
public SegmentPropertiesBox()
|
||||
{
|
||||
length = 1f;
|
||||
width = 0.05f;
|
||||
height = 0.2f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 278f3471b842200469e66a88287e903f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class SegmentPropertiesCylinder : SegmentPropertiesBase
|
||||
{
|
||||
public float radius;
|
||||
|
||||
public SegmentPropertiesCylinder()
|
||||
{
|
||||
length = 1f;
|
||||
radius = 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1876d7df821e9ca46a62254142001c6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
[Serializable]
|
||||
public class SerializedSoftJointLimitSpring
|
||||
{
|
||||
public float spring = 30000f;
|
||||
|
||||
public float damper = 30000f;
|
||||
|
||||
public SerializedSoftJointLimitSpring()
|
||||
{
|
||||
spring = 30000f;
|
||||
damper = 30000f;
|
||||
}
|
||||
|
||||
private SerializedSoftJointLimitSpring(SoftJointLimitSpring c)
|
||||
{
|
||||
damper = c.damper;
|
||||
spring = c.spring;
|
||||
}
|
||||
|
||||
public static implicit operator SoftJointLimitSpring(SerializedSoftJointLimitSpring c)
|
||||
{
|
||||
return new SoftJointLimitSpring
|
||||
{
|
||||
spring = c.spring,
|
||||
damper = c.damper
|
||||
};
|
||||
}
|
||||
|
||||
public static explicit operator SerializedSoftJointLimitSpring(SoftJointLimitSpring c)
|
||||
{
|
||||
return new SerializedSoftJointLimitSpring(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9f687b18e562c31f90c28822c0f641d
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,272 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
public class Utility
|
||||
{
|
||||
public class Calc
|
||||
{
|
||||
private float r_length;
|
||||
|
||||
private float h;
|
||||
|
||||
private float d;
|
||||
|
||||
public Calc(float r_, float h_, float d_)
|
||||
{
|
||||
r_length = r_;
|
||||
h = h_;
|
||||
d = d_;
|
||||
}
|
||||
|
||||
public float g(float s)
|
||||
{
|
||||
return (float)(2.0 * Math.Sinh(s * d / 2f) / (double)s - Math.Sqrt(r_length * r_length - h * h));
|
||||
}
|
||||
|
||||
public float dg(float s)
|
||||
{
|
||||
return (float)(2.0 * Math.Cosh(s * d / 2f) * (double)d / (double)(2f * s) - 2.0 * Math.Sinh(s * d / 2f) / (double)(s * s));
|
||||
}
|
||||
}
|
||||
|
||||
private const float DEG_2_RAD = 0.017453277f;
|
||||
|
||||
private const float RAD_2_DEG = 57.29583f;
|
||||
|
||||
public static void MatrixToTRS(Matrix4x4 mat, out Vector3 pos, out Quaternion rot, out Vector3 scale)
|
||||
{
|
||||
pos = mat.GetColumn(3);
|
||||
rot = Quaternion.LookRotation(mat.GetColumn(2), mat.GetColumn(1));
|
||||
scale = new Vector3(mat.GetColumn(0).magnitude, mat.GetColumn(1).magnitude, mat.GetColumn(2).magnitude);
|
||||
}
|
||||
|
||||
private static void Swap<T>(ref T lhs, ref T rhs)
|
||||
{
|
||||
T val = lhs;
|
||||
lhs = rhs;
|
||||
rhs = val;
|
||||
}
|
||||
|
||||
public static List<Vector3> getCatenaryPts(Vector3 vStart, Vector3 vEnd, float r_length, int N)
|
||||
{
|
||||
bool flag = false;
|
||||
int num = 100;
|
||||
float num2 = 1E-10f;
|
||||
float num3 = 1E-08f;
|
||||
float num4 = 0.5f;
|
||||
float num5 = 1E-09f;
|
||||
float num6 = 0.001f;
|
||||
if (vStart.y > vEnd.y)
|
||||
{
|
||||
Swap(ref vStart, ref vEnd);
|
||||
flag = true;
|
||||
}
|
||||
Vector3 vector = vEnd - vStart;
|
||||
float y = vector.y;
|
||||
vector.y = 0f;
|
||||
Vector3 vector2 = vector / (N - 1);
|
||||
float magnitude = vector.magnitude;
|
||||
vector.Normalize();
|
||||
float num7 = ((magnitude == 0f) ? 1f : (1f / magnitude));
|
||||
List<Vector3> list = new List<Vector3>(new Vector3[N]);
|
||||
if (Math.Abs(magnitude) < num6)
|
||||
{
|
||||
Vector3 vector3 = new Vector3((vStart.x + vEnd.x) / 2f, 0f, (vStart.z + vEnd.z) / 2f);
|
||||
if (r_length < Math.Abs(y))
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
list[i] = vector3 + new Vector3(0f, vStart.y + y * ((float)i * 1f / (float)(N - 1)), 0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num7 = (r_length - Math.Abs(y)) / 2f;
|
||||
int num8 = (int)Math.Ceiling((float)N * num7 / r_length);
|
||||
float num9 = Math.Max(vStart.y, vEnd.y);
|
||||
float num10 = Math.Min(vStart.y, vEnd.y);
|
||||
for (int j = 0; j < N; j++)
|
||||
{
|
||||
if (j < N - num8)
|
||||
{
|
||||
float num11 = num10 - num7 - num9;
|
||||
float num12 = num11 * ((float)j * 1f / ((float)(N - num8) - 1f));
|
||||
list[j] = vector3 + new Vector3(0f, num9 + num12, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float num13 = num7;
|
||||
float num14 = num13 * ((float)j * 1f / ((float)num8 - 1f));
|
||||
vector3 = (list[j] = vector3 + new Vector3(0f, num10 - num7 + num14, 0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((double)r_length <= Math.Sqrt(magnitude * magnitude + y * y))
|
||||
{
|
||||
for (int k = 0; k < N; k++)
|
||||
{
|
||||
Vector3 value = vStart + k * vector2;
|
||||
float num15 = (float)k * (vEnd.y - vStart.y) / (float)(N - 1);
|
||||
value.y = vStart.y + num15;
|
||||
list[k] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Calc calc = new Calc(r_length, y, magnitude);
|
||||
for (int l = 0; l < num; l++)
|
||||
{
|
||||
float value2 = calc.g(num7);
|
||||
float value3 = calc.dg(num7);
|
||||
if (Math.Abs(value2) < num3 || Math.Abs(value3) < num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
float num16 = (0f - calc.g(num7)) / calc.dg(num7);
|
||||
float num17 = 1f;
|
||||
float num18 = num7 + num17 * num16;
|
||||
while (num18 < 0f || Math.Abs(calc.g(num18)) > Math.Abs(value2))
|
||||
{
|
||||
num17 = num4 * num17;
|
||||
if (num17 < num5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
num18 = num7 + num17 * num16;
|
||||
}
|
||||
num7 = num18;
|
||||
}
|
||||
float num19 = (float)(0.5 * (Math.Log((r_length + y) / (r_length - y)) / (double)num7 - (double)magnitude));
|
||||
vector.y = 0f;
|
||||
vector.Normalize();
|
||||
Vector3 vector5 = vStart - num19 * vector;
|
||||
vector5.y = 0f;
|
||||
float num20 = (float)((double)vStart.y - Math.Cosh(num19 * num7) / (double)num7);
|
||||
for (int m = 0; m < N; m++)
|
||||
{
|
||||
Vector3 vector6 = vStart + m * vector2;
|
||||
Vector3 vector7 = vector6;
|
||||
vector6.y = 0f;
|
||||
vector6.y = (float)(Math.Cosh((vector6 - vector5).magnitude * num7) / (double)num7 + (double)num20);
|
||||
list[m] = vector6;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
list.Reverse();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Quaternion createOrientation(Vector3 v)
|
||||
{
|
||||
if (v.x == 0f && v.y == 0f && v.z == 0f)
|
||||
{
|
||||
return Quaternion.identity;
|
||||
}
|
||||
Vector3 vector = new Vector3(0f, 1f, 0f);
|
||||
Vector3 vector2 = Vector3.Cross(v, vector);
|
||||
vector2.Normalize();
|
||||
float num = Vector3.Dot(vector, v);
|
||||
if (num > 1f)
|
||||
{
|
||||
num = 1f;
|
||||
}
|
||||
else if (num < -1f)
|
||||
{
|
||||
num = -1f;
|
||||
}
|
||||
float num2 = (float)Math.Acos(num);
|
||||
return Quaternion.AngleAxis(num2 * 180f / 3.14159f, -vector2);
|
||||
}
|
||||
|
||||
public static T DeepClone<T>(T a)
|
||||
{
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter binaryFormatter = new BinaryFormatter();
|
||||
binaryFormatter.Serialize(memoryStream, a);
|
||||
memoryStream.Position = 0L;
|
||||
return (T)binaryFormatter.Deserialize(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Rigidbody, List<UnityEngine.Joint>> buildMapOfJoints()
|
||||
{
|
||||
Dictionary<Rigidbody, List<UnityEngine.Joint>> dictionary = new Dictionary<Rigidbody, List<UnityEngine.Joint>>();
|
||||
UnityEngine.Joint[] array = UnityEngine.Object.FindObjectsOfType<UnityEngine.Joint>();
|
||||
UnityEngine.Joint[] array2 = array;
|
||||
foreach (UnityEngine.Joint joint in array2)
|
||||
{
|
||||
Rigidbody component = joint.gameObject.GetComponent<Rigidbody>();
|
||||
if (component != null)
|
||||
{
|
||||
if (!dictionary.ContainsKey(component))
|
||||
{
|
||||
dictionary.Add(component, new List<UnityEngine.Joint>());
|
||||
}
|
||||
dictionary[component].Add(joint);
|
||||
}
|
||||
Rigidbody connectedBody = joint.connectedBody;
|
||||
if (connectedBody != null)
|
||||
{
|
||||
if (!dictionary.ContainsKey(connectedBody))
|
||||
{
|
||||
dictionary.Add(connectedBody, new List<UnityEngine.Joint>());
|
||||
}
|
||||
dictionary[connectedBody].Add(joint);
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private static void getConnectedBodies(ref Dictionary<Rigidbody, List<UnityEngine.Joint>> dic, Rigidbody body, ref HashSet<Rigidbody> bodies)
|
||||
{
|
||||
bodies.Add(body);
|
||||
if (!dic.ContainsKey(body))
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<UnityEngine.Joint> list = dic[body];
|
||||
foreach (UnityEngine.Joint item in list)
|
||||
{
|
||||
if (item.connectedBody != null && !bodies.Contains(item.connectedBody))
|
||||
{
|
||||
getConnectedBodies(ref dic, item.connectedBody, ref bodies);
|
||||
}
|
||||
Rigidbody component = item.gameObject.GetComponent<Rigidbody>();
|
||||
if (component != null && !bodies.Contains(component))
|
||||
{
|
||||
getConnectedBodies(ref dic, component, ref bodies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void moveConnectedBodies(Rigidbody start, Matrix4x4 newPose)
|
||||
{
|
||||
Dictionary<Rigidbody, List<UnityEngine.Joint>> dic = buildMapOfJoints();
|
||||
HashSet<Rigidbody> bodies = new HashSet<Rigidbody>();
|
||||
getConnectedBodies(ref dic, start, ref bodies);
|
||||
Matrix4x4 matrix4x = Matrix4x4.TRS(start.transform.position, start.transform.rotation, new Vector3(1f, 1f, 1f));
|
||||
foreach (Rigidbody item in bodies)
|
||||
{
|
||||
Matrix4x4 matrix4x2 = Matrix4x4.TRS(item.transform.position, item.transform.rotation, new Vector3(1f, 1f, 1f));
|
||||
Matrix4x4 inverse = matrix4x.inverse;
|
||||
matrix4x2 = inverse * matrix4x2;
|
||||
matrix4x2 = newPose * matrix4x2;
|
||||
Vector3 pos;
|
||||
Quaternion rot;
|
||||
Vector3 scale;
|
||||
MatrixToTRS(matrix4x2, out pos, out rot, out scale);
|
||||
item.transform.position = pos;
|
||||
item.transform.rotation = rot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93c19397aa18981aebed2e7aba8ca270
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PhysicsTools
|
||||
{
|
||||
public class Winch : MonoBehaviour
|
||||
{
|
||||
public float brakeForce;
|
||||
|
||||
public float heaveTorque;
|
||||
|
||||
public float tensionTorque;
|
||||
|
||||
public float radius;
|
||||
|
||||
public float length;
|
||||
|
||||
public float inertia;
|
||||
|
||||
public float maxRopeLength;
|
||||
|
||||
public float minRopeLength;
|
||||
|
||||
public float rpm;
|
||||
|
||||
public float maxRPM;
|
||||
|
||||
private float omega;
|
||||
|
||||
public Rope rope;
|
||||
|
||||
public Winch()
|
||||
{
|
||||
radius = 1f;
|
||||
length = 1f;
|
||||
maxRPM = 1f;
|
||||
omega = 0f;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
float fixedDeltaTime = Time.fixedDeltaTime;
|
||||
float num = tensionTorqueValue() - heaveTorque;
|
||||
float num2 = num / inertia;
|
||||
float num3 = brakeForce * radius / inertia;
|
||||
float num4 = omega + num2 * fixedDeltaTime;
|
||||
if ((num2 < 0f && rope.getLength() > minRopeLength) || (num2 > 0f && num2 > num3 && rope.getLength() < maxRopeLength))
|
||||
{
|
||||
if (num4 > 0f && num4 - num3 * fixedDeltaTime < 0f)
|
||||
{
|
||||
num4 = 0f;
|
||||
}
|
||||
else if (num4 < 0f && num4 + num3 * fixedDeltaTime > 0f)
|
||||
{
|
||||
num4 = 0f;
|
||||
}
|
||||
else if (num4 > 0f)
|
||||
{
|
||||
num4 -= num3 * fixedDeltaTime;
|
||||
}
|
||||
else if (num4 < 0f)
|
||||
{
|
||||
num4 += num3 * fixedDeltaTime;
|
||||
}
|
||||
omega = num4;
|
||||
rope.changeLength(getLinearSpeed() * fixedDeltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
omega = 0f;
|
||||
}
|
||||
rpm = omega / 6.28318f * 60f;
|
||||
if (Math.Abs(rpm) > maxRPM)
|
||||
{
|
||||
if (rpm < 0f)
|
||||
{
|
||||
rpm = 0f - maxRPM;
|
||||
}
|
||||
else
|
||||
{
|
||||
rpm = maxRPM;
|
||||
}
|
||||
}
|
||||
omega = rpm / 60f * 6.28318f;
|
||||
}
|
||||
|
||||
private float tensionTorqueValue()
|
||||
{
|
||||
tensionTorque = radius * getTension();
|
||||
return tensionTorque;
|
||||
}
|
||||
|
||||
private float getLinearSpeed()
|
||||
{
|
||||
return omega * radius;
|
||||
}
|
||||
|
||||
private float getTension()
|
||||
{
|
||||
return rope.getTension();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fac89f9401be21c56be128e602bbd1cd
|
||||
timeCreated: 1771646562
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
name:
|
||||
externalObjects: {}
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user