Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
0
1
00:00:00,030 --> 00:00:01,800
Welcome to the communicator system.
1
2
00:00:01,890 --> 00:00:06,570
This system is responsible for propagating knowledge from one AI agent to another.
2
3
00:00:06,600 --> 00:00:12,390
In this particular case, if one tank acquires the target, it will then try to inform others about
3
4
00:00:12,390 --> 00:00:12,540
it.
4
5
00:00:12,570 --> 00:00:14,730
Let's find out how this all works.
5
6
00:00:14,760 --> 00:00:17,070
The communicator is made out of two parts.
6
7
00:00:17,100 --> 00:00:21,930
One of them is the main system that is attached to all AI agents.
7
8
00:00:21,960 --> 00:00:28,350
You can find this system on every AI instance, child to the main kinematic body because it uses the collision.
8
9
00:00:28,410 --> 00:00:35,160
The other is the signal, which is similar to a projectile, but it travels directly to another instance
9
10
00:00:35,160 --> 00:00:40,650
and when it arrives, it's meant to inform that AI instance that it has a new target.
10
11
00:00:40,800 --> 00:00:43,470
Let's start with the main communicator component.
11
12
00:00:43,590 --> 00:00:45,520
Here we can find the following parts.
12
13
00:00:45,540 --> 00:00:50,940
First, you have the area collision, which will keep track of all other AI agents that are in the vicinity
13
14
00:00:50,940 --> 00:00:51,580
of this one.
14
15
00:00:51,610 --> 00:00:54,140
To not be able to communicate faraway distances.
15
16
00:00:54,150 --> 00:00:58,850
Of course you can change this by changing the collision sphere shape to different sizes.
16
17
00:00:58,860 --> 00:01:03,930
So this particular instance would communicate farther away or on shorter ranges.
17
18
00:01:03,960 --> 00:01:09,390
The other two parts are two timers: the ClearSignalListTimer and the CommunicateTimer.
18
19
00:01:09,420 --> 00:01:14,760
The communicate timer is actually triggered so that the communication doesn't happen all the time,
19
20
00:01:14,760 --> 00:01:17,540
but with 2 seconds delay in between them.
20
21
00:01:17,550 --> 00:01:21,550
And of course we don't want to send to the same tank the signal twice.
21
22
00:01:21,600 --> 00:01:27,870
So we keep track of the signal list and at some point we clear it up because the tank that received a signal
22
23
00:01:27,870 --> 00:01:33,120
from us might have lost the target and is good to be able to communicate with it again, but at some
23
24
00:01:33,120 --> 00:01:34,440
point later in time.
24
25
00:01:34,470 --> 00:01:38,100
Now let's look at the communicator script and see how this works.
25
26
00:01:38,130 --> 00:01:41,010
First, I want to highlight the following variables.
26
27
00:01:41,130 --> 00:01:48,390
The signal prefab, which is actually you can see here, it's the signal that we use as the projectile.
27
28
00:01:48,420 --> 00:01:53,010
This will get instantiated when we need to communicate between different AI instances.
28
29
00:01:53,040 --> 00:01:55,350
We also have the maximum communication number.
29
30
00:01:55,500 --> 00:02:01,830
Basically, once we send the signal out to three different other AI instances, we stop this communicator
30
31
00:02:01,830 --> 00:02:02,430
from working.
31
32
00:02:02,460 --> 00:02:06,450
This is do not overpower the system and let the whole map come after us.
32
33
00:02:06,510 --> 00:02:12,010
Next, we have the nearby list, which will be updated by the area collision on_body_entered and
33
34
00:02:12,020 --> 00:02:13,150
on_body_left.
34
35
00:02:13,160 --> 00:02:18,150
This will get updated with more or less AIs that are in our nearby field.
35
36
00:02:18,180 --> 00:02:23,330
The signaled_list is a list of tanks that already have received communication from this one.
36
37
00:02:23,340 --> 00:02:25,340
We do not want to send the same thing twice.
37
38
00:02:25,350 --> 00:02:31,200
The current_communication is actually a counter that keeps track of how many AI agents have we signaled to,
38
39
00:02:31,230 --> 00:02:36,740
and this will be used to compare to the maximum communication to stop once we reach the limit.
39
40
00:02:36,750 --> 00:02:41,730
And of course you can change this to communicate to more or less AIs depending of your balancing
40
41
00:02:41,730 --> 00:02:42,270
of the game.
41
42
00:02:42,360 --> 00:02:47,640
In the initialize function we get the tank object that is the parent of this and we also will need the
42
43
00:02:47,640 --> 00:02:49,560
target handler. In the restart,
43
44
00:02:49,570 --> 00:02:55,290
we reset basically the communication so that we can communicate to three AIs in this case. And also
44
45
00:02:55,290 --> 00:03:00,030
we clear the signaled_list so that we can communicate with the same three AIs that we want.
45
46
00:03:00,090 --> 00:03:02,970
The main functionality is the throw_signal, but before
46
47
00:03:02,970 --> 00:03:04,060
we go into this
47
48
00:03:04,080 --> 00:03:08,280
I want to quickly point out how the nearby list gets updated.
48
49
00:03:08,280 --> 00:03:13,530
We have the area collision and in the node here we have body_entered and body_exited.
49
50
00:03:13,770 --> 00:03:20,070
Here these two are actually signals that are hooked up with these two functions.
50
51
00:03:20,070 --> 00:03:26,520
And here we get the type of the body that has entered or left and if it's enemy and it's not in the
51
52
00:03:26,520 --> 00:03:29,850
nearby list already, and of course it's not the same one.
52
53
00:03:29,850 --> 00:03:35,990
We want to prevent collision to itself because we don't want this tank to issue communications to itself.
53
54
00:03:36,030 --> 00:03:38,250
Then we append it to the nearby list.
54
55
00:03:38,280 --> 00:03:42,870
Alternatively, if this tank exited, then we actually remove it from the nearby list.
55
56
00:03:42,930 --> 00:03:45,300
Basically, this is how we get a nearby list
56
57
00:03:45,450 --> 00:03:53,040
working every frame. throw_signal() is not actually called by any other script, but by using this timer,
57
58
00:03:53,040 --> 00:03:56,140
which as I mentioned, is in the on_communicate_timer.
58
59
00:03:56,160 --> 00:04:00,030
This is also a signal that's hooked up through the Godot system.
59
60
00:04:00,120 --> 00:04:06,600
Once this reaches zero, first we need to make sure that we still have a valid target for this particular
60
61
00:04:06,600 --> 00:04:06,990
tank.
61
62
00:04:07,050 --> 00:04:12,720
So in this case, if the target exists and is the instance valid, and then if we have reached the maximum
62
63
00:04:12,720 --> 00:04:19,200
communication number, we need to stop the communicate timer and of course return and otherwise we haven't
63
64
00:04:19,200 --> 00:04:22,980
reached it yet and we can actually throw a new signal.
64
65
00:04:23,010 --> 00:04:28,500
Now let's look at the throw_signal functionality. And here we need to do the following:
65
66
00:04:28,500 --> 00:04:32,640
First, we need to check if the nearby list has some tanks around.
66
67
00:04:32,640 --> 00:04:36,900
If we don't have anyone around, then we cannot communicate with someone.
67
68
00:04:36,900 --> 00:04:37,890
We return.
68
69
00:04:37,890 --> 00:04:40,970
Basically, this just stops the execution of this function here.
69
70
00:04:40,980 --> 00:04:47,640
Then we have the other enemy which we will get from the nearby list, and this is actually generated through
70
71
00:04:47,640 --> 00:04:48,390
a random number.
71
72
00:04:48,390 --> 00:04:50,130
So we get the random index number.
72
73
00:04:50,190 --> 00:04:55,500
We also need to check if the other enemy still exists and the instance is still valid, and then if
73
74
00:04:55,500 --> 00:04:58,020
the other enemy doesn't have already the same target.
74
75
00:04:58,020 --> 00:04:59,670
Because if it does have the target.
75
76
00:04:59,840 --> 00:05:02,230
Then sending a signal to it would be useless.
76
77
00:05:02,260 --> 00:05:08,100
We don't want to have the same enemy signaled twice, so we check it in the signaled_list.
77
78
00:05:08,110 --> 00:05:14,150
But if the selected enemy passes all of these checks, then this means we can properly issue a new signal.
78
79
00:05:14,170 --> 00:05:16,710
We increase the current communication number.
79
80
00:05:16,720 --> 00:05:19,430
We append this other enemy to the signaled_list.
80
81
00:05:19,450 --> 00:05:24,820
Lastly, we create a new signal, and the first two steps are, of course, instantiate the signal and
81
82
00:05:24,820 --> 00:05:30,640
add it to the root scene node and then set up the position as well as the rotation of the signal.
82
83
00:05:30,640 --> 00:05:36,370
And lastly, trigger the start functionality which will receive the other enemy and what target the
83
84
00:05:36,370 --> 00:05:37,630
other enemy should receive.
84
85
00:05:37,630 --> 00:05:41,740
The last callback that we need to mention here is on_clear_signal_timeout
85
86
00:05:41,740 --> 00:05:42,940
.
86
87
00:05:43,000 --> 00:05:49,180
This just clears the signaled_list to be able to inform the enemies that already have been informed by
87
88
00:05:49,180 --> 00:05:50,140
this particular one.
88
89
00:05:50,170 --> 00:05:55,540
The other part of the communicator is the actual signal and we can check its code right now.
89
90
00:05:55,540 --> 00:05:58,890
And basically here it looks very, very similar to a projectile.
90
91
00:05:59,170 --> 00:06:04,660
Besides the start which actually receives the other enemy and the target we actually wait for is
91
92
00:06:04,660 --> 00:06:09,460
enabled because we don't want to start moving this while it's not at the correct position.
92
93
00:06:09,460 --> 00:06:16,540
We create the direction vector and then we normalize it and we move this particular object towards the
93
94
00:06:16,540 --> 00:06:18,910
position using the speed and delta.
94
95
00:06:18,940 --> 00:06:24,640
The other part of this is actually calculating the distance between this current signal and the enemy.
95
96
00:06:24,640 --> 00:06:29,440
And if it's below one, it means that it has reached the intended target, and if it has the function
96
97
00:06:29,440 --> 00:06:31,210
on signal hit, then it will call it.
97
98
00:06:31,270 --> 00:06:34,810
If it's not, then might be a mistake or might have hit something else.
98
99
00:06:34,810 --> 00:06:36,130
But this should not be the case.
99
100
00:06:36,130 --> 00:06:38,390
And then the signal will actually be removed.
100
101
00:06:38,410 --> 00:06:39,890
This happens with this function.
101
102
00:06:40,030 --> 00:06:43,300
There is also one particular case that the signal might handle.
102
103
00:06:43,390 --> 00:06:50,380
So if we send the signal to a particular enemy and that enemy gets destroyed before the signal reaches
103
104
00:06:50,380 --> 00:06:50,570
it.
104
105
00:06:50,620 --> 00:06:52,570
In this case, this won't work anymore.
105
106
00:06:52,570 --> 00:06:59,200
So we need to have also a lifespan that actually is 5 seconds and it will automatically start.
106
107
00:06:59,200 --> 00:07:04,990
So if the signal either reaches the enemy or has elapsed 5 seconds after each instantiation, then it
107
108
00:07:04,990 --> 00:07:08,330
will get destroyed. And for the signal hit on the enemy.
108
109
00:07:08,350 --> 00:07:12,520
If we go back to the enemy script, then this is the function we are looking at.
109
110
00:07:12,550 --> 00:07:17,070
This was also discussed in the main enemy video, but quickly, just a refresh.
110
111
00:07:17,080 --> 00:07:22,390
It gets to the target and if the target is still valid, then it will set the target externally to the
111
112
00:07:22,390 --> 00:07:23,170
target handler.
112
113
00:07:23,170 --> 00:07:27,580
So this new enemy will get informed about this target via the signal.
113
114
00:07:27,640 --> 00:07:29,070
This is it for the communicator.
114
115
00:07:29,080 --> 00:07:30,220
I hope you liked it.
115
116
00:07:30,220 --> 00:07:32,080
And leave a comment here and tell me.
116
117
00:07:32,320 --> 00:07:33,430
See you in the next one.
12730
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.