A character controller for 3D characters.
For use with Godot 4.6.1 and later.
The following dependencies are included in the addons folder and are required for the template to function.
- Copy the
dragonforge_controllerfolder from theaddonsfolder into your project'saddonsfolder. - Ignore any errors (they are appearing because the component is not yet enabled).
- Copy the
dragonforge_camerafolder from theaddonsfolder into your project'saddonsfolder. - Copy the
dragonforge_state_machinefolder from theaddonsfolder into your project'saddonsfolder. - Copy the
dragonforge_character_3dfolder from theaddonsfolder into your project'saddonsfolder. - In your project go to Project -> Project Settings...
- Select the Plugins tab.
- Check the On checkbox under Enabled for Dragonforge Controller
- Check the On checkbox under Enabled for Dragonforge Camera 3D
- Check the On checkbox under Enabled for Dragonforge Character 3D
- Press the Close button.
- Go to Project -> Reload Project. When the project reloads, the errors in step 2 should no longer appear and the new controls for movement, jumping and camera control will be enabled. (We cannot guarantee your own errors will not still appear.)
There are an infinite number of 3D models you can import. We are going to try and cover some of the free options.
The KayKit Adventurer Pack includes four free player models. If you purchase it, you can get two more. Since KayKit has a ton of models sharing the same rigging, this means we can use the same script and approach to load any KayKit models.
The first thing to do is to import the models. You can do this without a script, but this plugin has a script that handles a number of tasks, including: automatically looping all loopable animations; deleting custom BoneAttachmentNode3D nodes and creating generically named ones; moving all the equipment out of the character models but preserving them so you can copy them to their own nodes; rotating the model 180 degrees so it faces the forward (-Z axis); and, simplifies the names of the MeshInstance3D nodes.
- Download the pack.
- Copy the
Barbarian.glb,Knight.glb,Mage.glb, andRogue.glbfiles to your project. - Find the four
.glbfiles in the FileSystem area of your editor. - Holding down the Ctrl key (Command on Mac) click on each file to select it. (You want all four
.glbfiles selected, but not the.pngfiles.) - Click on the Import tab (next to the Scene tab).
- Scroll down to the Import Script section.
- Click on the Open File button next to the Path text box.
- Browse to
res://addons/dragonforge_character_3d/utilities/import/import_kay_kit_character_as_skin.gd - Click the Open button.
- Click the yellow Reimport(*) button.
- Wait for all the files to import.
Now that we have the models imported, we want to utilize the editor to make local copies we can edit of our models. Currently I don't know how to do this through code so it's a manual process.
- Create a new Scene with a Node3D as the root.
- Rename the Node3D node to Workspace an save it. (This scene is a temporary workspace but we don't want to lose anything to a crash while we are working.)
- Drag-and-drop the four
.glbfiles from FileSystem on top of the Node3D node. (You should have four Node3D nodes namedBarbarianSkinetc. under the first node.) - Right-click on the BarbarianSkin node and select Make Local from the pop-up menu. (The Open in Editor button will disappear.)
- Expand the BarbarianSkin node.
- Scroll down and find all the MeshInstance3D nodes after the AnimationPlayer.
- Move these nodes to the Workspace root node so they are no longer part of the BarbarianSkin node.
- Right-click on the BarbarianSkin node and select Save Branch as Scene from the pop-up menu.
- Select a location to save it. (I recommend
res://assets/skins/, but whatever works for you is fine.) - Press the Save button. (The Open in Editor button will re-appear once you save the file.)
- Repeat steps 3 to 10 for the other three models. NOTE: Once the skins are created this way, re-importing the model will have no effect on it.
Let's create a shield. We've created a Shield class and a ShieldResource class to get things started.
- Find the Barbarian_Round_Shield node under our Workspace node.
- Right-click the Barbarian_Round_Shield node and select Copy.
- Create a new scene.
- Press the Other Node button in the scene tree under the Create Root Node heading.
- Type "shield" in the search bar.
- Select the Shield node.
- Press the Create button.
- Right-click on the new Shield node and select Paste.
- Right-click the Shield node and rename it. (BarbarianRoundShield is a good name.)
- Save the node. (
res://equipment/shieldsis a good location.)
While it's not necessary to make the shield functionally work if it adds stats of some sort, if you do want it to work you can take the following steps.
- Make sure you are in 3D View by clicking the 3D button at the top middle of the Godot editor.
- Select the Barbarian_Round_Shield node (which is a MeshInstance3D node.)
- Click on the Mesh button that appears in the toolbar.
- Select Create Collision Shape... from the dropdown menu that appears.
- In the pop-up window under Collision Shape Placement select Static Body Child.
- In the pop-up window under Collision Shape Type select Trimesh.
- Select the StaticBody3D node.
- In the inspector, under CollisionObject3D -> Collision -> Layer select the layers you want to be blocked by this node. (See below.)
Selecting the layers you want to be affected determines what the shield blocks. Unless you're having issues with it colliding with the player model, just have it collide with everything. (If it does not collide with the environment, it will fall through the ground when dropped.)
- With the renamed BarbarianRoundShield selected, look at the Inspector on the right.
- Click the drop-down arrow next to the Resource field and select New Shield Resource
- Click on the ShieldResource that appears to expand it.
- Change the Defense value to
0.5.
Now that we have skins, we want to create scenes for all the individual items. Later on you'll want to add scripts to them but for now we are focusing on appearance.
- Find the Barbarian_Hat node under our Workspace node.
- Right-click the Barbarian_Hat node and select Save Branch as Scene.
- Select a location to save it. (I recommend
res://assets/accessories/, but whatever works for you is fine.) - Scroll back up to the BarbarianSkin node.
- Click the Open in Editor button to the right of the BarbarianSkin node. (It looks like the movie slates they use in movies to start a scene.)
- Select the HeadSlot node.
- Right click on the HeadSlot node and select Instantiate Child Scene... from the pop-up menu.
- Search for
barbarianin the window that pops up. - Select the
barbarian_hat.tscnfile. - Click on the 3D tab at the very top of the screen. (You will see the Barbarian is wearing the hat and it is in the right position on the model.)
You can repeat these steps for any items you want to keep. Alternately, you can just copy and paste the objects back in place on the model if you like in the appropriate slot. The import script was made to make it easier to swap out characters and mix/match equipment. So there's a little more work to re-equip the characters than just a straight import. However having all the models already loaded means you don't have to search in the Assets folder of the zipfile for as many things.
- Add the
res://addons/dragonforge_character_3d/player/player_3d.tscnscript to your CharacterBody3D node. (It is recommended that if you want to make any changes to the file, to inherit from it.)
- On your CharacterBody3D node click + Add Child Node... and select a Cameras node.
- On your Cameras node click + Add Child Node... and add as many Camera3D nodes as you like. Configure them however you like. The player will be able to rotate through them at will.
- If you haven't already, on your CharacterBody3D node click + Add Child Node... and select a Cameras node.
- On your Cameras node click + Add Child Node... and add a CameraMount3D node.
- Change the Upwards Rotation Limit to -15.
- Change the Downwards Rotation Limit to 40.
- Check the First Person box.
- Add the following code to your CharacterBody3D:
class_name Player extends Character
## Your character model
@export var rig: Node3D
## The speed at which the player turns.
@export var animation_decay: float = 20.0
##
@export var speed = 5.0
#A reference to your Cameras object
@onready var cameras: Cameras = $Cameras
var direction := Vector3.ZERO
func _physics_process(delta: float) -> void:
direction = get_input_direction()
velocity.x = direction.x * speed
velocity.z = direction.z * speed
if velocity.length() > 1.0 and direction != Vector3.ZERO:
look_toward_direction(delta)
move_and_slide()
func get_input_direction() -> Vector3:
var camera = cameras.active_camera
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
var input_vector := Vector3(input_dir.x, 0, input_dir.y).normalized()
if camera is CameraMount3D:
return camera.horizontal_pivot.global_transform.basis * input_vector
elif camera.rotation.y != 0.0:
return input_vector.rotated(Vector3.UP, camera.rotation.y).normalized()
else:
return transform.basis * input_vector
func look_toward_direction(delta: float) -> void:
var target := rig.global_transform.looking_at(rig.global_position + direction, Vector3.UP)
rig.global_transform = rig.global_transform.interpolate_with(target, 1.0 - exp(-animation_decay * delta))