Guest User

Untitled

a guest
Dec 12th, 2025
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.32 KB | None | 0 0
  1. [RequireComponent(typeof(Rigidbody))]
  2. public class PlayerMovementRigidbody : NetworkBehaviour
  3. {
  4.     #region Variables
  5.  
  6.     [Header("References")]
  7.     [SerializeField] Transform playerCamera;
  8.  
  9.     [Header("Ground Check")]
  10.     [SerializeField] Transform groundCheck;
  11.     [SerializeField] float groundCheckSphereRadius;
  12.     [SerializeField] LayerMask groundMask;
  13.  
  14.     [Header("Player Settings")]
  15.     [SerializeField] float walkingSpeed;
  16.     [SerializeField] float swimmingSpeed = 3f;
  17.     [SerializeField] float mouseSensitivity;
  18.     [SerializeField] private float jumpHeight;
  19.     [SerializeField] private float airResistance = 1f;
  20.     [SerializeField] float airControlSpeed = 3f;
  21.  
  22.     [Header("Private References")]
  23.     Rigidbody rb;
  24.     ShipRB ship;
  25.  
  26.     [Header("Current State")]
  27.     [SerializeField] MovementMode currentMovementMode;
  28.     Vector2 inputMovementVector;
  29.     Vector3 finalMoveVector;
  30.     Vector2 rotationVector;
  31.     float xRotation = 0f;
  32.     [SerializeField] float currentSpeed; // current movement speed based on mode
  33.     [SerializeField] bool isGrounded;
  34.  
  35.     [Header("Constants")]
  36.     const float GRAVITY = -9.81f;
  37.  
  38.     #endregion
  39.  
  40.     #region Unity Methods
  41.  
  42.     void Start()
  43.     {
  44.         rb = GetComponent<Rigidbody>();
  45.  
  46.         ship = FindAnyObjectByType<ShipRB>();
  47.  
  48.         //REMOVE
  49.         currentMovementMode = MovementMode.OnLand;
  50.  
  51.         currentSpeed = walkingSpeed;
  52.        
  53.         SetupRigidbody();
  54.     }
  55.  
  56.     void OnEnable()
  57.     {
  58.         InputHandler.OnMove += SetInputMovementVector;
  59.         InputHandler.OnMouseMove += SetRotationVector;
  60.         InputHandler.OnPlayerJump += Jump;
  61.     }
  62.  
  63.     void OnDisable()
  64.     {
  65.         InputHandler.OnMove -= SetInputMovementVector;
  66.         InputHandler.OnMouseMove -= SetRotationVector;
  67.         InputHandler.OnPlayerJump -= Jump;
  68.     }
  69.  
  70.     void Update()
  71.     {
  72.         IsCharacterInWater();
  73.         IsCharacterGrounded();
  74.     }
  75.  
  76.     void FixedUpdate()
  77.     {
  78.         if (!IsHost && IsOwner && currentMovementMode == MovementMode.OnShip)
  79.         {
  80.             AlignPositionWithShip();
  81.         }
  82.  
  83.         if (IsOwner)
  84.         {
  85.             MovePlayerCharacter();
  86.         }
  87.     }
  88.  
  89.     void LateUpdate()
  90.     {
  91.         if (!IsOwner) return;
  92.  
  93.         RotatePlayerCharacter();
  94.     }
  95.  
  96.     #endregion
  97.  
  98.     #region Setups
  99.  
  100.     void SetupRigidbody()
  101.     {
  102.         rb.isKinematic = false;
  103.  
  104.         rb.constraints = RigidbodyConstraints.FreezeRotation;
  105.     }
  106.  
  107.     #endregion
  108.  
  109.     #region Movement
  110.  
  111.     void MovePlayerCharacter()
  112.     {
  113.         switch (currentMovementMode)
  114.         {
  115.             case MovementMode.OnLand:
  116.                 MoveOnASurface();
  117.                 break;
  118.             case MovementMode.OnShip:
  119.                 MoveOnASurface();
  120.                 break;
  121.             case MovementMode.InWater:
  122.                 MoveInWater();
  123.                 break;
  124.             case MovementMode.OnLadder:
  125.                 //Ladder movement logic here
  126.                 break;
  127.         }  
  128.     }
  129.  
  130.     private void MoveInWater()
  131.     {
  132.         currentSpeed = swimmingSpeed;
  133.  
  134.         finalMoveVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
  135.  
  136.         finalMoveVector.Normalize();
  137.  
  138.         rb.MovePosition(finalMoveVector * currentSpeed * Time.fixedDeltaTime + rb.position);
  139.     }
  140.  
  141.     private void MoveOnASurface()
  142.     {
  143.         if (isGrounded)
  144.         {  
  145.             currentSpeed = walkingSpeed;
  146.  
  147.             finalMoveVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
  148.         }
  149.         else
  150.         {
  151.             currentSpeed = Mathf.Lerp(currentSpeed, 0, Time.fixedDeltaTime * airResistance);
  152.         }
  153.  
  154.         // нормализация после расчётов
  155.         finalMoveVector.Normalize();
  156.  
  157.         Vector3 airControlVector = transform.forward * inputMovementVector.y + transform.right * inputMovementVector.x;
  158.  
  159.         rb.MovePosition(rb.position + finalMoveVector * currentSpeed * Time.fixedDeltaTime + airControlVector * airControlSpeed * Time.fixedDeltaTime);
  160.     }
  161.  
  162.     private void RotatePlayerCharacter()
  163.     {
  164.         float mouseX = rotationVector.x * mouseSensitivity * Time.deltaTime;
  165.         float mouseY = rotationVector.y * mouseSensitivity * Time.deltaTime;
  166.  
  167.         // vertical rotation
  168.         xRotation -= mouseY;
  169.         xRotation = Mathf.Clamp(xRotation, -90f, 90f);
  170.         playerCamera.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
  171.  
  172.         // horizontal rotation
  173.         transform.Rotate(Vector3.up * mouseX);
  174.     }
  175.  
  176.     private void AlignPositionWithShip()
  177.     {
  178.         /*
  179.         Vector3 vel = ship.GetVelocity();
  180.         vel.y = 0;
  181.  
  182.         rb.MovePosition(rb.position + vel * Time.fixedDeltaTime);
  183.         */
  184.  
  185.         Vector3 shipMovement = ship.currentShipVelocity.Value;
  186.         shipMovement.y = 0;
  187.  
  188.         rb.MovePosition(rb.position + shipMovement * Time.fixedDeltaTime);
  189.     }
  190.  
  191.     #endregion
  192.  
  193.     #region Actions
  194.  
  195.     private void Jump()
  196.     {
  197.         if (!IsOwner) return;
  198.  
  199.         if (isGrounded)
  200.         {
  201.             rb.AddForce(Vector3.up * Mathf.Sqrt(jumpHeight * -2f * GRAVITY), ForceMode.VelocityChange);
  202.         }
  203.     }
  204.  
  205.     #endregion
  206.  
  207.     #region Checks
  208.  
  209.     private void IsCharacterInWater()
  210.     {
  211.         float waterHeight = OceanManager.Instance.GetOceanPointHeight(transform.position);
  212.  
  213.         if (transform.position.y < waterHeight && currentMovementMode != MovementMode.OnShip)
  214.         {
  215.             SetMovementMode(MovementMode.InWater);
  216.         }
  217.     }
  218.  
  219.     private void IsCharacterGrounded()
  220.     {
  221.         isGrounded = Physics.CheckSphere(groundCheck.position, groundCheckSphereRadius, groundMask);
  222.     }
  223.  
  224.     #endregion
  225.  
  226.     #region Setters
  227.  
  228.     void SetInputMovementVector(Vector2 newMovementVector)
  229.     {
  230.         inputMovementVector = newMovementVector;  
  231.     }
  232.  
  233.     void SetRotationVector(Vector2 rotVector)
  234.     {
  235.         rotationVector = rotVector;
  236.     }
  237.  
  238.     public void SetMovementMode(MovementMode newMode)
  239.     {
  240.         currentMovementMode = newMode;
  241.     }
  242.  
  243.     #endregion
  244. }
  245.  
  246.  
  247.  
  248. [RequireComponent(typeof(Rigidbody))]
  249. public class ShipFloatingSmooth : MonoBehaviour
  250. {
  251.     [Header("Points & refs")]
  252.     [SerializeField] Transform[] floatPoints;
  253.     Rigidbody rb;
  254.  
  255.     [Header("Vertical (Y) settings")]
  256.     [SerializeField] float verticalSmoothTime = 0.5f;
  257.     [SerializeField] float verticalDamping = 1f;
  258.     [SerializeField] float buoyancyOffset = 0f;
  259.  
  260.     [Header("Rotation (pitch / roll) settings")]
  261.     [SerializeField] float pitchSmoothTime = 0.6f;
  262.     [SerializeField] float rollSmoothTime = 0.8f;
  263.  
  264.     [Header("Limits & feel")]
  265.     [SerializeField] float maxPitchAngle = 35f;
  266.     [SerializeField] float maxRollAngle = 40f;
  267.  
  268.     [Header("Optional extras")]
  269.     [SerializeField] bool keepForwardProjectedOnWave = true;
  270.  
  271.     float yVelocity = 0f;
  272.     float pitchVelocity = 0f;
  273.     float rollVelocity = 0f;
  274.  
  275.     Quaternion targetRotation;
  276.     float targetYPos = 0f;
  277.  
  278.     float yMovementThisFrame = 0f;
  279.  
  280.     void Start()
  281.     {
  282.         rb = GetComponent<Rigidbody>();
  283.         rb.isKinematic = true;
  284.         UpdateTargetYPos();
  285.         UpdateTargetRotation();
  286.     }
  287.  
  288.     void Update()
  289.     {
  290.         UpdateTargetYPos();
  291.         UpdateTargetRotation();
  292.     }
  293.  
  294.     void FixedUpdate()
  295.     {
  296.         MoveToRotationTarget();
  297.     }
  298.  
  299.     private void UpdateTargetRotation()
  300.     {
  301.         Vector3 A = floatPoints.Length > 0 ? floatPoints[0].position : transform.position;
  302.         Vector3 B = floatPoints.Length > 1 ? floatPoints[1].position : transform.position + transform.forward;
  303.         Vector3 C = floatPoints.Length > 2 ? floatPoints[2].position : transform.position + transform.right;
  304.  
  305.         A.y = OceanManager.Instance.GetOceanPointHeight(A);
  306.         B.y = OceanManager.Instance.GetOceanPointHeight(B);
  307.         C.y = OceanManager.Instance.GetOceanPointHeight(C);
  308.  
  309.         Vector3 normal = GetNormal(A, B, C);
  310.         if (normal.y < 0f) normal = -normal;
  311.  
  312.         Vector3 forward = transform.forward;
  313.         if (keepForwardProjectedOnWave)
  314.         {
  315.             Vector3 forwardProj = Vector3.ProjectOnPlane(forward, normal);
  316.             if (forwardProj.sqrMagnitude > 0.001f) forward = forwardProj.normalized;
  317.         }
  318.  
  319.         Quaternion raw = Quaternion.LookRotation(forward, normal);
  320.         Vector3 rawEuler = NormalizeAngles(raw.eulerAngles);
  321.         rawEuler.x = Mathf.Clamp(rawEuler.x, -maxPitchAngle, maxPitchAngle);
  322.         rawEuler.z = Mathf.Clamp(rawEuler.z, -maxRollAngle, maxRollAngle);
  323.         rawEuler.y = transform.eulerAngles.y;
  324.  
  325.         targetRotation = Quaternion.Euler(rawEuler);
  326.     }
  327.  
  328.     private void UpdateTargetYPos()
  329.     {
  330.         if (floatPoints == null || floatPoints.Length == 0)
  331.         {
  332.             targetYPos = OceanManager.Instance.GetOceanPointHeight(transform.position) + buoyancyOffset;
  333.             return;
  334.         }
  335.  
  336.         float sum = 0f;
  337.         for (int i = 0; i < floatPoints.Length; i++)
  338.         {
  339.             Vector3 p = floatPoints[i].position;
  340.             sum += OceanManager.Instance.GetOceanPointHeight(p);
  341.         }
  342.  
  343.         targetYPos = (sum / floatPoints.Length) + buoyancyOffset;
  344.     }
  345.  
  346.     public Vector3 GetMovementToYTarget()
  347.     {
  348.         Vector3 pos = rb.position;
  349.  
  350.         float smoothedY = Mathf.SmoothDamp(pos.y, targetYPos, ref yVelocity, verticalSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
  351.  
  352.         pos.y = Mathf.Lerp(pos.y, smoothedY, Mathf.Clamp01(verticalDamping * Time.fixedDeltaTime));
  353.  
  354.         return pos - rb.position;
  355.     }
  356.  
  357.     private void MoveToRotationTarget()
  358.     {
  359.         Vector3 currentEuler = rb.rotation.eulerAngles;
  360.         Vector3 targetEuler = targetRotation.eulerAngles;
  361.  
  362.         currentEuler = NormalizeAngles(currentEuler);
  363.         targetEuler = NormalizeAngles(targetEuler);
  364.  
  365.         float newX = Mathf.SmoothDampAngle(currentEuler.x, targetEuler.x, ref pitchVelocity, pitchSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
  366.         float newZ = Mathf.SmoothDampAngle(currentEuler.z, targetEuler.z, ref rollVelocity, rollSmoothTime, Mathf.Infinity, Time.fixedDeltaTime);
  367.  
  368.         float newY = targetEuler.y; // без сглаживания по yaw — ставим напрямую
  369.  
  370.         Vector3 smoothedEuler = new Vector3(newX, newY, newZ);
  371.         rb.MoveRotation(Quaternion.Euler(smoothedEuler));
  372.     }
  373.  
  374.     Vector3 GetNormal(Vector3 A, Vector3 B, Vector3 C)
  375.     {
  376.         Vector3 AB = B - A;
  377.         Vector3 AC = C - A;
  378.         Vector3 normal = Vector3.Cross(AB, AC).normalized;
  379.         return normal;
  380.     }
  381.  
  382.     Vector3 NormalizeAngles(Vector3 euler)
  383.     {
  384.         euler.x = NormalizeAngle(euler.x);
  385.         euler.y = NormalizeAngle(euler.y);
  386.         euler.z = NormalizeAngle(euler.z);
  387.         return euler;
  388.     }
  389.  
  390.     float NormalizeAngle(float a)
  391.     {
  392.         a = Mathf.Repeat(a + 180f, 360f) - 180f;
  393.         return a;
  394.     }
  395.  
  396.     void OnDrawGizmosSelected()
  397.     {
  398.         if (floatPoints != null)
  399.         {
  400.             Gizmos.color = Color.cyan;
  401.             foreach (var p in floatPoints)
  402.             {
  403.                 if (p) Gizmos.DrawSphere(p.position, 0.2f);
  404.             }
  405.         }
  406.  
  407.         Gizmos.color = Color.yellow;
  408.         Gizmos.DrawLine(transform.position, transform.position + Vector3.up * (targetYPos - transform.position.y));
  409.     }
  410. }
Advertisement
Add Comment
Please, Sign In to add comment