Need help with player movement,Help with character controller
Hi I'm in the early stages of working on a game and I am having some problems getting my player movements to work properly, so I thought I might try my luck and see if anybody in here would be able to help me.
The problems I have is that I have made a statemachine to keep track of my states and rules for switching between them which seemed to work in the beginning but I can't seem to figure out the code to switch from walk to idle, fall to idle and fall to walk. If I try to add code to switch to idle when the player isn't moving I won't be able to walk at all since as as soon as I try to walk the state will immediately go back to idle, on the other hand if i jump as soon as i touch ground the player just stand still and I have to release my walk button and press it again to resume walking.
Below is the code I'm working on.
StateMachine.cs:
public interface IState
{
void Enter();
void Execute();
void ExecutePhysics();
void Exit();
}
public interface StateManaged
{
void RequestState(IState requestedState);
}
public class StateMachine
{
public IState currentState;
public void ChangeState(IState newState)
{
if (currentState != null)
currentState.Exit();
currentState = newState;
currentState.Enter();
}
public void Update()
{
if (currentState != null)
currentState.Execute();
}
public void FixedUpdate()
{
if (currentState != null)
currentState.ExecutePhysics();
}
}
PlayerController.cs
public class PlayerController : MonoBehaviour, StateManaged
{
StateMachine stateMachine = new StateMachine();
public float speed = 5.0f;
public float jump = 20.0f;
bool isGrounded = true;
private Rigidbody playerRigidbody;
private void Awake()
{
playerRigidbody = GetComponent<Rigidbody>();
}
void Start()
{
RequestState(new IdleState(this));
}
void Update()
{
Debug.Log(stateMachine.currentState);
CaptureInput();
stateMachine.Update();
}
void FixedUpdate()
{
UpdateStateFromPhysics();
stateMachine.FixedUpdate();
}
private void CaptureInput()
{
if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.D))
RequestState(new WalkState(this));
if (Input.GetButtonDown("Jump"))
RequestState(new JumpState(this));
}
private void UpdateStateFromPhysics()
{
if (playerRigidbody.velocity.y < -.01 && !isGrounded)
RequestState(new FallState(this));
}
#region
// Manage state transition rules
public void RequestState(IState requestedState)
{
Debug.Log(requestedState.ToString());
// Idle
if (requestedState is IdleState)
{
if (stateMachine.currentState is null || stateMachine.currentState is WalkState || stateMachine.currentState is FallState)
stateMachine.ChangeState(requestedState);
}
// Walk
if (requestedState is WalkState)
{
if (stateMachine.currentState is IdleState || stateMachine.currentState is FallState)
stateMachine.ChangeState(requestedState);
}
// Jump
if (requestedState is JumpState)
{
if (stateMachine.currentState is IdleState || stateMachine.currentState is WalkState)
stateMachine.ChangeState(requestedState);
}
// Fall
if (requestedState is FallState)
if (stateMachine.currentState is JumpState || stateMachine.currentState is WalkState)
stateMachine.ChangeState(requestedState);
}
public class IdleState : IState
{
PlayerController player;
public IdleState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
}
public void Execute()
{
}
public void ExecutePhysics()
{
}
public void Exit()
{
}
}
public class WalkState : IState
{
PlayerController player;
public WalkState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
}
public void Execute()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal") * player.speed, 0f, Input.GetAxis("Vertical") * player.speed);
player.playerRigidbody.transform.position += movement * Time.deltaTime;
}
public void ExecutePhysics()
{
}
public void Exit()
{
}
}
public class JumpState : IState
{
PlayerController player;
public JumpState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
Vector3 jumping = new Vector3(0, player.jump, 0);
player.playerRigidbody.AddForce(jumping, ForceMode.Impulse);
}
public void Execute()
{
}
public void ExecutePhysics()
{
}
public void Exit()
{
}
}
public class FallState : IState
{
PlayerController player;
public FallState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
}
public void Execute()
{
}
public void ExecutePhysics()
{
}
public void Exit()
{
}
}
#endregion
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613011257im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
State Machine Tutorial Question 0 Answers
how to move a gameobject based on a dice roll 1 Answer
Diagonal character movement 0 Answers
Is there any good examples or tutorials of using StateMachineBehaviour properly? 0 Answers
GetKey Problems 2 Answers