|
|
|
|
Reply From: |
Pomelo |
I havent worked with AnimationPlayer for a while, so I dont remember what exactly travel()
does , I think it esentially starts to plays the desired animation? If I am right, then your problem is that you are triggering travel() every frame, since it is inside a procces()
function (I think the last 3/4 questions I answered, were of people not realizing of procces()
triggering stuff, haha). I may be wrong though if travel()
works differently.
Without knowing the rest of your code and how you setted up your state machine, I dont have a “best” way to solve your issue, but what you have to do is make sure to not trigger travel()
every frame. I personally use setters in my state machines, to trigger stuff only when entering or exiting states.
Not related to your question, but maybe it will help. I think it is a good aproach to manage inputs in _unhandled_input()
and just let the input determine a normalized direction Vector3() and maybe a “strength” var (if you care to get the strength of the inputs). Then in procces()
you just move using this direction
Pomelo | 2022-06-24 14:27
To prevent the animation from being played each frame, instead of going into idle animation if the user didn’t press a direction, you should have is_moving = false
when the player releases forward or back. That way, pressing forward/back moves, the character only enter the moving animation when you initially pressed the button (not when you hold it down), just like you have, and when they release the button the player goes idle.
Your current logic right now is every frame a button hasn’t just been pressed, go idle. So your character will immediately stop after 1 tick
godot_dev_ | 2022-06-24 15:00
func _physics_process(delta):
handle_movement(delta)
func handle_movement(delta):
var direction = Vector3()
if Input.is_action_pressed("forward"):
direction += transform.basis.z
elif Input.is_action_pressed("backward"):
direction -= transform.basis.z
if Input.is_action_just_pressed("forward"):
is_moving = true
elif Input.is_action_just_pressed("backward"):
is_moving = true
if Input.is_action_pressed("left"):
null #You will dash to the left/right and I haven't gotten to that so I put null for now
elif Input.is_action_pressed("right"):
null
if Input.is_action_just_released("forward") or Input.is_action_just_released("backward"):
is_moving = false
if is_moving == true:
animation_mode.travel("WALK")
else:
animation_mode.travel("IDLE")
direction = direction.normalized()
this is what I got. The animations now play when they are supposed to, but it still doesn’t loop properly. @Pomelo when you said that don’t trigger travel every frame, I assumed @godot_dev_ provided a fix to that. If I weren’t to do it in physics process, where would I put my animations?
newgodot_user | 2022-06-25 00:04
I dont agree with what @godotdev wrote. as I said in my awnser, everything that you write in procces()
is “read” by the engine in every frame. I recomend you getting used to read the Documentation! For example I recomended you to read unhandled_input() and also understand setters (both come in handy so you dont end up using procces()
for everything).
now back to your problem, what you want to solve is not a matter of changing the state of your state machine, but when to trigger the animations. You could make a state machine that handles this, but since it seems you are quite new to coding I will recomend an easier but less powerfull aproach: (I wrote only what is relevant to the animation)
var is_walk_playing := false # write this outside of procees
if Input.is_action_pressed("forward") or Input.is_action_pressed("backward"):
if not is_walk_playing:
animation_mode.travel("WALK")
is_walk_playing = true
This way when you press forward, walk starts to play, but it wont trigger in the next frame even if you keep pressing, or even if the state is is_moving
. then when you to stop walking, make sure to do is_walk_playing = false
, so you can trigger the animation the next time.
Pomelo | 2022-06-25 01:28
I tried to implement the code you provided here (I put here the whole script. The part you provided is at the bottom):
extends KinematicBody
export var speed : float = 20
export var acceleration : float = 50
export var air_acceleration : float = 5
export var gravity : float = 0.98
export var max_terminal_velocity : float = 54
export var jump_power : float = 20
export(float, 0.1, 1) var mouse_sensitivity : float = 0.3
export(float, -90, 0) var min_pitch : float = -90
export(float, 0, 90) var max_pitch : float = 90
var velocity : Vector3
var y_velocity : float
onready var camera_pivot = $camerapivot
onready var camera = $camerapivot/cameraboom/Camera
onready var animation_tree = $AnimationTree
onready var animation_mode = animation_tree.get("parameters/playback")
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
animation_tree.active = true
func _process(delta):
if Input.is_action_just_pressed(“ui_cancel”):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
func _input(event):
if event is InputEventMouseMotion:
rotation_degrees.y -= event.relative.x * mouse_sensitivity
camera_pivot.rotation_degrees.x -= event.relative.y * mouse_sensitivity
camera_pivot.rotation_degrees.x = clamp(camera_pivot.rotation_degrees.x, min_pitch, max_pitch)
func _physics_process(delta):
handle_movement(delta)
func handle_movement(delta):
var direction = Vector3()
if Input.is_action_pressed("forward"):
direction += transform.basis.z
elif Input.is_action_pressed("backward"):
direction -= transform.basis.z
if Input.is_action_pressed("left"):
null
elif Input.is_action_pressed("right"):
null
direction = direction.normalized()
var accel = acceleration if is_on_floor() else air_acceleration
velocity = velocity.linear_interpolate(direction * speed, accel * delta)
if is_on_floor():
y_velocity = -0.01
else:
y_velocity = clamp(y_velocity - gravity, -max_terminal_velocity, max_terminal_velocity)
if Input.is_action_just_pressed("jump") and is_on_floor():
y_velocity = jump_power
animation_mode.travel("AIR")
velocity.y = y_velocity
velocity = move_and_slide(velocity, Vector3.UP)
func _unhandled_input(event):
var is_walk_playing := false # write this outside of procees
if Input.is_action_pressed("forward") or Input.is_action_pressed("backward"):
if not is_walk_playing:
animation_mode.travel("WALK")
is_walk_playing = true
if Input.is_action_just_released("forward") or Input.is_action_just_released("backward"):
if is_walk_playing:
animation_mode.travel("IDLE")
is_walk_playing = false
Honestly, I’m very clueless on this topic. I’ve only worked with the state machine once and I only really understand how to use it for 2D Top-Down games (e.g. Zelda-style games) through Heartbeast’s RPG tutorial.
It also might be a problem with my State Machine. Say, do you know how to use Blendspace 1Ds and animations in the state machine node? I’m pretty sure the Blendspace 1Ds can help with the transition from walk to sprint but when I tried it, it didn’t work.
This is how my state machine is currently put together:
Screenshot 2022-06-25 at 7.53.50 PM.png - Google Drive
newgodot_user | 2022-06-25 11:05
After watching https://www.youtube.com/watch?v=WY2cN9uG6W8 I’m currently making a transition from the State Machine to the Blend Tree. It seems very straightforward. Hopefully it works out.
newgodot_user | 2022-06-25 12:31