Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
0
1
00:00:00,060 --> 00:00:06,780
Now that we have covered the basics of the finite state machine, let's look how one can be implemented
1
2
00:00:06,780 --> 00:00:07,960
using GDScript.
2
3
00:00:08,010 --> 00:00:11,370
There are many ways to implement the finite state machine.
3
4
00:00:11,370 --> 00:00:13,260
This is but only one of them.
4
5
00:00:13,290 --> 00:00:20,340
We will use two type of scripts the main finite state machine, which is responsible for changing states
5
6
00:00:20,340 --> 00:00:26,510
and running them, but also keeping track of the values in a small database and the others, which are
6
7
00:00:26,520 --> 00:00:28,440
the actual state implementations.
7
8
00:00:28,470 --> 00:00:34,440
Let's look first at the finite state machine. And I've already created this structure, so we will go
8
9
00:00:34,440 --> 00:00:39,050
inside the custom finite state machine and start working with it.
9
10
00:00:39,060 --> 00:00:39,870
And of course.
10
11
00:00:42,620 --> 00:00:48,530
The first thing that we need to do is create the basic structure.
11
12
00:01:00,600 --> 00:01:08,540
We will use the entry_state that can be configured in the inspector of this state machine to know exactly
12
13
00:01:08,750 --> 00:01:11,060
which state should be run first.
13
14
00:01:14,650 --> 00:01:20,500
The current_state is the variable which holds the current state that is actually running.
14
15
00:01:22,660 --> 00:01:30,760
The database keeps our values when we need to access particular information about this state machine.
15
16
00:01:31,150 --> 00:01:37,210
And we also need the state list, which is also a dictionary. In the _ready function
16
17
00:01:37,600 --> 00:01:39,980
we will need to do a couple of different things.
17
18
00:01:40,180 --> 00:01:43,510
The first: we will parse all the children.
18
19
00:01:43,510 --> 00:01:48,030
So as you can see here, we have three states and we need to get all of them.
19
20
00:01:48,040 --> 00:01:51,490
And for this we can parse all the children.
20
21
00:01:54,150 --> 00:01:54,720
And...
21
22
00:01:57,310 --> 00:02:03,400
First we will initialize the children's finite state machine with this one.
22
23
00:02:04,360 --> 00:02:10,240
And of course, we need to add the state list of the state name and the state.
23
24
00:02:10,570 --> 00:02:17,740
This will basically create the key-pair value of the state name and the state in this finite state machine.
24
25
00:02:18,190 --> 00:02:23,050
This will be useful, for example, when we are going to change state
25
26
00:02:25,550 --> 00:02:29,510
from the entry_state. Because the entry_state is a string.
26
27
00:02:30,050 --> 00:02:35,380
So it's not an actual state object, but this one is a state object.
27
28
00:02:35,390 --> 00:02:43,910
And by having this dictionary, we can actually convert string names to actual state objects.
28
29
00:02:44,390 --> 00:02:49,850
Now let's proceed and implement the changed state function because we currently don't have it.
29
30
00:02:55,270 --> 00:03:00,760
And here we need the new state, which would be the new state where we will head into.
30
31
00:03:01,780 --> 00:03:10,060
And if the current_state is not null, then that means that the current_state currently has something
31
32
00:03:10,060 --> 00:03:10,540
in there.
32
33
00:03:14,460 --> 00:03:21,590
Of course, we always need to check to see if the current state is a legit state.
33
34
00:03:21,600 --> 00:03:31,200
And for this we will use the exit_state() because we will call for every single state the enter_state(), exit_state()
34
35
00:03:31,200 --> 00:03:32,820
and update_state().
35
36
00:03:33,120 --> 00:03:38,640
So in this case, if the current state has an exit_state() (function), then of course we will need to call this
36
37
00:03:40,150 --> 00:03:49,420
function. And be mindful that if the current state did not have this exit_state() method, then this will give
37
38
00:03:49,420 --> 00:03:50,260
an error without
38
39
00:03:50,290 --> 00:03:54,430
this if. So, it's important to put this check before. Next,
39
40
00:03:54,430 --> 00:04:02,170
we need to check if the state list actually registered a state with the name that we want to change
40
41
00:04:02,170 --> 00:04:02,470
with.
41
42
00:04:03,130 --> 00:04:05,590
So if the state list does not have.
42
43
00:04:09,900 --> 00:04:14,490
So to say, does not have, we can just negate the has().
43
44
00:04:14,880 --> 00:04:19,470
So instead of this which will return true, if it does have the state, then it will it will make
44
45
00:04:19,470 --> 00:04:22,320
it false if it does have the state => return.
45
46
00:04:22,620 --> 00:04:29,590
This is really important because we cannot change to a state that is invalid because it doesn't exist.
46
47
00:04:29,610 --> 00:04:32,040
Now that we know for sure that the state exists.
47
48
00:04:32,250 --> 00:04:37,080
We can say current state equals state list new state.
48
49
00:04:37,710 --> 00:04:45,300
And since this is a string, it is important to make sure this check happens because otherwise this
49
50
00:04:45,300 --> 00:04:46,740
query will give an error.
50
51
00:04:47,040 --> 00:04:48,180
This is also for check.
51
52
00:04:48,180 --> 00:04:51,330
But if the current state has method.
52
53
00:04:52,830 --> 00:04:54,120
enter_state()
53
54
00:04:54,510 --> 00:04:56,490
Then, of course, we need to call it.
54
55
00:04:59,760 --> 00:05:05,190
The enter_state() and exit_state() are always called when a state gets changed.
55
56
00:05:05,220 --> 00:05:09,720
This is important for one-time functions that need to run in that particular state.
56
57
00:05:09,780 --> 00:05:12,120
Now let's move on with the process.
57
58
00:05:12,900 --> 00:05:18,450
So in the _process() part, what we need to do is we need to check if there is a current state.
58
59
00:05:19,020 --> 00:05:20,070
And if it's not.
59
60
00:05:21,240 --> 00:05:25,290
We will call return because we don't want to process this any longer.
60
61
00:05:25,590 --> 00:05:31,920
Of course, what we could have done instead would have been if the current state is not null and then
61
62
00:05:31,920 --> 00:05:33,090
write our code here.
62
63
00:05:33,120 --> 00:05:40,590
But the problem by doing this is that we will have more indentation as we go with this kind of structure.
63
64
00:05:40,620 --> 00:05:47,160
So instead what we do is just check if it's null and then return to keep the indentation level.
64
65
00:05:47,400 --> 00:05:54,120
So to keep this indentation as close to the left as possible. This will create a nice code structure
65
66
00:05:54,210 --> 00:05:54,990
in the long run.
66
67
00:05:55,080 --> 00:06:00,900
And here, of course, we will call current_state because we know it exists and if it has the method.
67
68
00:06:04,200 --> 00:06:04,650
process()
68
69
00:06:04,890 --> 00:06:06,660
And be mindful here
69
70
00:06:06,870 --> 00:06:11,850
this process is a little different from this one because this gets automatically called by Godot,
70
71
00:06:11,850 --> 00:06:18,540
and we need a custom one because we would need to call it here and we need to make sure that it only
71
72
00:06:18,540 --> 00:06:19,370
gets called here.
72
73
00:06:19,380 --> 00:06:24,270
So I'm just copy-pasting this because it's much easier. And I'm going to put in the delta.
73
74
00:06:24,360 --> 00:06:28,380
Of course, I'll do exactly the same for the _physics_process().
74
75
00:06:49,690 --> 00:06:53,020
It's important to copy paste this to make sure that there's no error.
75
76
00:06:54,700 --> 00:06:56,860
Why is it important to have _process() and _physics_process()
76
77
00:06:56,860 --> 00:07:00,150
because some functions only work in _physics_process().
77
78
00:07:00,160 --> 00:07:04,270
So it's important to have both of these supported in our state machine.
78
79
00:07:04,330 --> 00:07:06,500
Of course, we already have the change_state().
79
80
00:07:06,520 --> 00:07:16,270
What we need to do here is create two more options, and that is set_value(), which is a setter for
80
81
00:07:16,270 --> 00:07:18,190
the key-pair database we have.
81
82
00:07:18,190 --> 00:07:23,380
So value name and value. And "db"
82
83
00:07:23,380 --> 00:07:31,300
the database dictionary that we created, the value name will be equal value and next one will have
83
84
00:07:32,680 --> 00:07:38,500
get_value() which can just get the value name.
84
85
00:07:39,160 --> 00:07:46,780
And here we can say if the database has(value_name) first because we cannot query something that doesn't
85
86
00:07:46,780 --> 00:07:50,830
exist, then it will return to the database value name.
86
87
00:07:52,190 --> 00:08:00,290
This is important because our state machine will need to communicate with different states to know what
87
88
00:08:00,290 --> 00:08:02,180
is the current state of the whole system.
88
89
00:08:02,420 --> 00:08:04,280
For example, is the player retreating?
89
90
00:08:04,280 --> 00:08:07,180
Is the player attacking so and so forth.
90
91
00:08:07,190 --> 00:08:11,540
So we need to have a synchronized database for all of these states.
91
92
00:08:11,720 --> 00:08:14,960
Now let's move to a particular node implementation.
92
93
00:08:14,960 --> 00:08:18,260
And for this I will target the idle state.
93
94
00:08:26,780 --> 00:08:32,300
So first we would need to have a reference to the custom state machine that we just implemented.
94
95
00:08:32,810 --> 00:08:34,790
And now we need to make sure we have:
95
96
00:08:36,420 --> 00:08:37,170
enter_state()
96
97
00:08:43,810 --> 00:08:50,150
And as you remember, the enter_state() is called when a state gets changed.
97
98
00:08:50,170 --> 00:08:55,150
So this will be called when the idle state is changed.
98
99
00:08:55,780 --> 00:08:58,840
Now, we also need the exit_state().
99
100
00:09:00,210 --> 00:09:06,150
Make sure that the names are exactly the ones used in the custom finite state machine.
100
101
00:09:06,150 --> 00:09:07,290
Otherwise it won't work.
101
102
00:09:12,420 --> 00:09:18,900
And here the process() is not with underscore, because this will be automatically called every single frame
102
103
00:09:19,140 --> 00:09:19,830
from Godot.
103
104
00:09:19,860 --> 00:09:25,680
And it's important because you have if you have multiple states, we don't want them to run without
104
105
00:09:25,680 --> 00:09:32,260
any control, but instead being able to control them through this process.
105
106
00:09:32,280 --> 00:09:36,690
So in order to make this happen, we need to make sure that this not with underscore. This is basically
106
107
00:09:36,690 --> 00:09:38,130
you can call it whatever you like.
107
108
00:09:38,130 --> 00:09:40,950
But I just called the process. Delta.
108
109
00:09:45,700 --> 00:09:46,480
And here.
109
110
00:09:47,780 --> 00:09:54,170
Before we actually do any process from the state, we need to check the conditions.
110
111
00:09:54,710 --> 00:10:03,890
And the conditions are really important because they will tell us if we need to go from this state to
111
112
00:10:04,220 --> 00:10:08,570
another one based on some values that are stored in the database.
112
113
00:10:09,320 --> 00:10:14,900
We will create these and the other states in the mini example for the finite state machine.
113
114
00:10:15,020 --> 00:10:16,610
Let's find out how to make them.
12043
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.