目录结构调整

This commit is contained in:
2025-08-28 00:20:12 +08:00
parent a19a071c47
commit efb64ce7bc
195 changed files with 344 additions and 677 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 19ffa462a8ae4066a12d946a8b80cab0
timeCreated: 1748446110

View File

@@ -0,0 +1,326 @@
using UnityEngine;
namespace NBF
{
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(AudioSource))]
public class FirstPersonController : MonoBehaviour
{
[SerializeField] private bool m_IsWalking;
[SerializeField] public float m_WalkSpeed;
[SerializeField] public float m_RunSpeed;
[SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten;
[SerializeField] private float m_JumpSpeed;
[SerializeField] private float m_StickToGroundForce;
[SerializeField] private float m_GravityMultiplier;
[SerializeField] public MouseLook m_MouseLook;
[SerializeField] private bool m_UseFovKick;
[SerializeField] private FOVKick m_FovKick = new FOVKick();
[SerializeField] private bool m_UseHeadBob;
[SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob();
[SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob();
[SerializeField] private float m_StepInterval;
[SerializeField] private AudioClip[] m_FootstepSounds;
[SerializeField] private AudioClip[] m_FootstepSoundsBridge;
[SerializeField] private AudioClip[] m_FootstepSoundsStone;
[SerializeField] private AudioClip m_JumpSound;
[SerializeField] private AudioClip m_LandSound;
private Camera m_Camera;
private bool m_Jump;
public bool frezzeRotation;
public bool frezzePosition;
public bool rotateMouseInFixedUpdate = true;
public Vector2 m_Input;
public Vector3 m_MoveDir = Vector3.zero;
public CharacterController m_CharacterController;
private CollisionFlags m_CollisionFlags;
private bool m_PreviouslyGrounded;
private Vector3 m_OriginalCameraPosition;
private float m_StepCycle;
private float m_NextStep;
private bool m_Jumping;
private AudioSource m_AudioSource;
private string groundTypeTag = "";
public float horizontal;
public float vertical;
public bool isJumping;
public bool isRuning;
public bool notMove;
public bool isWater;
private void Start()
{
m_CharacterController = GetComponent<CharacterController>();
m_Camera = Camera.main;
m_OriginalCameraPosition = m_Camera.transform.localPosition;
m_FovKick.Setup(m_Camera);
m_HeadBob.Setup(m_Camera, m_StepInterval);
m_StepCycle = 0f;
m_NextStep = m_StepCycle / 2f;
m_Jumping = false;
m_AudioSource = GetComponent<AudioSource>();
m_MouseLook.Init(transform, m_Camera.transform);
}
private void Update()
{
if (!frezzeRotation && !rotateMouseInFixedUpdate)
{
RotateView();
}
if (!m_Jump)
{
m_Jump = isJumping;
}
if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
{
StartCoroutine(m_JumpBob.DoBobCycle());
PlayLandingSound();
m_MoveDir.y = 0f;
m_Jumping = false;
}
if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
{
m_MoveDir.y = 0f;
}
m_PreviouslyGrounded = m_CharacterController.isGrounded;
}
private void PlayLandingSound()
{
m_AudioSource.clip = m_LandSound;
m_AudioSource.Play();
m_NextStep = m_StepCycle + 0.5f;
}
private void FixedUpdate()
{
if (!frezzeRotation && rotateMouseInFixedUpdate)
{
RotateView();
}
if (frezzePosition)
{
return;
}
GetInput(out var speed);
Vector3 vector = transform.forward * m_Input.y + transform.right * m_Input.x;
Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out var hitInfo,
m_CharacterController.height / 2f, -1, QueryTriggerInteraction.Ignore);
vector = Vector3.ProjectOnPlane(vector, hitInfo.normal).normalized;
m_MoveDir.x = vector.x * speed;
m_MoveDir.z = vector.z * speed;
if (m_CharacterController.isGrounded)
{
m_MoveDir.y = 0f - m_StickToGroundForce;
if (m_Jump && !isWater)
{
if ((bool)transform.parent && transform.parent.gameObject.layer == LayerMask.NameToLayer("Boat"))
{
return;
}
m_MoveDir.y = m_JumpSpeed;
PlayJumpSound();
m_Jump = false;
m_Jumping = true;
}
}
else
{
m_MoveDir += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime;
}
if (!notMove)
{
m_CollisionFlags = m_CharacterController.Move(m_MoveDir * Time.fixedDeltaTime);
}
ProgressStepCycle(speed);
UpdateCameraPosition(speed);
m_MouseLook.UpdateCursorLock();
}
private void PlayJumpSound()
{
m_AudioSource.clip = m_JumpSound;
m_AudioSource.Play();
}
private void ProgressStepCycle(float speed)
{
if (m_CharacterController.velocity.sqrMagnitude > 0f && (m_Input.x != 0f || m_Input.y != 0f))
{
m_StepCycle +=
(m_CharacterController.velocity.magnitude + speed * (m_IsWalking ? 1f : m_RunstepLenghten)) *
Time.fixedDeltaTime;
}
if (m_StepCycle > m_NextStep)
{
m_NextStep = m_StepCycle + m_StepInterval;
PlayFootStepAudio();
}
}
private void PlayFootStepAudio()
{
if (!m_CharacterController.isGrounded)
{
return;
}
if (groundTypeTag == "Bridge" || groundTypeTag == "Boat")
{
if (m_FootstepSoundsBridge.Length != 0)
{
int num = Random.Range(1, m_FootstepSoundsBridge.Length);
m_AudioSource.clip = m_FootstepSoundsBridge[num];
m_AudioSource.PlayOneShot(m_AudioSource.clip, 0.3f);
m_FootstepSoundsBridge[num] = m_FootstepSoundsBridge[0];
m_FootstepSoundsBridge[0] = m_AudioSource.clip;
}
}
else if (groundTypeTag == "Stone")
{
if (m_FootstepSoundsStone.Length != 0)
{
int num2 = Random.Range(1, m_FootstepSoundsStone.Length);
m_AudioSource.clip = m_FootstepSoundsStone[num2];
m_AudioSource.PlayOneShot(m_AudioSource.clip, 0.3f);
m_FootstepSoundsStone[num2] = m_FootstepSoundsStone[0];
m_FootstepSoundsStone[0] = m_AudioSource.clip;
}
}
else if (m_FootstepSounds.Length != 0)
{
int num3 = Random.Range(1, m_FootstepSounds.Length);
m_AudioSource.clip = m_FootstepSounds[num3];
m_AudioSource.PlayOneShot(m_AudioSource.clip, 0.3f);
m_FootstepSounds[num3] = m_FootstepSounds[0];
m_FootstepSounds[0] = m_AudioSource.clip;
}
}
private void UpdateCameraPosition(float speed)
{
if (m_UseHeadBob)
{
Vector3 localPosition;
if (m_CharacterController.velocity.magnitude > 0f && m_CharacterController.isGrounded)
{
m_Camera.transform.localPosition = m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
speed *
(m_IsWalking ? 1f : m_RunstepLenghten));
localPosition = m_Camera.transform.localPosition;
localPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
}
else
{
localPosition = m_Camera.transform.localPosition;
localPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
}
m_Camera.transform.localPosition = localPosition;
}
}
private void GetInput(out float speed)
{
bool isWalking = m_IsWalking;
m_IsWalking = !isRuning;
speed = (m_IsWalking ? m_WalkSpeed : m_RunSpeed);
m_Input = new Vector2(horizontal, vertical);
if (m_Input.sqrMagnitude > 1f)
{
m_Input.Normalize();
}
if (m_IsWalking != isWalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0f)
{
StopAllCoroutines();
StartCoroutine((!m_IsWalking) ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
}
}
public void RotateView()
{
m_MouseLook.LookRotation(transform, m_Camera.transform);
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
Rigidbody attachedRigidbody = hit.collider.attachedRigidbody;
groundTypeTag = hit.collider.tag;
if (m_CollisionFlags != CollisionFlags.Below && !(attachedRigidbody == null))
{
_ = attachedRigidbody.isKinematic;
}
}
private void OnTriggerStay(Collider other)
{
if (other.CompareTag("Water"))
{
isWater = true;
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Water"))
{
isWater = false;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f1324aa5e564035ab9a361499a66c27
timeCreated: 1748446121

View File

@@ -0,0 +1,132 @@
using System;
using UnityEngine;
namespace NBF
{
[Serializable]
public class MouseLook
{
public float XSensitivity = 2f;
public float YSensitivity = 2f;
public bool clampVerticalRotation = true;
public float MinimumX = -90f;
public float MaximumX = 90f;
public bool smooth;
public float smoothTime = 5f;
public bool lockCursor = true;
public float RotYvalue;
public bool invertMouseY;
public bool invertMouseX;
public int ControllerHandMode;
private Quaternion m_CharacterTargetRot;
private Quaternion m_CameraTargetRot;
private bool m_cursorIsLocked = true;
// private Player player;
public void Init(Transform character, Transform camera)
{
m_CharacterTargetRot = character.localRotation;
m_CameraTargetRot = camera.localRotation;
// player = ReInput.players.GetPlayer(0);
}
public void LookRotation(Transform character, Transform camera)
{
// if (!SRDebug.Instance.IsDebugPanelVisible && !SRDebug.Instance.IsDebugPanelVisible)
{
var lookInput = InputManager.GetLookInput();
float num = Mathf.Clamp(lookInput.y * YSensitivity * 5f * Time.deltaTime, -10f, 10f);
float num2 =
Mathf.Clamp(lookInput.x * XSensitivity * 5f * Time.deltaTime, -10f, 10f);
if (invertMouseY)
{
num *= -1f;
}
if (invertMouseX)
{
num2 *= -1f;
}
RotYvalue = num2;
m_CharacterTargetRot *= Quaternion.Euler(0f, num2, 0f);
m_CameraTargetRot *= Quaternion.Euler(0f - num, 0f, 0f);
if (clampVerticalRotation)
{
m_CameraTargetRot = ClampRotationAroundXAxis(m_CameraTargetRot);
}
if (smooth)
{
character.localRotation = Quaternion.Slerp(character.localRotation, m_CharacterTargetRot,
smoothTime * Time.deltaTime);
camera.localRotation = Quaternion.Slerp(camera.localRotation, m_CameraTargetRot,
smoothTime * Time.deltaTime);
}
else
{
character.localRotation = m_CharacterTargetRot;
camera.localRotation = m_CameraTargetRot;
}
UpdateCursorLock();
}
}
public void SetCursorLock(bool value)
{
lockCursor = value;
if (!lockCursor)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
public void UpdateCursorLock()
{
if (lockCursor)
{
InternalLockUpdate();
}
}
private void InternalLockUpdate()
{
}
private Quaternion ClampRotationAroundXAxis(Quaternion q)
{
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1f;
float value = 114.59156f * Mathf.Atan(q.x);
value = Mathf.Clamp(value, MinimumX, MaximumX);
q.x = Mathf.Tan((float)Math.PI / 360f * value);
return q;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8d0cbae98ed8408e90ca0cb0e05b6d1d
timeCreated: 1748446245

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8d919912beb546df866a283a379c7e96
timeCreated: 1748446174

View File

@@ -0,0 +1,54 @@
using System;
using UnityEngine;
namespace NBF
{
[Serializable]
public class CurveControlledBob
{
public float HorizontalBobRange = 0.33f;
public float VerticalBobRange = 0.33f;
public AnimationCurve Bobcurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(0.5f, 1f),
new Keyframe(1f, 0f), new Keyframe(1.5f, -1f), new Keyframe(2f, 0f));
public float VerticaltoHorizontalRatio = 1f;
private float m_CyclePositionX;
private float m_CyclePositionY;
private float m_BobBaseInterval;
private Vector3 m_OriginalCameraPosition;
private float m_Time;
public void Setup(Camera camera, float bobBaseInterval)
{
m_BobBaseInterval = bobBaseInterval;
m_OriginalCameraPosition = camera.transform.localPosition;
m_Time = Bobcurve[Bobcurve.length - 1].time;
}
public Vector3 DoHeadBob(float speed)
{
float x = m_OriginalCameraPosition.x + Bobcurve.Evaluate(m_CyclePositionX) * HorizontalBobRange;
float y = m_OriginalCameraPosition.y + Bobcurve.Evaluate(m_CyclePositionY) * VerticalBobRange;
m_CyclePositionX += speed * Time.deltaTime / m_BobBaseInterval;
m_CyclePositionY += speed * Time.deltaTime / m_BobBaseInterval * VerticaltoHorizontalRatio;
if (m_CyclePositionX > m_Time)
{
m_CyclePositionX -= m_Time;
}
if (m_CyclePositionY > m_Time)
{
m_CyclePositionY -= m_Time;
}
return new Vector3(x, y, 0f);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 491f525f09d84899a13bf70f08f7a713
timeCreated: 1748446274

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections;
using UnityEngine;
namespace NBF
{
[Serializable]
public class FOVKick
{
public Camera Camera;
[HideInInspector] public float originalFov;
public float FOVIncrease = 3f;
public float TimeToIncrease = 1f;
public float TimeToDecrease = 1f;
public AnimationCurve IncreaseCurve;
public void Setup(Camera camera)
{
CheckStatus(camera);
Camera = camera;
originalFov = camera.fieldOfView;
}
private void CheckStatus(Camera camera)
{
if (camera == null)
{
throw new Exception("FOVKick camera is null, please supply the camera to the constructor");
}
if (IncreaseCurve == null)
{
throw new Exception(
"FOVKick Increase curve is null, please define the curve for the field of view kicks");
}
}
public void ChangeCamera(Camera camera)
{
Camera = camera;
}
public IEnumerator FOVKickUp()
{
float t = Mathf.Abs((Camera.fieldOfView - originalFov) / FOVIncrease);
while (t < TimeToIncrease)
{
Camera.fieldOfView = originalFov + IncreaseCurve.Evaluate(t / TimeToIncrease) * FOVIncrease;
t += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
}
public IEnumerator FOVKickDown()
{
float t = Mathf.Abs((Camera.fieldOfView - originalFov) / FOVIncrease);
while (t > 0f)
{
Camera.fieldOfView = originalFov + IncreaseCurve.Evaluate(t / TimeToDecrease) * FOVIncrease;
t -= Time.deltaTime;
yield return new WaitForEndOfFrame();
}
Camera.fieldOfView = originalFov;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cb6289c553a943a98adf26c14b1eaf2b
timeCreated: 1748446181

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections;
using UnityEngine;
namespace NBF
{
[Serializable]
public class LerpControlledBob
{
public float BobDuration;
public float BobAmount;
private float m_Offset;
public float Offset()
{
return m_Offset;
}
public IEnumerator DoBobCycle()
{
float t2 = 0f;
while (t2 < BobDuration)
{
m_Offset = Mathf.Lerp(0f, BobAmount, t2 / BobDuration);
t2 += Time.deltaTime;
yield return new WaitForFixedUpdate();
}
t2 = 0f;
while (t2 < BobDuration)
{
m_Offset = Mathf.Lerp(BobAmount, 0f, t2 / BobDuration);
t2 += Time.deltaTime;
yield return new WaitForFixedUpdate();
}
m_Offset = 0f;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1ff17b813690432a9da59c9ab3ceccbb
timeCreated: 1748446293

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8ce6ddcc06025e84c8f118c9af703263
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,176 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0cc4d18ef4a8ff6439959ca335b42593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d9816d80c9fd754aaa984a288cd35d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
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);
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 4c3919bd67247ecf47ac8b5970b70372
timeCreated: 1747788126
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,142 @@
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;
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 3e680fa725d3066a2472a42dc6f1ba88
timeCreated: 1747788127
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09ae8cd9a6c1c324b8c2a2a78ac60d7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
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;
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 88218b6dac3a1d87d3867523046c804d
timeCreated: 1747788125
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b2e47173d3a5c346a9528bef13473eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 8d8b3d7293da4ed8736330164944ddd3
timeCreated: 1747788125
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 089e242339d5f784baf45339b1f072ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
// 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;
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: b876b665f2164469858aa78787017d4d
timeCreated: 1747788127
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bbc2d7df2b1ead41bf1846c6e06b77d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9090fbf5485508f41b83439d2c44e9b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd4b78dfa69ad534c94ee6f13133b5e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using System;
namespace PhysicsTools
{
[Serializable]
public class SegmentPropertiesCylinder : SegmentPropertiesBase
{
public float radius;
public SegmentPropertiesCylinder()
{
length = 1f;
radius = 0.1f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c06432f1a93c1694e97f31bf3112ceb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
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)
{
SoftJointLimitSpring result = default(SoftJointLimitSpring);
result.spring = c.spring;
result.damper = c.damper;
return result;
}
public static explicit operator SerializedSoftJointLimitSpring(SoftJointLimitSpring c)
{
return new SerializedSoftJointLimitSpring(c);
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: e9f687b18e562c31f90c28822c0f641d
timeCreated: 1747788125
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,272 @@
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;
}
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 93c19397aa18981aebed2e7aba8ca270
timeCreated: 1747788122
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,103 @@
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();
}
}
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: fac89f9401be21c56be128e602bbd1cd
timeCreated: 1747788127
licenseType: Free
MonoImporter:
serializedVersion: 2
name:
externalObjects: {}
defaultReferences: []
executionOrder: 0
icon: {fileID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62ddefd95a62cbc4ea1a2aabc009a378
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,182 @@
// The SteamManager is designed to work with Steamworks.NET
// This file is released into the public domain.
// Where that dedication is not recognized you are granted a perpetual,
// irrevocable license to copy and modify this file as you see fit.
//
// Version: 1.0.13
#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX)
#define DISABLESTEAMWORKS
#endif
using UnityEngine;
#if !DISABLESTEAMWORKS
using System.Collections;
using Steamworks;
#endif
//
// The SteamManager provides a base implementation of Steamworks.NET on which you can build upon.
// It handles the basics of starting up and shutting down the SteamAPI for use.
//
[DisallowMultipleComponent]
public class SteamManager : MonoBehaviour {
#if !DISABLESTEAMWORKS
protected static bool s_EverInitialized = false;
protected static SteamManager s_instance;
protected static SteamManager Instance {
get {
if (s_instance == null) {
return new GameObject("SteamManager").AddComponent<SteamManager>();
}
else {
return s_instance;
}
}
}
protected bool m_bInitialized = false;
public static bool Initialized {
get {
return Instance.m_bInitialized;
}
}
protected SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook;
[AOT.MonoPInvokeCallback(typeof(SteamAPIWarningMessageHook_t))]
protected static void SteamAPIDebugTextHook(int nSeverity, System.Text.StringBuilder pchDebugText) {
Debug.LogWarning(pchDebugText);
}
#if UNITY_2019_3_OR_NEWER
// In case of disabled Domain Reload, reset static members before entering Play Mode.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void InitOnPlayMode()
{
s_EverInitialized = false;
s_instance = null;
}
#endif
protected virtual void Awake() {
// Only one instance of SteamManager at a time!
if (s_instance != null) {
Destroy(gameObject);
return;
}
s_instance = this;
if(s_EverInitialized) {
// This is almost always an error.
// The most common case where this happens is when SteamManager gets destroyed because of Application.Quit(),
// and then some Steamworks code in some other OnDestroy gets called afterwards, creating a new SteamManager.
// You should never call Steamworks functions in OnDestroy, always prefer OnDisable if possible.
throw new System.Exception("Tried to Initialize the SteamAPI twice in one session!");
}
// We want our SteamManager Instance to persist across scenes.
DontDestroyOnLoad(gameObject);
if (!Packsize.Test()) {
Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this);
}
if (!DllCheck.Test()) {
Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this);
}
try {
// If Steam is not running or the game wasn't started through Steam, SteamAPI_RestartAppIfNecessary starts the
// Steam client and also launches this game again if the User owns it. This can act as a rudimentary form of DRM.
// Note that this will run which ever version you have installed in steam. Which may not be the precise executable
// we were currently running.
// Once you get a Steam AppID assigned by Valve, you need to replace AppId_t.Invalid with it and
// remove steam_appid.txt from the game depot. eg: "(AppId_t)480" or "new AppId_t(480)".
// See the Valve documentation for more information: https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown
if (SteamAPI.RestartAppIfNecessary(AppId_t.Invalid)) {
Debug.Log("[Steamworks.NET] Shutting down because RestartAppIfNecessary returned true. Steam will restart the application.");
Application.Quit();
return;
}
}
catch (System.DllNotFoundException e) { // We catch this exception here, as it will be the first occurrence of it.
Debug.LogError("[Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.\n" + e, this);
Application.Quit();
return;
}
// Initializes the Steamworks API.
// If this returns false then this indicates one of the following conditions:
// [*] The Steam client isn't running. A running Steam client is required to provide implementations of the various Steamworks interfaces.
// [*] The Steam client couldn't determine the App ID of game. If you're running your application from the executable or debugger directly then you must have a [code-inline]steam_appid.txt[/code-inline] in your game directory next to the executable, with your app ID in it and nothing else. Steam will look for this file in the current working directory. If you are running your executable from a different directory you may need to relocate the [code-inline]steam_appid.txt[/code-inline] file.
// [*] Your application is not running under the same OS user context as the Steam client, such as a different user or administration access level.
// [*] Ensure that you own a license for the App ID on the currently active Steam account. Your game must show up in your Steam library.
// [*] Your App ID is not completely set up, i.e. in Release State: Unavailable, or it's missing default packages.
// Valve's documentation for this is located here:
// https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown
m_bInitialized = SteamAPI.Init();
if (!m_bInitialized) {
Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this);
return;
}
s_EverInitialized = true;
}
// This should only ever get called on first load and after an Assembly reload, You should never Disable the Steamworks Manager yourself.
protected virtual void OnEnable() {
if (s_instance == null) {
s_instance = this;
}
if (!m_bInitialized) {
return;
}
if (m_SteamAPIWarningMessageHook == null) {
// Set up our callback to receive warning messages from Steam.
// You must launch with "-debug_steamapi" in the launch args to receive warnings.
m_SteamAPIWarningMessageHook = new SteamAPIWarningMessageHook_t(SteamAPIDebugTextHook);
SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook);
}
}
// OnApplicationQuit gets called too early to shutdown the SteamAPI.
// Because the SteamManager should be persistent and never disabled or destroyed we can shutdown the SteamAPI here.
// Thus it is not recommended to perform any Steamworks work in other OnDestroy functions as the order of execution can not be garenteed upon Shutdown. Prefer OnDisable().
protected virtual void OnDestroy() {
if (s_instance != this) {
return;
}
s_instance = null;
if (!m_bInitialized) {
return;
}
SteamAPI.Shutdown();
}
protected virtual void Update() {
if (!m_bInitialized) {
return;
}
// Run Steam client callbacks
SteamAPI.RunCallbacks();
}
#else
public static bool Initialized {
get {
return false;
}
}
#endif // !DISABLESTEAMWORKS
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ef4bffeda13d7a748973ff9204401c07
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData: