Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Question The physics of the player sliding on sloped surfaces

Discussion in 'Physics' started by Seeanax, Nov 6, 2023.

  1. Seeanax

    Seeanax

    Joined:
    Nov 6, 2022
    Posts:
    8
    Hello! Please help me with the player's physics. I have a script that is not based on "Rigidbody" but on "Character Controller." When I use the character controller in my script, I've come to the point of creating sliding physics on surfaces, and I've tried many things, asked neural networks, and searched for solutions, but I don't know how to make it work. Please help. I've recorded a video that provides more information.

    I'll also include my player movement code here.

    (I need more realistic physics so that the player can slide on inclined surfaces. For example, if the player is standing on a surface with a slight incline, they should not slide. But if the incline becomes steeper, they should start sliding slowly in the direction of the incline. They can resist to some extent, but if the incline is too steep, they should not be able to resist and should simply slide downward. It may not be entirely accurate, but I don't know how to achieve this, and I'm seeking your help. I'm just starting to learn all of this, and I don't fully understand everything.)



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     public float moveSpeed = 5.0f;
    8.     public float jumpForce = 5.0f;
    9.     public float gravity = 9.81f;
    10.     public float sprintSpeedMultiplier = 2.0f;
    11.  
    12.     private CharacterController controller;
    13.     private Vector3 moveDirection;
    14.     private bool isSprinting;
    15.     private float jumpTime = 0.0f;
    16.  
    17.     public float maxSlopeAngle = 45.0f; // Максимальный угол наклона поверхности, на которой игрок может стоять
    18.  
    19.     private void Start()
    20.     {
    21.         controller = GetComponent<CharacterController>();
    22.     }
    23.  
    24.     public bool IsGrounded()
    25.     {
    26.         return controller.isGrounded;
    27.     }
    28.  
    29.     private void Update()
    30.     {
    31.         // Управление перемещением
    32.         float horizontalInput = Input.GetAxis("Horizontal");
    33.         float verticalInput = Input.GetAxis("Vertical");
    34.         Vector3 move = transform.TransformDirection(new Vector3(horizontalInput, 0, verticalInput));
    35.  
    36.         // Выполняем лучевое попадание вниз от позиции игрока
    37.         RaycastHit hitInfo;
    38.         if (Physics.Raycast(transform.position, Vector3.down, out hitInfo))
    39.         {
    40.             // Проверяем угол наклона поверхности
    41.             float slopeAngle = Vector3.Angle(hitInfo.normal, Vector3.up);
    42.  
    43.             if (slopeAngle > maxSlopeAngle)
    44.             {
    45.                 // Применяем силу гравитации, учитывая угол наклона
    46.                 Vector3 gravity = Physics.gravity * Mathf.Cos(Mathf.Deg2Rad * slopeAngle);
    47.                 controller.Move(gravity * Time.deltaTime);
    48.  
    49.                 // Учитываем трение
    50.                 float friction = 0.5f; // Настройте значение трения по своему усмотрению
    51.                 Vector3 frictionForce = -controller.velocity.normalized * friction;
    52.                 controller.Move(frictionForce * Time.deltaTime);
    53.             }
    54.         }
    55.  
    56.         // Применение скорости бега, если зажата клавиша Shift
    57.         if (Input.GetKey(KeyCode.LeftShift))
    58.         {
    59.             isSprinting = true;
    60.             move *= moveSpeed * sprintSpeedMultiplier;
    61.         }
    62.         else
    63.         {
    64.             isSprinting = false;
    65.             move *= moveSpeed;
    66.         }
    67.  
    68.         // Применение гравитации
    69.         if (!controller.isGrounded)
    70.         {
    71.             moveDirection.y -= gravity * Time.deltaTime;
    72.         }
    73.         else
    74.         {
    75.             // Сброс продолжительности прыжка при соприкосновении с землей
    76.             jumpTime = 0.0f;
    77.         }
    78.  
    79.         // Прыжок
    80.         if (Input.GetButton("Jump") && jumpTime < 0.2f) // Зажатие кнопки Jump продолжит прыжок
    81.         {
    82.             moveDirection.y = jumpForce;
    83.             jumpTime += Time.deltaTime;
    84.         }
    85.  
    86.         // Перемещение с учетом направления
    87.         moveDirection.x = move.x;
    88.         moveDirection.z = move.z;
    89.  
    90.         // Применение перемещения
    91.         controller.Move(moveDirection * Time.deltaTime);
    92.     }
    93. }
    94.  

    Video:

     
  2. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    979
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SlippyController : MonoBehaviour
    4. {
    5.     CharacterController cc;
    6.     Vector3 velocity;
    7.     RaycastHit hit;
    8.  
    9.     float gravity=20f;
    10.     float slippy=10f; // How slippery are the slopes?
    11.  
    12.     void Start()
    13.     {
    14.         cc=GetComponent<CharacterController>();
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         Vector3 moveDirection=new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
    20.         if (cc.isGrounded)
    21.         {
    22.             // slide down slopes:
    23.             if (Physics.SphereCast(transform.position,0.5f,Vector3.down,out hit,5f)) // raycast to get the hit normal
    24.             {
    25.                 Vector3 dir=Vector3.ProjectOnPlane(Vector3.down,hit.normal); // slope direction
    26.                 velocity+=dir*Vector3.Dot(Vector3.down,dir)*gravity*slippy*Time.deltaTime;
    27.             }
    28.             velocity+=moveDirection;
    29.             velocity*=0.95f;   // basic friction
    30.         }
    31.         else
    32.             velocity.y-=gravity*Time.deltaTime;
    33.        
    34.         cc.Move(velocity*Time.deltaTime);
    35.     }
    36. }
    37.  
     
    Seeanax likes this.
  3. Seeanax

    Seeanax

    Joined:
    Nov 6, 2022
    Posts:
    8

    Thank you very much! You helped me a lot! You are the best !!!!
     
  4. Seeanax

    Seeanax

    Joined:
    Nov 6, 2022
    Posts:
    8


    Sorry, it’s not convenient for me to ask, but I just can’t make a normal code for moving with this physics, I tried to do it somehow but it doesn’t work.. Your code works very well and everything is fine, but I couldn’t insert it into my code and that’s it It doesn't work well at all. Please, if you can, help me with the code for moving, I’m completely confused and don’t understand anything..
     
  5. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    979
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerController : MonoBehaviour
    4. {
    5.     CharacterController cc;
    6.     Vector3 velocity;
    7.     RaycastHit hit;
    8.  
    9.     float gravity=9.81f;
    10.     float slippy=10f; // How slippery are the slopes?
    11.  
    12.     void Start()
    13.     {
    14.         cc=GetComponent<CharacterController>();
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         Vector3 moveDirection=((transform.right*Input.GetAxisRaw("Horizontal"))+(transform.forward*Input.GetAxisRaw("Vertical"))).normalized;
    20.         if (cc.isGrounded)
    21.         {
    22.             if (Input.GetButtonDown("Jump"))
    23.                 velocity.y+=8;
    24.             if (Input.GetKey(KeyCode.LeftShift))
    25.                 moveDirection*=2f;
    26.             // slide down slopes:
    27.             if (Physics.SphereCast(transform.position,0.5f,Vector3.down,out hit,5f)) // raycast to get the hit normal
    28.             {
    29.                 Vector3 dir=Vector3.ProjectOnPlane(Vector3.down,hit.normal); // slope direction
    30.                 velocity+=dir*Vector3.Dot(Vector3.down,dir)*gravity*slippy*Time.deltaTime;
    31.             }
    32.             velocity+=moveDirection;
    33.             velocity*=0.95f;   // basic friction
    34.         }
    35.         else
    36.         {
    37.             velocity+=moveDirection*0.2f;
    38.             velocity.y-=gravity*Time.deltaTime;
    39.         }
    40.         cc.Move(velocity*Time.deltaTime);
    41.     }
    42. }
    43.  
     
    Seeanax likes this.
  6. Seeanax

    Seeanax

    Joined:
    Nov 6, 2022
    Posts:
    8

    Thank you very much! I don't know if you will agree, but I hope so. Would you like to create a game with me? We can discuss the topic and the game idea here or wherever it's convenient for you. From my side, it might be a bit brazen, but if you don't mind, we can try to create something cool.