Files
2026-03-04 10:03:45 +08:00

236 lines
5.0 KiB
C#

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<Rigidbody>();
}
}
public Collider Collider
{
get
{
if (!(collider == null))
{
return collider;
}
return GetComponent<Collider>();
}
}
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<Collider>();
rb = GetComponent<Rigidbody>();
_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<Rigidbody>();
GetComponentsInChildren<Rigidbody>().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<ConfigurableJoint>();
_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);
}
}
}