HomeVideos

Godot 4.6: Master Classes & Inheritance (Build a Droid Factory!)

Now Playing

Godot 4.6: Master Classes & Inheritance (Build a Droid Factory!)

Transcript

466 segments

0:01

Stop copying and pasting code. If you

0:04

want to make a game with 50 different

0:05

enemies, you don't need 50 completely

0:07

different scripts. I'm going to show you

0:09

how to write code once and then use it

0:11

to spawn an army of unique droids.

0:13

Welcome back to GDO Dev Checkpoint.

0:15

Today, we aren't just writing scripts.

0:18

We're building an architecture. We're

0:19

going to build a droid factory. And

0:22

thank you to our new Patreon member,

0:24

Elon. Your support helps keep the lights

0:26

on. Now, let's open up GDO 4.6 six and

0:29

get to work. First, we need to

0:31

understand what a class actually is.

0:33

Think of a class as a blueprint. A

0:35

blueprint for a house isn't the house

0:37

itself. You can't live in the paper, but

0:40

you can use that one blueprint to build

0:42

10 identical houses. The first thing

0:44

we're going to do is we're going to

0:45

create a new folder. Rightclick our root

0:48

folder in our file system. Create new

0:51

folder. We're going to name this folder

0:53

scripts.

0:55

In this scripts folder, we're going to

0:56

create right click, create new script.

0:59

We're going to call it droid. Create.

1:03

Now, we're going to delete all this

1:04

boiler plate. We don't need it. Up on

1:07

top here, what we want to do is write

1:08

class name. I'm going to call this class

1:11

name droid. Now, this class name droid

1:14

line is the magic. It tells GDAU, hey,

1:17

this isn't just a script file anymore.

1:19

This is a global type called droid. And

1:22

you're going to be able to now use this

1:24

droid anywhere in your project just like

1:26

you use node or sprite 2D. So in this

1:30

class, what we're going to have is a

1:31

variable serial number for a droid and

1:35

it's going to be of type string

1:38

and we're just going to set it initially

1:40

to x

1:42

00 x-0000

1:46

just a base default name. And then we're

1:48

going to have a battery level for our

1:49

droid. Let's set that base level to a

1:53

type int of 100. So fully charged. Now

1:57

when we build our droid, we're going to

1:59

initialize it with the initialize

2:01

function function underscore init.

2:04

You can tab to autocomplete,

2:07

but we're going to add

2:10

a parameter here in the parenthesis

2:12

called new serial.

2:15

We're going to change the serial number

2:17

and give them all unique serial numbers.

2:19

It's going to be of type string.

2:22

Perfect.

2:24

Enter down into the function. And then

2:26

we're going to set the serial number to

2:29

the new serial number. So then the

2:32

serial number we pass into this

2:33

initialize is going to become this

2:35

droid's new serial number.

2:37

Enter down. And then we're going to have

2:39

a print statement for the output. It's

2:41

going to be droid space,

2:44

comma, serial number,

2:48

comma, another quotations, has been

2:52

assembled.

2:54

So, this is going to say the droid, and

2:56

it's going to take the serial number

2:57

that's been assigned to it, and say it

2:59

has been assembled. Now, a robot needs

3:01

to do something. Let's give our droid a

3:03

job. Now, still in our droid script

3:06

here, I'm going to enter down a couple

3:07

times, create a new function. I call

3:09

this function perform task no

3:14

underscore.

3:16

In the beginning, it's going to be of

3:17

return type

3:19

void. So, we're not going to return

3:21

anything. And in this, we're going to

3:23

have a battery level that we're going to

3:25

minus saying

3:28

this task has been performed. Now, let's

3:30

take some battery away. Take 10 battery

3:33

away. So, 10%. Then we're going to print

3:36

in the output the serial number of our

3:39

jury comma quotation

3:43

colon space we're going to say idling 1

3:46

2 3 battery

3:49

at

3:52

comma after the string we're going to

3:54

pass in the battery level and then we're

3:57

going to add a percentage sign at the

3:59

end.

4:00

There we go. And then a parenthesy.

4:04

Make this bigger so you see it. There we

4:06

go. Save the script.

4:09

Now, this class is going to be the

4:11

default behavior for any generic droid.

4:15

I'm going to highlight the parameters in

4:17

this print statement here. So, it can be

4:18

a little confusing sometimes. Now, this

4:20

is the safe mode for printing. If you

4:23

tried to use the plus signs instead of

4:25

these commas, well, this wouldn't work.

4:27

It would actually crash. As you can see

4:30

here, you can't actually just put an int

4:33

into a strict language like GDScript.

4:37

So the only way you can do this is you

4:38

actually have more syntax with the str

4:42

and then take this battery level and if

4:45

you highlight it, you can press the

4:48

parenthesy

4:50

and then it puts parenthesis around it

4:53

and then it's okay to print just like

4:54

this. However, instead of doing it so

4:58

much like this, a lot less syntax just

5:01

to use a comma.

5:05

So, when you use commas, GDO says, "I

5:07

got you." It automatically converts

5:09

those numbers into text. It stitches

5:11

everything together into one nice debug

5:13

message and strictly type languages like

5:16

GDScript.

5:18

This throws an error because it's

5:19

ambiguous. It's addition versus

5:21

concatenation.

5:23

And this just saves us from having to

5:25

type string every time. Now to quick

5:27

side note, you might be wondering why in

5:28

it has an underscore, but our perform

5:30

task does not. Well, in GDAU, an

5:33

underscore at the start of a function

5:34

name like in it or ready even usually

5:37

means it's a life cycle function, which

5:41

means GDAU calls it automatically for

5:43

you. You don't have to tell the droid to

5:45

in it. The engine's going to do it for

5:47

us the moment that this droid is born.

5:50

Functions without the underscore are

5:52

custom. Those are the ones we have to

5:54

trigger manually in our code. Now,

5:57

you've reached a checkpoint. I want you

5:59

to add a function called recharge. And

6:02

it should set the battery level back to

6:05

100 and then print a message saying the

6:07

Droid is fully charged. Maybe want to

6:10

try this without the hint. Go ahead and

6:12

pause now and give it a try.

6:18

Now, for those who might be a little

6:19

stuck, that's okay. Maybe a little bit

6:22

of a hint. What we need here is we're

6:24

going to create the recharge

6:27

function

6:29

and then we're going to set the battery

6:33

level to 100. And then we're going to

6:37

print a message saying the droid is

6:42

fully charged.

6:44

And that's it. If you want to take a

6:47

look at the perform task function here,

6:50

it can help you out quite a bit. Go and

6:52

pause now and give it a try.

6:58

All right, hopefully you gave that a

6:59

try. What we're going to do here is I'm

7:01

going to create the recharge function.

7:02

It's going to be function recharge.

7:07

That's going to return nothing. So, it's

7:09

going to be a void. It's not going to

7:11

take any parameters in. So, we're good

7:13

there. Now, we want to set the battery

7:15

level to 100. So, we're going to take

7:17

the battery level and we're going to

7:19

equal that to 100. And then we want to

7:22

have a print statement saying, "Hey,

7:24

we're fully charged." So, we're going to

7:26

take our serial number of the droid that

7:28

we're saying anything about, comma,

7:31

separate

7:33

quotation, colon, and then recharged to

7:37

full power.

7:39

Right? That's it. Then save the script.

7:42

Now the key takeaway here is classes

7:45

hold both data variables and actions

7:48

functions. They are self-contained

7:51

packages. Now we need a security droid.

7:54

We could copy the code from droid.gd

7:58

but that's messy. Instead we're going to

8:00

use inheritance. I'm going to make this

8:02

smaller. Then in my scripts folder we're

8:05

going to rightclick and then create new

8:07

script. We're going to call this script

8:10

security

8:12

droid.

8:13

There we go. Create. Now, in our

8:17

security droid here, get rid of this

8:19

boilerplate code here. And then, instead

8:21

of it extending, instead of extending

8:24

node, we're going to extend droid. And

8:28

because we write extends Droid, this new

8:30

script automatically has the serial

8:33

number and the battery level and all the

8:36

functions in Droid itself without having

8:39

to write them in the Droid script

8:41

itself. Right now, above this extend

8:44

droid, we're actually going to make this

8:46

a class

8:48

name as well. This is going to be our

8:51

security dur.

8:54

Great. Then below extends, I'm going to

8:56

actually add some laser power

8:59

in case our

9:01

security droid needs to secure things.

9:04

Type in make it 50. Now we're going to

9:07

do something called overwriting

9:09

functions. I'm enter a couple times. I'm

9:11

going write the function perform task.

9:14

And if you see it actually will

9:16

autocomplete because we have this in our

9:17

Droid function. We're going to write

9:19

this function as well. And in this

9:22

function, we're actually going to use a

9:24

keyword called super,

9:27

which basically means do the things in

9:30

the Droid class that the perform task

9:34

already does. So back to Droid, it's

9:36

going to do all this stuff

9:39

before it does anything else. So we do

9:42

super.perform

9:44

task. So I'm just calling that function

9:45

basically.

9:47

Droid call this function. do this stuff

9:51

and then what I'm going to do after that

9:54

is I'm going to do anything else which

9:57

for this guy I'm going to say the serial

9:59

number which I have access to because I

10:01

extended droid

10:03

I'm going to say scanning for intruders

10:09

intruders. Yeah, I spelled that right.

10:11

If I find them pew pew. There we go. So

10:16

this once again the super.perform

10:18

perform task is just calling that

10:19

function to do the basics. So we're

10:22

going to do do the default droid stuff

10:28

which is drain battery

10:33

because once again go back to droid this

10:35

perform test does not have an

10:36

underscore. So in order for this to run

10:39

we have to call it which we're doing

10:41

here. So once we drain the battery we

10:43

drain the battery because we're scanning

10:45

for intruders.

10:47

So now we know the super actually calls

10:49

our parent version of the function. So

10:51

we still drain the battery and then we

10:54

can actually add in some logic to blast

10:56

the lasers. For now we're just going to

10:58

do the print statement. In the future

11:00

you can actually use this laser power

11:02

for something else. Now a common

11:04

question is I want to attach this script

11:06

to a character body 2D so it can move.

11:09

Can I extend that as well? Well the

11:12

answer is single inheritance. You can

11:14

only pick one parent. You cannot say

11:17

extends droid and character body 2D. But

11:21

we can use something called a chain. Now

11:23

if we go back to droid.gd

11:25

and change the first line to extends

11:28

character body 2D. So back in our droid

11:31

script and under class name we say

11:34

extends

11:36

character body 2D.

11:40

Then save that. So now because security

11:43

droid extends droid, it inherits

11:47

everything droid has which now includes

11:49

all the physics and movement from its

11:51

parent which is the class stuff in droid

11:54

and character body 2D. It's a package

11:56

deal. So the droid gets a serial number

11:59

from droid and the move and slide

12:00

functions from character body 2D. For

12:03

example, if I go back to security droid

12:06

and under here just for testing, we're

12:08

going to delete this, but just to look

12:09

at it function, the move and slide is in

12:12

the physics process. If I enter there,

12:14

type in move and slide. You see it

12:17

autocompleted and I can save that and I

12:18

have that in my security droid now. But

12:22

if I go back to Droid and then I get rid

12:25

of this character body TD and then I

12:28

save it. Notice then we'll get an error

12:32

saying move and slide not found in base

12:35

self because this does not have access

12:37

to character body 2D anymore. If for

12:41

example you cannot do this

12:44

that's not a thing. So you have to only

12:47

extend one thing. If you want to chain

12:49

things has to come from above to the

12:52

parent. I'm gonna delete this.

12:56

Save the script. Now there's an

12:58

alternative method. It's a little more

13:01

intermediate. It's called the brain

13:03

method. Now if you don't want every

13:05

droid to be a physics object, maybe some

13:07

are just UI data, you would keep the

13:10

droid as a data class and just use

13:12

something called composition.

13:15

So what is composition? Well, script A

13:17

would be droid. which has the data, the

13:19

health, and the name. And script B, your

13:22

security droid. When we change that,

13:26

I'll comment this out here real quick.

13:28

And then we extends

13:30

character body 2D in here. And then we

13:34

can enter down. And how do we get this

13:37

perform task back? Well, what we have to

13:39

do is do something called a link, which

13:42

is creating a variable base droid stats.

13:49

Stats

13:51

is going to be of type droid, it's going

13:53

to equal droid new.

13:57

And you'll notice we need to actually

13:59

put in an argument. If we go in our

14:01

droid, what the initialize is looking

14:03

for is a string. So, what's the droid's

14:06

name? So initializing we just put an

14:08

empty string. So just quotation marks

14:11

that solves that. And then we would have

14:13

to copy this base droid stats and put it

14:16

instead of super

14:20

base droid stats perform task instead of

14:22

serial number base droid task or stats

14:26

dot serial number. And that's how we

14:28

access that.

14:30

We'll go and keep it the way we had it.

14:34

More cleaner I think. and actually

14:38

is more readable in the end. And if we

14:42

do it that way, we'll have to change how

14:44

we're giving it in our next part. So,

14:46

we'll do it just this way in the end. It

14:49

just shows there's multiple ways to do

14:51

things. I'm going to save that how we

14:53

had it. Our class name droid, a class

14:57

name security droid, and we're going to

14:58

extend droid and use the super keyword

15:01

and then use it just like that. But that

15:04

is composition.

15:06

Now we have the blueprints. Now let's

15:08

build the factory and actually spawn

15:10

them. All right. Now we're just going to

15:12

create a standard 2D scene. We're going

15:14

to rename the node 2D. We're going to

15:16

create a factory.

15:19

We're attach a script to this factory.

15:21

And we're going to put it in a scripts

15:23

folder. Not the root folder. Double

15:25

click the scripts. Open. Then create.

15:30

I'm going to get rid of the process

15:32

function. We don't need that. And then

15:34

in the ready function, we'll use that.

15:36

We're going to do first is create a

15:39

basic droid.

15:42

How do we do that? We're going to put in

15:44

a variable worker type droid. It's going

15:47

to equal droid new. Just like we kind of

15:51

saw earlier, we're going to name this

15:53

droid. We'll name it W1.

15:56

Perfect. Now, we're going to create a

15:59

security droid.

16:03

They have two different kinds of droids.

16:06

And then it's going to be the guard,

16:08

but it's still going to be of type droid

16:12

because says security droid extends

16:14

droid, it is still a normal droid. And

16:18

that'll be important in just a second.

16:20

So equals security droid. And we're

16:24

going to make a new one. We're going to

16:25

name this security droid 900.

16:29

There we go. So, we have our welcome and

16:30

our security droid. So, now what we're

16:33

going to do is put these droids in an

16:35

array and put them in an array.

16:40

We're going to use factory units. These

16:44

are our factory units in the factory.

16:46

So, all of our droids and be of type

16:48

array. And in this array is going to be

16:51

droid.

16:54

And the droids we're going to put in the

16:56

array are well the ones we just made.

16:58

the worker and the guard.

17:03

Since our security droid extends droid,

17:06

this array only has to be of type droid.

17:09

Doesn't care if it's a security droid as

17:11

long as it's a droid. Now we have our

17:14

array. Well, let's run them all so we

17:17

can see them in our output. And how do

17:20

we do that? Well, we use a for loop for

17:22

and all the unit in factory units has to

17:26

go through the array. And when it does,

17:29

well, we're just going to perform the

17:31

task. Unit perform task. So that's our

17:37

custom function. So our regular droid is

17:40

going to do perform task here in the

17:43

base class. And in our security droid,

17:46

it's going to perform task here, which

17:48

does the basic one, but also the extra

17:51

stuff we put in there. Great. So, in our

17:53

factory, going to save that. We're going

17:56

to save this factory scene. Right click,

17:58

new folder, scenes folder. So, it's good

18:01

to stay organized. And then we're going

18:04

to call it factory.

18:07

Save.

18:09

Right. Now, press F6 or run the current

18:12

scene here. and start. And now you see

18:16

here the Droid 101 has been assembled.

18:19

Droid S900 has been assembled. 101 is

18:23

idling. Battery is at 90%.

18:26

Idling battery at 90%. They both

18:29

performed a task. And this one actually

18:31

the security bot scanned for intruders,

18:34

found one. Keep it. Notice the magic

18:37

there. The array that's typed array

18:39

droid, but we put a security droid

18:42

inside it. Well, that's called

18:43

polymorphism.

18:45

The factory doesn't care what kind of

18:47

droid it is as long as it is a droid.

18:49

Then it can call perform task. So to

18:52

recap, we created a class name to define

18:55

a global type. We used extends to

18:58

inherit all that functionality into a

19:00

specialized version. And we used super

19:02

to keep the original logic while adding

19:04

new flavor. Now to take this further, we

19:08

could take these scripton classes and

19:10

turn them into resources. So we can edit

19:11

their stats in the inspector without

19:13

writing code. We can make them visual in

19:16

a 2D or 3D atmosphere. And you let me

19:18

know in the comments if that's something

19:20

you'd like to see in a future video or

19:22

do it yourself and I would love to see

19:23

your results. Now, if you found this

19:25

helpful at all or fun, leave a comment

19:27

on what your GDAU gamedev goals are. And

19:30

please like, subscribe, and hit that

19:32

notification bell. It really helps out

19:34

the channel. And thank you to all our

19:36

current and past Patreon and coffee

19:38

members. Your generous support keeps the

19:40

channel moving. Now, if you want early

19:42

access to tutorials, source code, or

19:44

suggesting future tutorials, please

19:46

consider becoming a member yourself. The

19:48

links are in the description. I

19:51

Spaghetti Syntax, and remember, always

19:53

stay curious, and I'll see you at the

19:56

next checkpoint.

Interactive Summary

The video demonstrates how to efficiently create various game entities using GDScript classes, avoiding repetitive code. It begins by explaining classes as blueprints, then walks through creating a base `Droid` class with properties like serial number and battery level, and functions for initialization and task performance. The tutorial introduces inheritance by showing how a `SecurityDroid` class can extend the `Droid` class, inheriting its base functionality and adding specialized behavior using the `super` keyword to augment parent functions. It also briefly discusses single inheritance versus composition. Finally, the video showcases polymorphism through a "Droid Factory" that spawns both basic and security droids into a single array, demonstrating how they can be treated uniformly despite their specialized functions.

Suggested questions

7 ready-made prompts