236 lines
5.0 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|