Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [RequireComponent(typeof(Rigidbody))]
- public class PlayerMovementRigidbody : NetworkBehaviour
- {
- #region Variables
- [Header("References")]
- [SerializeField] Transform playerCamera;
- [Header("Ground Check")]
- [SerializeField] Transform groundCheck;
- [SerializeField] float groundCheckSphereRadius;
- [SerializeField] LayerMask groundMask;
- [Header("Player Settings")]
- [SerializeField] float walkingSpeed;
- [SerializeField] float swimmingSpeed = 3f;
- [SerializeField] float mouseSensitivity;
- [SerializeField] private float jumpHeight;
- [SerializeField] private float airResistance = 1f;
- [SerializeField] float airControlSpeed = 3f;
- [Header("Private References")]
- Rigidbody rb;
- ShipRB ship;
- [Header("Current State")]
- [SerializeField] MovementMode currentMovementMode;
- Vector2 inputMovementVector;
- Vector3 finalMoveVector;
- Vector2 rotationVector;
- float xRotation = 0f;
- [SerializeField] float currentSpeed; // current movement speed based on mode
- [SerializeField] bool isGrounded;
- [Header("Constants")]
- const float GRAVITY = -9.81f;
- #endregion
- #region Unity Methods
- void Start()
- {
- rb = GetComponent<Rigidbody>();
- ship = FindAnyObjectByType<ShipRB>();
- //REMOVE
- currentMovementMode = MovementMode.OnLand;
- currentSpeed = walkingSpeed;
- SetupRigidbody();
- }
- void OnEnable()
- {
- InputHandler.OnMove += SetInputMovementVector;
- InputHandler.OnMouseMove += SetRotationVector;
- InputHandler.OnPlayerJump += Jump;
- }
- void OnDisable()
- {
- InputHandler.OnMove -= SetInputMovementVector;
- InputHandler.OnMouseMove -= SetRotationVector;
- InputHandler.OnPlayerJump -= Jump;
- }
- void Update()
- {
- IsCharacterInWater();
- IsCharacterGrounded();
- }
- void FixedUpdate()
- {
- if (!IsHost && IsOwner && currentMovementMode == MovementMode.OnShip)
- {
- AlignPositionWithShip();
- }
- if (IsOwner)
- {
- MovePlayerCharacter();
- }
- }
- void LateUpdate()
- {
- if (!IsOwner) return;
- RotatePlayerCharacter();
- }
- #endregion
- #region Setups
- void SetupRigidbody()
- {
- rb.isKinematic = false;
- rb.constraints = RigidbodyConstraints.FreezeRotation;
- }
- #endregion
- #region Movement
- void MovePlayerCharacter()
- {
- switch (currentMovementMode)
- {
- case MovementMode.OnLand:
- MoveOnASurface();
- break;
- case MovementMode.OnShip:
- MoveOnASurface();
- break;
- case MovementMode.InWater:
- MoveInWater();
- break;
- case MovementMode.OnLadder:
- //Ladder movement logic here
- break;
- }
- }
- private void MoveInWater()
- {
- currentSpeed = swimmingSpeed;
- finalMoveVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
- finalMoveVector.Normalize();
- rb.MovePosition(finalMoveVector * currentSpeed * Time.fixedDeltaTime + rb.position);
- }
- private void MoveOnASurface()
- {
- if (isGrounded)
- {
- currentSpeed = walkingSpeed;
- finalMoveVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
- }
- else
- {
- currentSpeed = Mathf.Lerp(currentSpeed, 0, Time.fixedDeltaTime * airResistance);
- }
- // нормализация после расчётов
- finalMoveVector.Normalize();
- Vector3 airControlVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
- rb.MovePosition(rb.position + finalMoveVector * currentSpeed * Time.fixedDeltaTime + airControlVector * airControlSpeed * Time.fixedDeltaTime);
- }
- private void RotatePlayerCharacter()
- {
- float mouseX = rotationVector.x * mouseSensitivity * Time.deltaTime;
- float mouseY = rotationVector.y * mouseSensitivity * Time.deltaTime;
- // vertical rotation
- xRotation -= mouseY;
- xRotation = Mathf.Clamp(xRotation, -90f, 90f);
- playerCamera.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
- // horizontal rotation
- transform.Rotate(Vector3.up * mouseX);
- }
- private void AlignPositionWithShip()
- {
- /*
- Vector3 vel = ship.GetVelocity();
- vel.y = 0;
- rb.MovePosition(rb.position + vel * Time.fixedDeltaTime);
- */
- Vector3 shipMovement = ship.currentShipVelocity.Value;
- shipMovement.y = 0;
- rb.MovePosition(rb.position + shipMovement * Time.fixedDeltaTime);
- }
- #endregion
- #region Actions
- private void Jump()
- {
- if (!IsOwner) return;
- if (isGrounded)
- {
- rb.AddForce(Vector3.up * Mathf.Sqrt(jumpHeight * -2f * GRAVITY), ForceMode.VelocityChange);
- }
- }
- #endregion
- #region Checks
- private void IsCharacterInWater()
- {
- float waterHeight = OceanManager.Instance.GetOceanPointHeight(transform.position);
- if (transform.position.y < waterHeight && currentMovementMode != MovementMode.OnShip)
- {
- SetMovementMode(MovementMode.InWater);
- }
- }
- private void IsCharacterGrounded()
- {
- isGrounded = Physics.CheckSphere(groundCheck.position, groundCheckSphereRadius, groundMask);
- }
- #endregion
- #region Setters
- void SetInputMovementVector(Vector2 newMovementVector)
- {
- inputMovementVector = newMovementVector;
- }
- void SetRotationVector(Vector2 rotVector)
- {
- rotationVector = rotVector;
- }
- public void SetMovementMode(MovementMode newMode)
- {
- currentMovementMode = newMode;
- }
- #endregion
- }
- [RequireComponent(typeof(Rigidbody))]
- public class ShipFloatingSmooth : MonoBehaviour
- {
- [Header("Points & refs")]
- [SerializeField] Transform[] floatPoints;
- Rigidbody rb;
- [Header("Vertical (Y) settings")]
- [SerializeField] float verticalSmoothTime = 0.5f;
- [SerializeField] float verticalDamping = 1f;
- [SerializeField] float buoyancyOffset = 0f;
- [Header("Rotation (pitch / roll) settings")]
- [SerializeField] float pitchSmoothTime = 0.6f;
- [SerializeField] float rollSmoothTime = 0.8f;
- [Header("Limits & feel")]
- [SerializeField] float maxPitchAngle = 35f;
- [SerializeField] float maxRollAngle = 40f;
- [Header("Optional extras")]
- [SerializeField] bool keepForwardProjectedOnWave = true;
- float yVelocity = 0f;
- float pitchVelocity = 0f;
- float rollVelocity = 0f;
- Quaternion targetRotation;
- float targetYPos = 0f;
- float yMovementThisFrame = 0f;
- void Start()
- {
- rb = GetComponent<Rigidbody>();
- rb.isKinematic = true;
- UpdateTargetYPos();
- UpdateTargetRotation();
- }
- void Update()
- {
- UpdateTargetYPos();
- UpdateTargetRotation();
- }
- void FixedUpdate()
- {
- MoveToRotationTarget();
- }
- private void UpdateTargetRotation()
- {
- Vector3 A = floatPoints.Length > 0 ? floatPoints[0].position : transform.position;
- Vector3 B = floatPoints.Length > 1 ? floatPoints[1].position : transform.position + transform.forward;
- Vector3 C = floatPoints.Length > 2 ? floatPoints[2].position : transform.position + transform.right;
- A.y = OceanManager.Instance.GetOceanPointHeight(A);
- B.y = OceanManager.Instance.GetOceanPointHeight(B);
- C.y = OceanManager.Instance.GetOceanPointHeight(C);
- Vector3 normal = GetNormal(A, B, C);
- if (normal.y < 0f) normal = -normal;
- Vector3 forward = transform.forward;
- if (keepForwardProjectedOnWave)
- {
- Vector3 forwardProj = Vector3.ProjectOnPlane(forward, normal);
- if (forwardProj.sqrMagnitude > 0.001f) forward = forwardProj.normalized;
- }
- Quaternion raw = Quaternion.LookRotation(forward, normal);
- Vector3 rawEuler = NormalizeAngles(raw.eulerAngles);
- rawEuler.x = Mathf.Clamp(rawEuler.x, -maxPitchAngle, maxPitchAngle);
- rawEuler.z = Mathf.Clamp(rawEuler.z, -maxRollAngle, maxRollAngle);
- rawEuler.y = transform.eulerAngles.y;
- targetRotation = Quaternion.Euler(rawEuler);
- }
- private void UpdateTargetYPos()
- {
- if (floatPoints == null || floatPoints.Length == 0)
- {
- targetYPos = OceanManager.Instance.GetOceanPointHeight(transform.position) + buoyancyOffset;
- return;
- }
- float sum = 0f;
- for (int i = 0; i < floatPoints.Length; i++)
- {
- Vector3 p = floatPoints[i].position;
- sum += OceanManager.Instance.GetOceanPointHeight(p);
- }
- targetYPos = (sum / floatPoints.Length) + buoyancyOffset;
- }
- public Vector3 GetMovementToYTarget()
- {
- Vector3 pos = rb.position;
- float smoothedY = Mathf.SmoothDamp(pos.y, targetYPos, ref yVelocity, verticalSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
- pos.y = Mathf.Lerp(pos.y, smoothedY, Mathf.Clamp01(verticalDamping * Time.fixedDeltaTime));
- return pos - rb.position;
- }
- private void MoveToRotationTarget()
- {
- Vector3 currentEuler = rb.rotation.eulerAngles;
- Vector3 targetEuler = targetRotation.eulerAngles;
- currentEuler = NormalizeAngles(currentEuler);
- targetEuler = NormalizeAngles(targetEuler);
- float newX = Mathf.SmoothDampAngle(currentEuler.x, targetEuler.x, ref pitchVelocity, pitchSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
- float newZ = Mathf.SmoothDampAngle(currentEuler.z, targetEuler.z, ref rollVelocity, rollSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
- float newY = targetEuler.y; // без сглаживания по yaw — ставим напрямую
- Vector3 smoothedEuler = new Vector3(newX, newY, newZ);
- rb.MoveRotation(Quaternion.Euler(smoothedEuler));
- }
- Vector3 GetNormal(Vector3 A, Vector3 B, Vector3 C)
- {
- Vector3 AB = B - A;
- Vector3 AC = C - A;
- Vector3 normal = Vector3.Cross(AB, AC).normalized;
- return normal;
- }
- Vector3 NormalizeAngles(Vector3 euler)
- {
- euler.x = NormalizeAngle(euler.x);
- euler.y = NormalizeAngle(euler.y);
- euler.z = NormalizeAngle(euler.z);
- return euler;
- }
- float NormalizeAngle(float a)
- {
- a = Mathf.Repeat(a + 180f, 360f) - 180f;
- return a;
- }
- void OnDrawGizmosSelected()
- {
- if (floatPoints != null)
- {
- Gizmos.color = Color.cyan;
- foreach (var p in floatPoints)
- {
- if (p) Gizmos.DrawSphere(p.position, 0.2f);
- }
- }
- Gizmos.color = Color.yellow;
- Gizmos.DrawLine(transform.position, transform.position + Vector3.up * (targetYPos - transform.position.y));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment