Inner Classes

2025/12/27

Type
Learning Resource
Format
Glossary Article
Version
General
Subject Tags
Code
Assets
All else
Copyright 2016-2026, GDQuest
Created
2026/02/16
Updated
2025/12/27

Inner Classes

Godot has two ways of creating new classes:

  1. Create a new script. Each script is a class (optionally named with the class_name keyword).
  2. Use the class keyword in a script. It creates an inner class.

Here's an example with two inner classes:

class Person:
	var name := ""
	var age := 0

class Superhero extends Person:
	var power := ""

Inner classes have a limitation compared to creating scripts: you cannot instantiate them from the editor, so you can't use them for nodes and resources that you'd like to interact with in the editor. You can only use them for data containers and helper classes.

But inner classes offer at least two benefits:

  1. They allow you to keep related classes grouped in a single file. It makes it easy to read and maintain related code.
  2. Their names are scoped locally, which helps to hide them from the rest of the project.

In this example, I define an inner class with a leading underscore, _Power to share code between the Flight and Fire classes and hide it from the outside world:

class_name Powers:

class _Power:
	var name := ""

class Flight extends _Power:
	var duration := 10

class Fire extends _Power:
	var strength := 5

With a script like this, anywhere in the project, you can call Powers.Flight.new() to create a new instance of Flight.

Grouping related classes together like this is something we call "namespacing". It compartmentalizes the code and helps to avoid naming conflicts. Imagine that you want a power named Fire and that you also need to define the magical element Fire in your game.

Because the Fire power is an inner class, you access it as Powers.Fire, and you can have two inner classes named Fire in the same project without conflicts.

Using inner classes for strongly typed data containers

Another feature of inner classes is to create well-typed objects to store data. Suppose I have a complicated function to get user properties for a web server connection. I could return a dictionary:

func get_connect_properties() -> Dictionary:
	return {
		"user_name": "AzureDiamond",
		"password": "hunter2",
		"server_ip": "localhost",
		"port": 3000,
		"role": "moderator"
	}

But then to know what keys are available, I need to look at the function's documentation or the source code. If I try to access a nonexistent key, I won't get any error until the game runs. It's a common source of bugs.

Instead, you can use an inner class to define the data structure:

class ConnectionProperties:
	var user_name: String
	var password: String
	var server_ip: String
	var port: int
	var role: String

func get_connect_properties() -> ConnectionProperties:
	var properties := ConnectionProperties.new()
	properties.user_name = "AzureDiamond"
	properties.password = "hunter2"
	properties.server_ip = "localhost"
	properties.port = 3000
	properties.role = "moderator"
	return properties

Now, when someone uses get_connect_properties(), they get a well-typed object with autocompletion and error reporting in the editor.

Become an Indie Gamedev with GDQuest!

Don't stop here. Step-by-step tutorials are fun but they only take you so far.

Try one of our proven study programs to become an independent Gamedev truly capable of realizing the games you’ve always wanted to make.

Nathan

Founder and teacher at GDQuest
  • Starter Kit
  • Learn Gamedev from Zero
Check out GDSchool

You're welcome in our little community

Get help from peers and pros on GDQuest's Discord server!

20,000 membersJoin Server

Contribute to GDQuest's Free Library

There are multiple ways you can join our effort to create free and open source gamedev resources that are accessible to everyone!