Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Physics.Raycast and hovering

Discussion in 'Physics' started by VascoCorreia, Mar 9, 2023.

  1. VascoCorreia

    VascoCorreia

    Joined:
    Dec 5, 2020
    Posts:
    23
    Hello,

    I am creating a spirit character and he is supposed to hover 1 unit above the ground always.
    I am using a Character Controller component for the movement.

    To detect if the player is on the ground I started by doing a simple ray cast down starting from the player's spirit position. But I quickly realized this will not work since when the character jumps the ray cast can go inside of surfaces.
    Besides this, the character is not exactly 1 unit above in the Y axis as if you check in the video attached. (it is always a value between 0.90 to 0.99)
    I tried fixing this but I could not, and I feel like it is because Controller.Move() is the last function called in my controller script.

    Link to demonstrarion:


    Does anyone have some tips on how I can achieve this?
    Thank you!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. //Use arrows and numpad 0 and 1 to move spirit
    7. public class SpiritPlayerController : MonoBehaviour
    8. {
    9.     [SerializeField] private float _hoverHeight;
    10.     [SerializeField] private Vector3 _velocity;
    11.     [SerializeField] private Camera _spiritCamera;
    12.     [SerializeField, Range(0f, 10f)] private float maxJumpHeight = 2f;
    13.     [SerializeField, Range(0f, 50f)] private float _maxSpeed = 10f;
    14.     [SerializeField, Range(0f, 25f)] private float pushPower = 3f;
    15.  
    16.     private CharacterController _controller;
    17.     private Vector2 _playerInput;
    18.     private float _ySpeed;
    19.  
    20.     private void Awake()
    21.     {
    22.         _controller = GetComponent<CharacterController>();
    23.     }
    24.     void Update()
    25.     {
    26.         getPlayerMovementInput();
    27.         calculateVelocityAndMove();
    28.     }
    29.  
    30.     private void LateUpdate()
    31.     {
    32.         applyGravity();
    33.     }
    34.  
    35.     //gets player movement input
    36.     private void getPlayerMovementInput()
    37.     {
    38.         _playerInput.x = Input.GetAxis("SpiritHorizontal");
    39.         _playerInput.y = Input.GetAxis("SpiritVertical");
    40.     }
    41.  
    42.     //This function is reponsible for continuously applying gravity to our human.
    43.     private void applyGravity()
    44.     {
    45.         _ySpeed += Physics.gravity.y * Time.deltaTime;
    46.  
    47.         //if we set it to zero the _controller.isGrounded property does not work as intended so we must set it to a small negative value
    48.         if (isGrounded())
    49.         {
    50.             _ySpeed = 0f;
    51.         }
    52.     }
    53.  
    54.     //this function calculates the velocity magnitude and direction of the current movement and after makes the character move.
    55.     //It is also responsible for listening to jumping input
    56.     private void calculateVelocityAndMove()
    57.     {
    58.         if (isGrounded() && Input.GetButtonDown("SpiritJump"))
    59.         {
    60.             Jump();
    61.         }
    62.  
    63.         //get player input
    64.         //get cameras forward and right vectors
    65.         //multiply input X vector by camera right vector
    66.         //multiply input Z vector by camera forward vector
    67.         //add these two vectors
    68.  
    69.         Vector3 forward = _spiritCamera.transform.forward;
    70.         Vector3 right = _spiritCamera.transform.right;
    71.         forward.y = 0;
    72.         right.y = 0;
    73.         forward = forward.normalized;
    74.         right = right.normalized;
    75.  
    76.         Vector3 forwardRelativeVerticalInput = forward * _playerInput.y;
    77.         Vector3 rightRelativeVerticalInput = right * _playerInput.x;
    78.  
    79.         Vector3 cameraRelativeMovement = forwardRelativeVerticalInput + rightRelativeVerticalInput;
    80.  
    81.         float magnitudeTest = Mathf.Clamp01(cameraRelativeMovement.magnitude) * _maxSpeed;
    82.  
    83.         cameraRelativeMovement.Normalize();
    84.         _velocity = cameraRelativeMovement * magnitudeTest;
    85.         _velocity.y = _ySpeed;
    86.         _velocity = AdjustvelocityToSlope(_velocity);
    87.  
    88.         _controller.Move(_velocity * Time.deltaTime);
    89.     }
    90.  
    91.     //https://screenrec.com/share/62pUYiuKDW
    92.     public void Jump()
    93.     {
    94.         _ySpeed += Mathf.Sqrt(maxJumpHeight * -2.0f * Physics.gravity.y);
    95.     }
    96.  
    97.     //removes bounciness when moving down slopes, keeps the direction of the movement align with the slope angle
    98.     private Vector3 AdjustvelocityToSlope(Vector3 velocity)
    99.     {
    100.         var ray = new Ray(transform.position, Vector3.down);
    101.  
    102.         if (Physics.Raycast(ray, out RaycastHit hitInfo, 2f))
    103.         {
    104.             var rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
    105.             var adjustedvelocity = rotation * velocity;
    106.  
    107.             //only adjust the _velocity if were moving down a slope which means out Y component of velocity must be negative, otherwise dont change velocity
    108.             if (adjustedvelocity.y < 0)
    109.             {
    110.                 return adjustedvelocity;
    111.             }
    112.         }
    113.         return velocity;
    114.     }
    115.  
    116.     private bool isGrounded()
    117.     {
    118.         Debug.DrawRay(transform.position, Vector3.down, Color.green);
    119.  
    120.         if(Physics.Raycast(transform.position, Vector3.down, _hoverHeight))
    121.         {
    122.             return true;
    123.         }
    124.  
    125.         return false;
    126.     }
    127. }
    128.  
     
  2. VascoCorreia

    VascoCorreia

    Joined:
    Dec 5, 2020
    Posts:
    23
    Any ideas?
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,428
    You may find this video useful:

     
    VascoCorreia likes this.
  4. UnityFledgling

    UnityFledgling

    Joined:
    Jan 30, 2022
    Posts:
    20
    Can this be used to move a hovering UFO game object that is simultaneously rotating along its Y Axis?