I’ve recently started learning Godot to make prototypes (and, ultimately, full production) for the next game. I have over 15 years of Unity experience and used several other languages and engines before that, so this is not going to be a complete newcomer’s introduction to game development. If you are, however, a bit more experienced game developer (and especially if you’re coming from Unity), I made this article to sum up things that I had to google and/or ask about. I was not able to find a written article about getting started with importing a few assets and plugging in some C# code, so hopefully, this one fills that niche for at least some people.
Alright, let’s get started.
I’m not an artist (and even if I were, I would still prefer to start protos with premade assets to save time) so the first thing I need is going to be a few assets. Namely, a character and some environment pieces. In Unity, the Asset Store would be the one-stop shop for all that, and the process of importing the Unity assets into Godot is (probably) not too complicated, but I don’t want to fire up Unity every time I need some assets, so I asked around for good alternatives for Godot. And boy, Mastodon delivered.
Here’s a short list:
- https://quaternius.com/
- https://www.thebasemesh.com/
- https://www.gdquest.com/news/2020/01/mannequiny-released/
- https://github.com/gdquest-demos/godot-4-3D-Characters
- OpenGameArt
- Kenney
- https://itch.io/game-assets
- Mixamo
I ended up starting with this character and uploaded it to Mixamo:
Another model I tried previous didn’t seem compatible, so you might need to try a few to find one that Mixamo knows how to work with. I assume they should have a standard humanoid rig. Next, I chose an idle animation that I liked and downloaded it with the settings below. Some articles and videos I found said to download it with skin, but I had no trouble getting the animations to work without either, so I preferred that.
Now we’re ready to get to Godot. Load up your project and place (copy, drag&drop, whatever you prefer) the model and the animation to your project (I used “models” as a name for the folder, feels like lowercase naming fits Godot):
Then go ahead and create a root node, in this case we’ll want a 3D scene. Everything in Godot is a Node and what you would call prefabs or GameObjects or scenes in Unity are all just Nodes. What’s funny (not actually funny), is that the button doesn’t actually create anything else than a Node3D. Not even a camera, so let’s create one now, too. Click on the ‘+’ button in the Scene tab (or ctrl+a), type camera in the search bar and select Camera3D. Alright, the second thing we need is a light. For reasons unknown to me, if there’s no light in the scene, Godot will only render a grey screen. So, I added a DirectionalLight3D.
We’re ready to add the character now! I always add an empty node first to hold everything, including the model, so if (when) I need to change the model, I can just keep the rest. So add another Node3D and rename (F2) it to “Player” (or whatever you like, really). Now drag the model onto that node.
Now we can actually hit play, see that the camera is way close to the character, move things around and finally end up with something like this:
Aside About Formats
According to the docs, Godot doesn’t technically know how to import FBX files – yet I just did. I think it uses Blender or something behind the scenes. So the preferred format is actually .gltf, which may or may not become popular in the future. Some assets are already available in that format and there are free converters. For whatever reason, I was not able to import a .gltf, only a .fbx.
Alright! Time for some sweet animations!
Double click on the animation file and you should see the advanced import settings. The animation from Mixamo will be called ‘mixamo_com’:
In the settings on the right, you need to enable ‘Save to File’:
After enabling ‘Save to File’, you get to choose the path (I made a folder ‘animations’) and the file name. You can change the other settings if you feel like it (I set the loop mode to linear) and then click the Reimport button on the bottom. Now you should have a .res file in the FileSystem:
Then, when I was first doing this, my question was, where is the animator component?! Or any other component or child for that matter! Well, turns out you need to enable ‘Editable Children’ (right-click on the model in the scene):
And voilá! You can see the children now:
Then, add a child node to the model and select ‘AnimationPlayer’ as the type. This is a simple animation component similar to the old Unity one. If you want something more akin to the Animator, there’s also AnimationTree. But I opted for the simple one this time.
To get the animation to play, there are a couple of additional steps, unfortunately. First, in the Animation tab below the scene view(s),
click the Animation button and choose ‘Manage animations:
Then add a New Library (I named it ‘Player’) and click on the folder icon to open an existing animation:
And select the .res file we created earlier. Then, for some reason, I needed to choose the rig node (in my case, meta_rig_002) and then again the AnimationPlayer to get the animation to show up in the ‘Current Animation’ list. Lastly, I turned on the ‘Autoplay on load’ to get the animation to play automatically:
Now, when you press play, you should see the character idling away like there’s no tomorrow!
That was a lot already! But we’re not done yet! Let’s do some coding to get the character to attack! (well, play the attack animation)
Attacking
First, we’ll define a key we’ll use to trigger the animation. To do that, head over to the Project Settings:
Switch to the ‘Input Map’ settings, type in the name of the action to the field below and press ‘Add’:
Next, I got another animation from Mixamo and imported it the same way I did with the idle. I added it to the library via ‘Manage Animations’ (see above) again.
Press the ‘+’ button to add key to the action:
So, now, finally, time to do some code!
I added a new script called PlayerControls, that inherits Node, which is pretty much the most vanilla class you can inherit. Godot should automatically create a .csproj for you, but if it didn’t you can also do it here:
By default, you have two methods: _Ready and _Process. They are roughly the same as Awake/Start and Update in Unity. Let’s add the code for reading the input first, since it’s the easier part:
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("Attack"))
{
GD.Print("Attack!");
}
}
This should be pretty straightforward: we’re asking the input system if the player just (i.e. on this frame) pressed the attack button, and if they did, we print out a debug line.
Then, I’ll just add the script to my ‘Player’ node by choosing the Quick Load option:
Now, when you run the game, pressing the attack button (space in my case) should print out the debug line:
Now we just need to tell the AnimationPlayer to play the animation, which… is trickier than you might expect. See, Godot doesn’t have a built-in equivalent of Unity’s GetComponentInChildred<>(), so we need to make out own. Fortunately, you can do it as an extension method really easily:
public static class NodeExtensions
{
public static T GetChildOfType<T>(this Node node) where T : Node
{
foreach (var child in node.GetChildren())
{
if (child is T node1)
return node1;
}
foreach (var child in node.GetChildren())
{
var result = child.GetChildOfType<T>();
if (result != null)
return result;
}
return null;
}
}
It’s a pretty simple recursive method that first iterates through all the children in a node (node.GetChildren) and then checks if any of them are of the type we want. If not, it calls itself on each of the children and finally returns null if no matching children were found.
With this handy helper method, we can cache the reference to the AnimationPlayer in _Ready():
private AnimationPlayer _animationPlayer;
public override void _Ready()
{
_animationPlayer = this.GetChildOfType<AnimationPlayer>();
}
And finally, we can call the AnimationPlayer’s Play method to play the animation:
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("Attack"))
{
GD.Print("Attack!");
_animationPlayer.Play("Player/attack", .4f);
}
}
The first parameter is the animation’s name preceded by the Library, the second is the blending time (somewhat weirdly named ‘customBlend’).
And we have an animation that can be triggered from the code!
Ok, one last thing!
We probably want the character to return to the idle animation after the attack is done, so let’s do that.
We need a private boolean to keep track of our state:
private bool _isAttacking;
And, in the _Process, we now check if the attack animation is still playing:
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("Attack") && !_isAttacking)
{
GD.Print("Attack!");
_animationPlayer.Play("Player/attack", .4f);
_isAttacking = true;
}
if (_animationPlayer.GetCurrentAnimation() != "Player/attack" && _isAttacking)
{
_isAttacking = false;
_animationPlayer.Play("Player/idle", 1f);
}
}
If the current animation is not the attack animation and we have attacked (_isAttacking is true), we revert back to the idle. Pretty simple, this part!
Ok, this post became a pretty lengthy one, so let’s end here! In the next part (whenever that may be), I’ll cover movement and collisions.