Делаю бег по стене, персонаж не выходит из стейта "wallrunning"
Делаю по тутору систему бега по стене, персонаж заходит в стейт бега по стене, однако не выходит из него. Потратил немало времени но так и не смог решить этот момент. Подумал, что из-за того что у меня всего один стейт проблема, сделал стейт ходьбы но проблема была не в этом. Пробовал сделать включение гравитации после выхода из состояния волрана, тоже не сработало.
Вот демонстрация: https://youtu.be/y4POPMRsjg4?si=xVXUcZJNsDtSRDMm
PlayerMovement
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Speed Display")]
public float speed; //переменная для проверки скорости
[Header("Movement")]
public float moveSpeed;
public float groundDrag;
public float jumpForce;
public float jumpCooldown;
public float airMultiplayer;
public float wallRunSpeed;
bool readyToJump = false;
[Header("Keybinds")]
public KeyCode jumpKey = KeyCode.Space;
[Header("Ground Check")]
public float playerHeight;
public LayerMask whatIsGround;
bool grounded;
[Header("References")]
public Transform orientation;
private Rigidbody rb;
public MovementState state;
public enum MovementState
{
wallrunning
}
public bool wallrunning;
[Header("Input")]
float horizontalInput;
float verticalInput;
Vector3 moveDirection;
private void Start()
{
//gameObject.GetComponent<PlayerMovement>().enabled = false;
StartCoroutine(CalcSpeed());
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true; //если не будет фриза, то игрок упадет (?)
readyToJump = true;
}
private void Update()
{
//ground check
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
//hangle drag
if (grounded)
rb.drag = groundDrag;
else
rb.drag = 0;
}
private void FixedUpdate()
{
MovePlayer();
SpeedControl();
}
private void MyInput()
{
if (Input.GetKey(jumpKey) && readyToJump && grounded)
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCooldown);
}
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
}
private void MovePlayer()
{
//calculate movement direction
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
if (grounded)
rb.AddForce(moveDirection * moveSpeed * 10f, ForceMode.Force);
else if (!grounded)
rb.AddForce(moveDirection * moveSpeed * 10f * airMultiplayer, ForceMode.Force);
}
private void SpeedControl()
{
Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
if (flatVel.magnitude > moveSpeed)
{
Vector3 limitedVel = flatVel.normalized * moveSpeed;
rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
}
}
// дисплей скорости
IEnumerator CalcSpeed()
{
bool isPlaying = true;
while (isPlaying)
{
Vector3 prevPos = transform.position;
yield return new WaitForFixedUpdate();
speed = Mathf.RoundToInt(Vector3.Distance(transform.position, prevPos) / Time.fixedDeltaTime);
}
}
private void Jump()
{
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
private void ResetJump()
{
readyToJump = true;
}
private void StateHandler()
{
//Mode - wallrunning
if (wallrunning)
{
state = MovementState.wallrunning;
moveSpeed = wallRunSpeed;
}
}
}
Wallrun
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallRun : MonoBehaviour
{
[Header("Wallrun")]
public LayerMask whatIsWall;
public LayerMask whatIsGround;
public float wallRunForce;
public float maxWallRunTime;
private float wallRunTimer;
[Header("Detection")]
public float wallCheckDistance;
public float minJumpHeight;
private RaycastHit leftWallHit;
private RaycastHit rightWallHit;
private bool wallLeft;
private bool wallRight;
[Header("Input")]
float horizontalInput;
float verticalInput;
[Header("References")]
public Transform orientation;
private Rigidbody rb;
private PlayerMovement pm;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
pm = GetComponent<PlayerMovement>();
}
void Update()
{
CheckForWall();
StateMachine();
}
private void FixedUpdate()
{
if (pm.wallrunning)
WallRunningMovement();
}
private void CheckForWall()
{
wallRight = Physics.Raycast(transform.position, /*Vector3.left*/orientation.right, out rightWallHit, wallCheckDistance, whatIsWall);
wallLeft = Physics.Raycast(transform.position, /*Vector3.left*/-orientation.right, out leftWallHit, wallCheckDistance, whatIsWall);
}
private bool AboveGround()
{
return !Physics.Raycast(transform.position, Vector3.down, minJumpHeight, whatIsGround);
}
private void StateMachine()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if((wallLeft || wallRight) && verticalInput > 0 && AboveGround())
{
if (!pm.wallrunning)
{
StartWallRun();
}
else
{
if(pm.wallrunning)
StopWallRun();
}
}
}
private void StartWallRun()
{
pm.wallrunning = true;
}
private void WallRunningMovement()
{
rb.useGravity = false;
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal;
Vector3 wallForward = Vector3.Cross(wallNormal, transform.up);
rb.AddForce(wallForward * wallRunForce, ForceMode.Force);
}
private void StopWallRun()
{
pm.wallrunning = false;
}
}