How to Move and Animate a 2D Sprite using AnimationTree in Godot
Вставка
- Опубліковано 14 лип 2024
- Learn how to move and animate a top down 2d sprite in Godot. I go over basic physics movement, AnimationPlayer, and AnimationTree.
Spritesheet: raw.githubusercontent.com/jon...
Code: github.com/jontopielski/Top-D...
00:00 - Intro
00:07 - Scene Setup
00:45 - Movement Code
01:44 - Fix Movement
02:11 - AnimationPlayer
03:09 - AnimationTree
05:17 - Fix Directions
06:15 - Add Walk State
07:45 - Change Side Frame
08:28 - End
This was fantastic. Didn't waste any time and packed a lot of information in efficiently and clearly.
didn't work for me.
@@FilipeRinaldi you probs did it wrong
@@ZiRR0 i did something the person in the video didnt do cause i kept getting errors and it worked.
Very fast. Would not recommend for early users unless you plan on watching multiple times, and pause on a few spots, but very informative and worthwhile altogether!
Really loving your tutorial, they're brief and the code is very clean.
Really great video, lots of information and straight to the point, and very easy to understand. Keep it up!
Fast and to the point! Brilliant!!!
Really clear and to the point. Thank you!
neat, to the point and with a practical example. really good tutorial! :)
thanks
Nice, AnimationTree has improved a lot since last time I've seen it.
Super concise and great. Thanks man 👍
Nice! You even touched my concern which was using the up and down instead when going at an angle lol
Great stuff, straight to the point. Cheers mate
Exactly as condensed as i needed
Damn brother.. what a wonderful tutorial.. i was havinhg a issue from past 3-4 days.. thanks alot..god bless you..put more videos..and do post the godot videos.. people need things.
Finely 😌 Amazing tutorial 👏
Exactly what I needed and no nonsense
Cool tutorial. Thanks!
gosh that was so easy and straight forward to watch!
thanks, very good tutorial man
felicitaciones, el mejor video que he visto en yt de este tema, excelente de verdad. ganaste un subscriptor
4:23 one important thing that one might miss - do change blending from linear to discrete
it was mentioned in the video but can be easily overseen
your video helped alot!
Good tutorial about AnimationTree node
tnx soo much u help a lot ❤❤
short and sweet
Thanks man
Thank you :D
Thank you!!!
Good job!!!!
Dream of tutorials
I feel today was a success. I hit a few snaggs but closely looking at the code I ended in the same place as him. Very nice tutorial!!!!
export doesn't work for some reason '-'
the best explication
U made it look easy
if you have access to the pause button and don't mind pressing it every 2 seconds, then this is a great tut.
Understandable!
i am your 900th subscriber!
medal please
thanks
._.
أنت ليش هنا؟؟
For the C# version here's the code;
Note that this version has the animations bugged tho
public class Player : KinematicBody2D
{
[Export] public int speed = 200;
public Vector2 velocity = new Vector2();
public void GetInput()
{
velocity = new Vector2();
if (Input.IsActionPressed("ui_right")) velocity.x += 1;
if (Input.IsActionPressed("ui_left")) velocity.x -= 1;
if (Input.IsActionPressed("ui_down")) velocity.y += 1;
if (Input.IsActionPressed("ui_up")) velocity.y -= 1;
velocity = velocity.Normalized() * speed;
}
public override void _PhysicsProcess(float delta)
{
GetInput();
if (velocity == Vector2.Zero)
{
GetNode("/root/Node2D/Player/AnimationTree").Get("parameters/playback").Equals("Idle");
}
else
{
GetNode("/root/Node2D/Player/AnimationTree").Get("parameters/playback").Equals("Walk");
GetNode("/root/Node2D/Player/AnimationTree").Set("parameters/Idle/blend_position",velocity);
GetNode("/root/Node2D/Player/AnimationTree").Set("parameters/Walk/blend_position", velocity);
velocity = MoveAndSlide(velocity);
}
}
i remade your code and fixed the animation problem ! -
using Godot;
using System;
public class PlayerController : KinematicBody2D
{
[Export] public int speed;
Vector2 velocity = new Vector2();
public override void _Ready()
{
}
public void GetInput()
{
velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_right")) velocity.x += 1;
if (Input.IsActionPressed("ui_left")) velocity.x -= 1;
if (Input.IsActionPressed("ui_down")) velocity.y += 1;
if (Input.IsActionPressed("ui_up")) velocity.y -= 1;
velocity = velocity.Normalized() * speed;
}
public override void _PhysicsProcess(float delta)
{
GetInput();
AnimationTree myAnimTree = GetNode("AnimationTree");
AnimationNodeStateMachinePlayback stateMachinePlayback = (AnimationNodeStateMachinePlayback)myAnimTree.Get("parameters/playback");
if(velocity == Vector2.Zero)
stateMachinePlayback.Travel("Idle");
else
{
stateMachinePlayback.Travel("Walk");
myAnimTree.Set("parameters/Idle/blend_position", velocity);
myAnimTree.Set("parameters/Walk/blend_position", velocity);
MoveAndSlide(velocity*speed);
}
}
// // Called every frame. 'delta' is the elapsed time since the previous frame.
// public override void _Process(float delta)
// {
//
// }
}
the reason you had problems with the animations is because you were using AnimationTree.equals and that checks to see if it is equal to the parameters u put inbetween the parenthesis. In order to acess the travel function in c# we need to create a reference of the AnimaionNodeStateMachinePlayback and with this we can call the travel function.
@@GamerPlaya12 i dont know how i found you reply few minutes ago on a few months old video
@@JeloOW hope it helps u with converting this and other scripts to c# !
Nah nah, i mean its very AWESOME, but how about releasing MUCH more content? :D
ps. subbed.
NON-EXISTENT FUNCTION 'TRAVEL' IN BASE NILL. please tell me what can I do now
you've probably typed something wrong in the string argument in ("parameters/...")
have you fixed this problem? please let me know i got the same problem. been looking through the code back and forth and nothing seems wrong
@@31_muhammadiqbaltrikiswoyo34 yes bro I fixed that.
You have to add a function of travel in player code and give it a value.
If you understand then you can apply or watch my upcoming video tutorial for fix it it was the next one.
Have a nice day and make sure to subscribe 😊
@@MrHarumakiSensei Yep, immediately fixed the issue. I am I L L I T E R A T E
I have dead ass the exact same thing and yet my move and slide isn’t working
Thanks! This is going to help me with a yume nikki related project.
jeez that typing was fast
After 2 years I hope this still works.
It didn't work. I made it exactly how you did, but when I try to use it it doesn't move the character at all! Help!!
woa that fast
Im 1 minute into the vid and i already dont know what's going on
Hi, bro?
Thanks for lessons
I dont know inglish, but you're a pro
Awesome video also what language do you use to code?
GDscript, Godot’s built in scripting language
For some reason it starts in "idle" but after the "walk" animation it keeps on looping the walk. Return on the nodes is there, no idea what I'm doing wrong
I followed everything and did it in c# instead of GDScript and the player just wont face right or left. It stays on the animation i put in the animationtree and it wont update ingame
very helpful except the spritesheet seems to only have, idle and walk for Up, Down, and Left, not sure how to do right. My first thought was to mirror the left one but i have no idea how to do that and i can't find anything about it in the docs or online, any help would be appreciated :)
EDIT: I keep thinking I got it figured out until I check the animationTree and it only shows either left or right, plus up & down. I tried to select "Flip H" but then it seems to only use one direction... and unchecking it uses the other always regardless of which animation is selected
Hey you’re pretty close! Just add a new track for the flip_h variable in the animationplayer and set it to true for the right animations and false for the left animations
@@jontopielski6227 thank you so much !! Also I have a sort of general question, if I wanted to follow this process for another sprite, and the sprite zip comes with a separate png for each position, how do I get godot to only use that specific png for one specific direction / state. sorry if it's a dumb question i'm very new to godot
@@TheJason118511 You can actually "animate" a different sprite by adding a new key section to the animationplayer and setting a new sprite.
There are a couple ways to do this but while both the sprite and the animationplayer are in your scene, click on the sprite and then click "Animation" at the bottom of the screen. A key should appear next to every variable on the node. After initializing a new animation in the animationplayer, you can click on the key while a new sprite is active and it will log the setting of that sprite into the animation.
There are no dumb questions! Godot and especially the animationplayer has a learning curve and it takes a while to get the hang of how things should be done the "godot" way. Good luck and let me know if you're still stuck on anything!
@@jontopielski6227 thanks again ! I ended up connecting the dots that you can keep track of more than just the frames in the animation, but also the texture and really anything with a key next to it
Hey If the scrpit dosent work for you use this one.
extends KinematicBody2D
var speed = 200
var velocity = Vector2()
func _ready():
pass
func _physics_process(delta):
velocity = Vector2()
if Input.is_action_pressed("down"):
velocity.y += speed
if Input.is_action_pressed("up"):
velocity.y -= speed
if Input.is_action_pressed("left"):
velocity.x -= speed
if Input.is_action_pressed("right"):
velocity.x += speed
move_and_slide(velocity)
look_at(get_global_mouse_position())
Hi! First of all, Thank you for this video.
How did you make the OnScreenKeyboard? I´m new in this (Godot and programing) and I´m trying to create something like that. I need a frame to change only when and while I´m pressing a key but I can´t make it reset to the original frame after.
And Again, Thank you!
Hi, you can see the on screen keyboard scene in the source code here: github.com/jontopielski/Top-Down-Sprite-Tutorial
@@jontopielski6227 Thank You!!!!!!!!
Video on this would be awesome even with the code i have no idea what to do lol
awsome tutorial. how do i get the arrows to show while im previewing the project like it does on yours? thank you !
Checkout the OnScreenKeyboard scene in the project here: github.com/jontopielski/Top-Down-Sprite-Tutorial/tree/master/ui
@@jontopielski6227 Thank you Jon , slowly working thru this video ! appreciate you
I was trying to do a similar thing with the Godot 2D game demo in the documentation. For some reason, the character is moving diagonally when I push the right and left keys. Here is the code I am using. Not certain what is wrong.
extends Area2D
export var speed = 400
var screen_size
func _ready():
screen_size = get_viewport_rect().size
func _process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed("move_right"):
velocity.x += 1
if Input.is_action_pressed("move_left"):
velocity.x -= 1
if Input.is_action_pressed("move_up"):
velocity.y -= 1
if Input.is_action_pressed("move_down"):
velocity.y += 1
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite.play()
else:
$AnimatedSprite.stop()
position += velocity * delta
position.x = clamp(position.x, 0, screen_size.x)
position.y = clamp(position.x, 0, screen_size.y)
same thing, not sure what to do with it. I am trying to find it everywhere but I didnt find anything.
if i change the playback speed nothing changes so how do i make the animation go slower
Got this working in 3.5.1-stable, but it broke when I switched to 4.0-b6. Still trying to figure out why it wont work.
Currently need help with something
I have everything set up correctly (and practically the same)
Yet the animations for walking always just goes in one direction (for me it’ll only use the left walking animations)
Make sure you spelled walk or idle properly and its case sensitive so if your walk tree is called Walk you need the capital W
Mee too and I spelled it correctly :(
I write the script like you are but the animation didn't work
hi there i get a message for line 18 in the script whereby the error states ....parser error the identifier "onScreenKeyboard" isn't declared in the current scope. any wonder what this means thanks in advance.
me too did you find answer for it now?
remove everything onscreenkeyboard related in your script, i know this is old but others might look at this comment
For some reason even after restarting the engine, no matter what direction I walk in it only shows walking up
Ok so 10 seconds in "new character and save as player" i have no idea or prompt to save, do I have to pay? Or am I just missing something
I did it, but i have a problem, the inside animation tree is missing, like it went invisible but the animation still works, need help
why when I use animation tree and move the character through it, the character doesn't move ?
i did this i have no errors but when ever i play the scene nothing happens im still in idle its almost like its not recognising me use the arrow keys what do i do
Is your player character moving at all? I would double check your velocity setting and movement code. You can always reference the project code here: github.com/jontopielski/Top-Down-Sprite-Tutorial
Hi! I can't seem to run the scene because of an error "The identifier "OnScreenKeyboard" isn't declared in the current scope. Is there anyway to fix this?
Does anyone know how to fix the shaking/jittering of the pixel art character when moving diagonally?
Jittery diagonal 2d movement is a known side effect when pixels snap to a grid (or in Godot terms, when the window setting's stretch mode is set to Viewport instead of 2D).
There should be tutorials available online for addressing this (I'm not sure exactly how it works), or, just set your window setting stretch mode to 2D.
does the sprite sheet have to be in a straight line?
No, it can be any combination of rows or columns, you just have to specify it in the hframes and vframes properties of the sprite
2:33 How do you go up in framecount and key in frames so fast?
is there ay way it can move and play the animations at the sam time
F5
Hi, I am new to this, I tried everything but even after two days of struggle my player is moving diagonally when i press left or right and not moving at all when i press up or down. Animations are working but i have no idea what to do. PLEASE HELP !!! :/ ill send my code after if you want but i really need help please
How to you code the buttons?
hey, thanks! idk why everyone's so confused. one thing though, when I walked left it played the animation for right, and the other way around. I switched the animations and that seemed to fix it. idk why it happened, could you help? could it cause future problems?
I have the same problem, how can I switch the animation?, Im new in programming I dont know how to do it, please.
i t s l i t e r a l l y e x p l a i n e d i n t h e v i d e o
I just got into game dev and this video help.Also anyone got any tips?
Game jams are a great way to get started making stuff. I recommend checking out the jams on itch.io. Godot wild jam is a good one and has a discord community.
has anyone done this in c# because it doesnt work.
When I play it I can move but it doesnt rotate
The character in the video appears much bigger than it does in mine and I can't for the life of me figure out why
I can't find the kinematic body option :(
Update this is because its been renamed as characterbody2D
It's now characterbody2D
i'm surprised. i think i understood most of that
Every time i type a way to walk it does not work
My character does not even move
your spritesheet does not include walking right and misses the 48th frame, as well as being pixelated and not very sharp. :{ Besides that it's a damn good tutorial, nice and quick without wasting time
Edit: with pixelated I mean that the maby 100x100 guy is being upscaled to like at least 200x200, making edges very washy and not nice and clean like in the video
thank you i got it , but.. what is normalized
Reduce a vector size down to a length of 1
is this made with gdscript or c#
GDScript
$Animationtree is null when coding the movement animation
A bit too fast, otherwise really straight forwad, thanks!
why is this so painful.
you should have a face cam. great vid btw
Have to disagree: It wouldn't add anything useful to the video and we have more than enough "tutorials" with face cams. However, the kind of videos Jon Topielski creates (short, informative & straight to the point) are very rare. Think they are great the way they are ;)
@@patrickklein9328 mhm, especially with how varied godot is in its ui the facecam will almost always be blocking something important at some point
can mobile players use it?
no
thanks for the tutorial, i think you did it faster this time cuz you had failed attempts idk
I have followed all the steps and there is one area where I get stuck AND IT DOESN'T SEEM TO WORK. I have created all the movements using the animation player, followed the animation tree and now i am entering the code.
Now here is the code: ( ALMOST THE SAME AS YOURS ) THE PROBLEM THAT I HAVE IS THAT THE ANIMATIONS ARE NOT WORKING. MY GUYS IS MOVING AROUND BUT NOT ANIMATING. THERE IS A PROBLEM BETWEEM THE ANIMATIONTREE, THE ANIMATIONPLAYER, AND THE CODE...
extends KinematicBody2D
var speed = 200 # MOVING SPEED
var velocity = Vector2.ZERO
func _physics_process(delta):
var velocity = Vector2.ZERO
# VECTOR = FRAMES PER MINUTE
if Input.is_action_pressed("ui_right"): # ui = button pressed
velocity.x = +1 # .x = Y AXIS or X AXIS
if Input.is_action_pressed("ui_left"):
velocity.x = -1
if Input.is_action_pressed("ui_down"): # ui = button pressed
velocity.y = +1 # .x = Y AXIS or X AXIS
if Input.is_action_pressed("ui_up"):
velocity.y = -1
velocity = velocity.normalized() # DIAGONAL MOVEMENT NORMALIZED
$AnimationTree.set("parameters/idle/blend_position",velocity)
move_and_slide(velocity * speed)
Also the ELSE statement does not work! I constantly. Also the $AnimationTree.get("parameters/playback").travels("idle) does not work because my GODOT Engine says that there are not enought statements in the .get or soemthing like that!
@@thestoryman1984 Hi Richard, I would start by double checking your AnimationTree. AnimationTree is stubborn in the sense that a lot of little things have to be setup precisely otherwise it won't work. Some of those include:
- setting the initial state in the AnimationTree (03:28)
- setting the node curve to discrete (dotted) values instead of a smooth curve (04:23)
- adding transitions between states (06:57)
If you are seeing issue with .get on the AnimationTree, make sure you can see the thing you are trying to get in the side panel on the right. For example, in the video I did .get("parameters/playback") and at 06:57, you can see a "Parameters" tab and beneath it, "Playback".
I encourage you to import the code used in this video into your own Godot and cross reference some of the functionality: github.com/jontopielski/Top-Down-Sprite-Tutorial
If you are still stuck, feel free to upload your source code and link it to me or ping me on discord and I can take a deeper look. (jontopielski#7219)
@@jontopielski6227 OK thank you! I will try again!
IT WORKED :-) THANK YOU VERY MUCH!!! YOU JUST NEED TO HAVE PATIENTS AND TRY< TRY< AND TRY AGAIN!!! THANK YOU!!!
One more thing. Is it possible for you to zoom in or enlarge the script writing. The letters are very small. Thank you very much for your help and support!
Awesome. But dont work well in godot402. I hope its just the current state of the rc.
i don't understand anything
bro you type too fast its amazing but make slow for us
Just adjust the video playback speed for anyone reading this in the future.
Ich raff gar nix, lutsch bipfel
BULL CRAP HE DOSENT EVEN EXPLAIN IT RIGHT THIS TOO 5 HOURS AND IT STILL DOSENT WORK
Hi, are you getting any errors? Happy to help you work through your issues.
you got some issues, calm down
why does my code get an error message saying "Invalid call. nonexistent function 'travel' in base 'Vector2'"? i can run it, however when i tried to move the character it shows that error
extends KinematicBody2D
export(int)var speed = 100.0
var animationPlayer = null
func _physics_process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_right"):
velocity.x += 2.0
if Input.is_action_pressed("ui_left"):
velocity.x -= 2.0
if Input.is_action_pressed("ui_up"):
velocity.y -= 2.0
if Input.is_action_pressed("ui_down"):
velocity.y += 2.0
velocity = velocity.normalized()
if velocity == Vector2.ZERO:
$AnimationTree.get("parameters/playback").travel("Idle")
else:
$AnimationTree.get("parameters/playback").travel("Walk")
$AnimationTree.set("parameters/Idle/blend_position", velocity)
$AnimationTree.set("parameters/Walk/blend_position", velocity)
move_and_slide(velocity * speed)
so good so smart. hack 101
Do I need to repeat this process every time if I have 1000 spritesheets of different monsters?