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.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5.0f;
public float jumpForce = 5.0f;
public float gravity = 9.81f;
public float sprintSpeedMultiplier = 2.0f;
private CharacterController controller;
private Vector3 moveDirection;
private bool isSprinting;
private float jumpTime = 0.0f;
public float maxSlopeAngle = 45.0f; // Максимальный угол наклона поверхности, на которой игрок может стоять
private void Start()
{
controller = GetComponent<CharacterController>();
}
public bool IsGrounded()
{
return controller.isGrounded;
}
private void Update()
{
// Управление перемещением
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector3 move = transform.TransformDirection(new Vector3(horizontalInput, 0, verticalInput));
// Выполняем лучевое попадание вниз от позиции игрока
RaycastHit hitInfo;
if (Physics.Raycast(transform.position, Vector3.down, out hitInfo))
{
// Проверяем угол наклона поверхности
float slopeAngle = Vector3.Angle(hitInfo.normal, Vector3.up);
if (slopeAngle > maxSlopeAngle)
{
// Применяем силу гравитации, учитывая угол наклона
Vector3 gravity = Physics.gravity * Mathf.Cos(Mathf.Deg2Rad * slopeAngle);
controller.Move(gravity * Time.deltaTime);
// Учитываем трение
float friction = 0.5f; // Настройте значение трения по своему усмотрению
Vector3 frictionForce = -controller.velocity.normalized * friction;
controller.Move(frictionForce * Time.deltaTime);
}
}
// Применение скорости бега, если зажата клавиша Shift
if (Input.GetKey(KeyCode.LeftShift))
{
isSprinting = true;
move *= moveSpeed * sprintSpeedMultiplier;
}
else
{
isSprinting = false;
move *= moveSpeed;
}
// Применение гравитации
if (!controller.isGrounded)
{
moveDirection.y -= gravity * Time.deltaTime;
}
else
{
// Сброс продолжительности прыжка при соприкосновении с землей
jumpTime = 0.0f;
}
// Прыжок
if (Input.GetButton("Jump") && jumpTime < 0.2f) // Зажатие кнопки Jump продолжит прыжок
{
moveDirection.y = jumpForce;
jumpTime += Time.deltaTime;
}
// Перемещение с учетом направления
moveDirection.x = move.x;
moveDirection.z = move.z;
// Применение перемещения
controller.Move(moveDirection * Time.deltaTime);
}
}
using UnityEngine;
public class SlippyController : MonoBehaviour
{
CharacterController cc;
Vector3 velocity;
RaycastHit hit;
float gravity=20f;
float slippy=10f; // How slippery are the slopes?
void Start()
{
cc=GetComponent<CharacterController>();
}
void Update()
{
Vector3 moveDirection=new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
if (cc.isGrounded)
{
// slide down slopes:
if (Physics.SphereCast(transform.position,0.5f,Vector3.down,out hit,5f)) // raycast to get the hit normal
{
Vector3 dir=Vector3.ProjectOnPlane(Vector3.down,hit.normal); // slope direction
velocity+=dir*Vector3.Dot(Vector3.down,dir)*gravity*slippy*Time.deltaTime;
}
velocity+=moveDirection;
velocity*=0.95f; // basic friction
}
else
velocity.y-=gravity*Time.deltaTime;
cc.Move(velocity*Time.deltaTime);
}
}
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…
using UnityEngine;
public class PlayerController : MonoBehaviour
{
CharacterController cc;
Vector3 velocity;
RaycastHit hit;
float gravity=9.81f;
float slippy=10f; // How slippery are the slopes?
void Start()
{
cc=GetComponent<CharacterController>();
}
void Update()
{
Vector3 moveDirection=((transform.right*Input.GetAxisRaw("Horizontal"))+(transform.forward*Input.GetAxisRaw("Vertical"))).normalized;
if (cc.isGrounded)
{
if (Input.GetButtonDown("Jump"))
velocity.y+=8;
if (Input.GetKey(KeyCode.LeftShift))
moveDirection*=2f;
// slide down slopes:
if (Physics.SphereCast(transform.position,0.5f,Vector3.down,out hit,5f)) // raycast to get the hit normal
{
Vector3 dir=Vector3.ProjectOnPlane(Vector3.down,hit.normal); // slope direction
velocity+=dir*Vector3.Dot(Vector3.down,dir)*gravity*slippy*Time.deltaTime;
}
velocity+=moveDirection;
velocity*=0.95f; // basic friction
}
else
{
velocity+=moveDirection*0.2f;
velocity.y-=gravity*Time.deltaTime;
}
cc.Move(velocity*Time.deltaTime);
}
}
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.