|
|
|
 |
Reply From: |
USBashka |
It can be used to turn off effects that used for IN_AIR
state (and maybe play landing effect, not sure). If you have nothing to clean, just write pass
.
Thank you USBashika. I really appreciate your help. I have another problem that Id like to ask you. When I played the scene, the error occurs saying “Attempt to call function ‘enter’ in base ‘null instance’ on a null instance.” Do you have any idea why and how to fix it?
I simply copied and pasted script from the tutorial, so have no idea why this problem occurs.
# Generic state machine. Initializes states and delegates engine callbacks
# (_physics_process, _unhandled_input) to the active state.
class_name StateMachine
extends Node
# Emitted when transitioning to a new state.
signal transitioned(state_name)
# Path to the initial active state. We export it to be able to pick the initial state in the inspector.
export var initial_state := NodePath()
# The current active state. At the start of the game, we get the `initial_state`.
onready var state: State = get_node(initial_state)
func _ready() -> void:
yield(owner, "ready")
# The state machine assigns itself to the State objects' state_machine property.
for child in get_children():
child.state_machine = self
state.enter()
# The state machine subscribes to node callbacks and delegates them to the state objects.
func _unhandled_input(event: InputEvent) -> void:
state.handle_input(event)
func _process(delta: float) -> void:
state.update(delta)
func _physics_process(delta: float) -> void:
state.physics_update(delta)
# This function calls the current state's exit() function, then changes the active state,
# and calls its enter function.
# It optionally takes a `msg` dictionary to pass to the next state's enter() function.
func transition_to(target_state_name: String, msg: Dictionary = {}) -> void:
# Safety check, you could use an assert() here to report an error if the state name is incorrect.
# We don't use an assert here to help with code reuse. If you reuse a state in different state machines
# but you don't want them all, they won't be able to transition to states that aren't in the scene tree.
if not has_node(target_state_name):
return
state.exit()
state = get_node(target_state_name)
state.enter(msg)
emit_signal("transitioned", state.name)
amaou310 | 2022-07-14 13:11
You forgot to pick the initial_state
(Initial State) in the inspector tab. It is needed in _ready
function to enter to initial state.
USBashka | 2022-07-14 14:14
Thank you again. Understood that I need to assign the “Idle” in the inspector tab.
Another problem is that “Invalid set index ‘velocity’ (on base: ‘KinematicBody2D (player.gd)’) with value of type ‘Vector2’.” I have “player.velocity = Vector2.ZERO” in the PlayerIdle script, and “_velocity = Vector2.ZERO” in the Player script.
# Idle.gd
extends PlayerState
# Upon entering the state, we set the Player node's velocity to zero.
func enter(_msg := {}) -> void:
# We must declare all the properties we access through `owner` in the `Player.gd` script.
player.velocity = Vector2.ZERO
func physics_update(_delta: float) -> void:
# If you have platforms that break when standing on them, you need that check for
# the character to fall.
if not player.is_on_floor():
state_machine.transition_to("Air")
return
if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
state_machine.transition_to("Move")
Player script:
# Character that moves and jumps.
class_name Player
extends KinematicBody2D
# An enum allows us to keep track of valid states.
enum States {ON_GROUND, IN_AIR}
var _velocity = Vector2.ZERO
export var speed := 200.0
export var gravity := 1200.0
var ground_speed := 500.0
var air_speed := 300.0
var _speed := 500.0
# With a variable that keeps track of the current state, we don't need to add more booleans.
var _state : int = States.ON_GROUND
func _physics_process(delta: float) -> void:
var input_direction_x: float = (
Input.get_action_strength("move_right")
- Input.get_action_strength("move_left")
)
_velocity.x = input_direction_x * speed
_velocity.y = gravity * delta
_velocity = move_and_slide(_velocity, Vector2.UP)
var is_jumping: bool = _state == States.ON_GROUND and Input.is_action_just_pressed("move_up")
if is_on_floor():
_state = States.ON_GROUND
func change_state(new_state: int) -> void:
var previous_state := _state
_state = new_state
match _state:
States.IN_AIR:
_speed = air_speed
States.ON_GROUND:
_speed = ground_speed
match previous_state:
States.IN_AIR:
pass
amaou310 | 2022-07-15 04:20
Sorry for delay. I think it’s obvious: velocity
is not _velocity
USBashka | 2022-07-16 04:45
Thank you for the help USBashka. Tbh, this node based state machine was too difficult to implement for me. I wish I could do this, but I just gave up. Instead, I followed this tutorial and implemented much simpler state machine. Anyway, thank you for the help.
amaou310 | 2022-07-18 14:18