using System; using Sirenix.Utilities; using UFS2.ScriptableObjects; using UnityEngine; namespace UFS2.Gameplay { public class FishPhysics : MonoBehaviour { private Rigidbody rb; private Collider collider; private bool _IsInWater; private FishData fishData; private Transform _TailRag; private ConfigurableJoint _Joint; private Quaternion _LastRotation; private Vector3 _StartTailLocalPosition; private float jointTensionSmooth; public Rigidbody Rbody { get { if (!(rb == null)) { return rb; } return GetComponent(); } } public Collider Collider { get { if (!(collider == null)) { return collider; } return GetComponent(); } } public bool IsInWater { get { return _IsInWater; } set { if (_IsInWater != value) { _IsInWater = value; if (_IsInWater) { this.OnEnterWater?.Invoke(); } else { this.OnExitWater?.Invoke(); } } } } public bool IsJointTension { get { float target = -1f; if ((bool)_Joint) { float num = 20f; if (_Joint.currentForce.magnitude > num) { target = 1f; } } jointTensionSmooth = Mathf.MoveTowards(jointTensionSmooth, target, Time.fixedDeltaTime * 4f); return jointTensionSmooth > 0f; } } public float VelocityLimit { get; set; } = -1f; public event Action OnEnterWater; public event Action OnExitWater; private void Start() { collider = GetComponent(); rb = GetComponent(); _TailRag = base.transform.GetChild(0).Find("TailRag"); _LastRotation = base.transform.rotation; _StartTailLocalPosition = _TailRag.localPosition; } private void FixedUpdate() { IsInWater = GameWaterSystem.IsPositionUnderWater(base.transform.position); GravityUpdate(); RotationUpdate(); ClampSpeed(); } private void GravityUpdate() { if (!IsInWater) { rb.AddForce(Vector3.down * Mathf.Abs(Physics.gravity.y), ForceMode.Acceleration); rb.useGravity = true; rb.drag = Mathf.MoveTowards(rb.drag, 0.5f, Time.fixedDeltaTime * 10f); } else { rb.useGravity = false; rb.drag = Mathf.MoveTowards(rb.drag, 3f, Time.fixedDeltaTime); } } private void RotationUpdate() { if (!IsInWater) { rb.freezeRotation = false; rb.angularDrag = 1f; } else { rb.freezeRotation = !IsJointTension; rb.angularDrag = 1f; } } private void ClampSpeed() { if (VelocityLimit > 0f) { rb.velocity = Vector3.ClampMagnitude(rb.velocity, VelocityLimit); } } public void ImportData(FishData data, float weight) { fishData = data; rb = GetComponent(); GetComponentsInChildren().ForEach(delegate(Rigidbody x) { x.isKinematic = false; x.useGravity = false; }); rb.drag = 0.25f; rb.mass = weight; } public void AttachFishToBody(Rigidbody rbAttachment, Vector3 jointAnchor) { _Joint = base.gameObject.AddComponent(); _Joint.connectedBody = rbAttachment; _Joint.autoConfigureConnectedAnchor = false; _Joint.connectedAnchor = Vector3.zero; _Joint.anchor = jointAnchor; _Joint.axis = Vector3.zero; _Joint.swapBodies = false; _Joint.xMotion = ConfigurableJointMotion.Limited; _Joint.yMotion = ConfigurableJointMotion.Limited; _Joint.zMotion = ConfigurableJointMotion.Limited; _Joint.enableCollision = true; } public void RemoveJoint() { if (!(_Joint == null)) { UnityEngine.Object.Destroy(_Joint); } } public void SetJointDistance(float distance) { SoftJointLimit linearLimit = new SoftJointLimit { contactDistance = distance }; _Joint.linearLimit = linearLimit; } public void GravityScaleDown(float scale) { rb.velocity *= scale; } private void MoveTail(Vector3 direction, Quaternion targetRotation, float delta, float force = 15f) { float num = Quaternion.Angle(_LastRotation, targetRotation); Vector3 vector = Vector3.Cross(base.transform.forward, direction); float num2 = num / 30f; Vector3 localPosition = _TailRag.localPosition; localPosition.x = ((vector.y < 0f) ? (0f - num2) : num2); _TailRag.localPosition = localPosition; _LastRotation = Quaternion.Lerp(_LastRotation, targetRotation, delta * force); } public void ResetTail() { if (_TailRag == null) { Debug.LogError("Fish don't have tail rag please add component " + base.gameObject.name); } else { _TailRag.localPosition = _StartTailLocalPosition; } } public void MoveInDirection(Vector3 direction, float moveSpeed, float rotationSpeed, float delta, ForceMode forceMode = ForceMode.Acceleration) { Vector3 force = Vector3.RotateTowards(base.transform.forward, direction, MathF.PI / 12f, 0f) * moveSpeed; rb.AddForce(force, forceMode); Quaternion quaternion = Quaternion.LookRotation(direction, Vector3.up); rb.MoveRotation(Quaternion.Lerp(rb.rotation, quaternion, Time.deltaTime * rotationSpeed)); MoveTail(direction, quaternion, delta, 30f); } } }