Transcripts
1. Introduction: Welcome to the
Complete Point and click Adventure Game
Development course, No Code with Unity
and playmaker. I'm Rome Fozi, a
game developer and a Tre D artist with over
ten years of experience. I have self published
a Google Play game and worked on various client
projects using Unity. In this course, you
will learn how to master game development
using playmaker, a powerful unity add on that eliminates the
need for coding. Topics covered include
using FSM templates as custom actions or reusable FSMs with input and output values, creating an inventory system, using scriptable objects
for custom data types, building a complex
safe system to save inventory PC state
scene states and more, implementing animations and
setting up simple audio, utilizing timelines to create cinematic experience
in your game. If you have any questions during the course,
feel free to ask. I'm quite active in
the QN A section and committed to
providing trough answers. Join us to level up
your playmaker skills and unlock new possibilities
in game development.
2. 01 Project Setup: Hey, in this video, we
are going to prepare the new project for
creating the Point and click game using playmaker. So now here, I have
this Unity Hub opened, and let's create a new project, and I'm going to pick
Unity 2021 0.1 0.7. You can use other version, and if you have the same unity version
installed, that will be best. And for now, let's just
use a three DD templates. And for the locations, I already prepared
a location here. And I'm going to call this
playmaker coin and click. Okay. So now we
have Unity opened. Let's prepare the project by importing a couple of assets. So first, I'm going
to reset the layouts, so it is easier. And then we need to import
a couple of assets. I already have the
assets imported, but I'm going to share the link, and I'm going to open
the package manager. Okay. The first thing that we need to import is playmaker. Of course, I'm going
to import playmaker. And let's just
import all of them. And here, under
the guide window, let's just press
Install playmaker and then install playmaker here. Okay. Now we are
done with playmaker, Let's download another assets, which is the character
asset that we are going to use in this project. It's called tiny
two knee db here. I think it's this one here. Yeah. And I'm going to share the link so you can also
add it to your assets. And I'm going to do here. And once it's
finished downloading, let's press the import button. Okay. So that one is done, and the other thing that we need to download is the
animation pack. So I'm going to download, I think it's called simple
animation peg or every day. Yeah. It's called everyday
motion pack free. And I will also share the
link to this asset page. Just press download here. And once it's finished, press the import button again. Okay. Now we are done with importing the assets
from Package Manager. Next, let's add a custom add on for playmaker
called ecosystem, and this will help us customs actions that are
not available by default on playmaker and created
by other peoples or third parties that are collect that together in
the ecosystem Github. So you can press this button to open
the page if you want, and go to the
ecosystem borrowser here and download the package. I've already downloaded that, so I'm going to
import it right away. And to import this,
I need to go to the assets menu under the import package,
pick custom package. And let's browse to the folder where you download the files. So it's going to
be here on my PC, and then press import. Okay. Now, ecosystem has been downloaded and
to access ecosystem, we can go to the play
Macer menu under add ons and then press this ecosystem and open
the ecosystem browser. And if you install
it the first time, we will have this window, but if you want to use it, just press use the
ecosystem button, and it will show this bar, and we can type anything. Okay. So now let's just
close this for now, and there are another two assets that
we need to download, and this is the asset
that I created myself, so I'm going to share the files in the resource
part of this course. The first one is an audio file, so I'm going to drag the audio files folder
and put it here. And once we import
this audio files, we will have a couple of audio that we can use in our game. And then I need to also
import a package that consists of treaty models
for the environment that we are going to
use in this project. So let's go to the asset
menu, press import package, custom package, and
I'm going to go to the folder where I saved
those package file here. And then import it. And here, it will be under
the point and click folder, and there will be a lot of FBX files and also
material and textures. So let's just press import. And now we are pretty much
done with the projects. I'm going to clean
up a bit here. For example, on
the project page, I'm going to change the view to a very small icon so we can see the name of the folder at its full length to make it
easier to know which folder, So, yeah, I think we are pretty
much done in this video. And the next video, we are going to start
working on our game.
3. 02 Pathfinding Setup: In this video, we are going
to continue our game project, and we have set up the projects
in the previous video. So now here on our sample scene, let's just create a couple
of objects that we can use to test our FSM. So I'm going to create
a two d object, and this is going
to be the ground. I'm going to reset
its transform, so it's at 000. And for the scale, I'm
going to make this slightly bigger like
20 units on the side. And I'm going to set its
height to a very low value, which is 0.1, and this will be the ground of our
test environment. And here, let's create a couple of materials
that we can use. So I'm going to go to the point and click folder materials, and let's create a new
subfolder inside of it, and this is going to be
the prototype materials. And here inside this folder. Let's create a new material, and let's just call
this ground proto. So we know this is for the
ground prototype object. And let's just track
this to the object here. Now it's assigned to the measure render of
this cube game object. We can change its color. Let's just change the color
to a slightly darker gray. So it's not as bright as before. And now the other thing
that we want to create is a capsule object. So let's go to the
three D game object and create capsule. And this is going to be the character that are
going to move around. I'm going to move the position
to one on the y axis. So it aligns with
our ground here. And I think we can
lift this now. And the next thing that we want to do is we need to create the naviigation mesh
so the character can move around the scene and
can avoid any obstacles that are already considered as obstacles in the
navigation mesh. So in order to do
that, this tests, let's create a couple of other game objects,
another cube, for example, and let's
put it somewhere here. And I'm going to scale this
on the z axis. So it's wider. And let's just duplicate this cube here by
pressing control D, and then we can move the
object to other position. So we have created some
sort of obstacles here. And let's create an
empty game object, and let's call this environment. And let's just reset
the transform. And now I'm going to put all of the environment game object, which is the ground,
the obstacles as a child of this
anti game object. Just to make the scene much cleaner and easier to
look at also to navigate. So let's just select all
of the cube game object and then drag this to the
environment game object. Now it's a child of
this game object, and we can easily hide it to isolate the
player, for example. Okay. So the next
thing that we want to do is we want to generate
the navigation mass. In order to do that, we
need to make sure that all of these game objects
is marked to static. And you can change the
static options here on the top right
of the inspector, where we have the name
of the game object. On the right side, it will shows this check mark for checking the object
as a static object. You can select all of
this game object and then do that to all of the
three game object, or we can select the
parent game object, and we mark the parent
game object as static, and Unity will as if
we want to change the children also to
a static game object. So I'm going to pick yes here. And now if we select
the child game object, you see all of them
are marked to static. So let's save our scene, and now in order to bake
the navigation mesh, let's go to the window
here and under the AI, let's open the
navigation window. And basically,
navigation mesh is a way to create a path finding for a
game object in unity. Usually, it's being used
for creating a movement for enemies that can move around like patrolling and
avoiding any obstacles. But in this case, we want to use this for our player movement because we want to
move the player whenever we click
to a certain area. So in order to create those
automatic path finding, we need to use the naviigation
system from unity. So now we have the
navigation window opened. Let's go to the baked tab
here and this press bake. And this will automatically
bake the scene. And now, as you can see here, we already have this blue mesh, and this is called
Navigation mesh. This is the area where our
player can move around. So if we click in
this area later, we can set the player to go to that destinations
and it will move to that point with a certain speed. And if we click to this area, for example, it will
move to this point here, and then it will try to
avoid the obstacles by calculating the shorter route to that point that we click. This is make a very good system for point and click movement. Okay, now we have set
up the navigation mesh. Let's pick our
capsule game object and go to the inspector here, change the name to player. So it's easier to see
on our scene here, on the hierarchy, we
will know right away, this is the player game object. And then we want to add a
NAF mesh agent component. And this will drive the
movement of the player. And here we have
options like speed, angular speed, and other
stuff like acceleration, stopping distance, and
obstacle avoidance. Now we have set up the scene. In the next video, we are
going to start creating the FSM for move
the player around.
4. 03 Click to Move Behaviour: In this video, we are going to continue our game development, and we are going to
implement the click to Move Mechanics
using playmaker. So first, in order to do that, let's open the
playmaker editor window under the playmaker menu here. Click the playmaker editor, and they should open
the playmaker editor. I'm going to close this. Welcome
to Play Maker Window and drag the playmaker editor window by its name here
by the tab name, and then drag this to be
on the side of Console. And make this bigger. And here we can start creating the behavior for
the click to move movement. I've already created
some sort of a notes as a guideline on how we want to do the click to move
mechanics here. So basically, we need to
click a couple of states, and the first one would
be the wait for click. So let's just select the player again here and then right
click and then add an FSM. This will create a new FSMs with one state as
the start state. On the site here, we can rename the FSM or we can rename
the FSM from this tab here. So let's just call
this click to move, and this should make
it easier later when we are debugging things or when we are organizing
things in our scene. The first state, let's just
call this wait for click. The state is basically going
to wait for a user click, and then it will act upon on it. The next state
that we need to do is the defined
destination state. Let's create another state, and let's call this
define destination. Basically, on the start state, we want to get mouse
button down state, and then we want to go to another state based
on those clicks. First, I'm going to create
a custom event that we can use to transition
between state. I'm going to call
this mouse down. And we can add that transition to the first state here to
the wait for click state, and we can drag this connection to the
defined destination. And here inside the
wait for click state, we want to use the GT
mouse button down action. And if the left
button is clicked, then we want to send
the mouse down event. And this will trigger the transition whenever
mouse is clicked. And here on the
define destination. We want to use the
mouse pick action. And mouse pick action
basically performs a mouse peck on the scene from the main camera and
store the result. And we can use a couple of other options with this action. Basically, it will
detect if a ray from our mouse click is hitting
something on the scene, then we can use
that information. Let's just add the
action to state here. And we want to store the value whenever this
mouse pick pick an object. And basically, store
this object is a bulion, so we can just create
a new variable, and let's just call
this valid click. Once we create
this new variable, you see that we have
this false value, and if we go to the variables, we know that it's a type of b. This can be true or false. And if the mouse
pick hits something, this value will be true, but if it doesn't hit anything,
then it will be false. For example, if we click
on an empty area here, then the valid click
value will be false. But if we click on
top of a object that has clyder on it,
then this will be true. And we want to set a layer mask. So I'm going to add
a layer mask here, and we can add a layer. But right now we don't
have that layer now. So in order to do that, we can open the environment here and select the first cube. And under the layer options, let's just click Add layer, and I'm going to use
the user layer six, and let's just call this ground. Go back to the first
cube object here, and we can change
its layer to ground. Now let's say the scene and go back to the
player game object. And let's set the layer mass
element zero to ground. This will filter out any clicks. So if we click on other objects
that is not the ground, then it won't be registered
as a valid click. And we need to also
start a point here. So point is basically
a vector tree value, so we can just create
a new variable, and let's just call this target position,
or target pause. And now we are done basically
with our mouse pick action. We need to check if the valid
click is true or false. So let's just use a bull test. Action, and as the name just send an event based on the value of a
Bulion variable. Let's just add this one here. And then we can use the
valid click Bulion, and if it's true, then we
want to set a destination. Here, we can see that if
the click is not valid, we want to go back
to wait for click, but if it's valid, then we want to go
to another new state called Set destination. And this will set the
navigation M destinations. So we need to create a
custom event for this. I'm going to call this go
to target position pus. And at the transition, go to target pus
and also finish. And finish is when the
valid click is false, then we want to go back
to the wait for click. So now if it's true, then we want to go to
the target position, and if it's false, we want to
pick the finish transition. Okay. So that's all with
the bull test here. And let's disconnect
the finish back to the wait for click state. And we can create a new state
by right clicking and open the context menu
and then add state here or to make things faster. I will let you know
for some tip here, if you hold control
on the keyboard and then drag the transition
from the target pose here. If you release this, it will automatically
create a new state. And for the state here, we can call this
set destination. So let's just type it. This new name here,
set destination. And now inside the
set destinations, we need to add the Nu
mesh agent action, but we don't have
this by default. So in order to download it, we can go to the playmaker
menu under the add ons, open the ecosystem browser, and then search with
keyword path finding. Just press the search button. Once it shows the result, we can press the get button, and this will
download the package. Now here, let's just
press the import button, and they should import custom
actions for path finding, and once it's
finished compiling, we can add that action. Let's close the
ecosystem browser. And now if we go to
the action browser, we can search for agent, and this shows a lot of NAM agents related
actions that we can use. And here, the action
that we want to use is the SAT
agent destination. Let's just use this here. And now we have the
target position variable. If the valid click is true, then this should
store some value. We can use that for
the destination. So here, right now, we are going to use the owner. And for the destinations, we can press this equal sign, and this should expose
the variable field, and we can use the
target position. And we don't need to do anything
on this done event here, the path pending De event, but I want to add a
next frame event. And this will delay
the transition, which is the finished transition that we are going to add now. And on the next
frame event here, we want to send
that finish event. So this will delay the finish transition by one frame after we are
setting the destinations. And this is need to be
done because basically, on the next date, we
are going to check if the agent has arrived or not. And if we've done it
on the same frame, there is a possibility
that the destination has not been triggered
yet on the next date, and it will trigger
arrive in the same frame. So it will cause
a bug or issues, and this is how we are
going to prevent it to make sure that the
destination has been set, and on the next state, it will wait until the agent
arrived to the destination. Okay. So now if we review
the mechanics here, we want to go to the wait to arrive after set destinations. And this is going to wait the player while it's
moving And later, we are going to add
another transition to set for two different
scenarios here. If we click again to
another destination, then we want to go back
to defined destinations. And if we arrive,
then we want to go back to the first state,
which is wait for clay. So now let's just create
this way to arrive state. So I'm going to hold
the control button and then direct the transition, and we can create the
state automatically. Let's just call
this way to arrive. Basically here on
the way to arrive, we want to add a transition, and the first one is the
mouse down transition, and the second one will be
the finished transition. Here, basically we need to
add two actions for now, and the first one will
be the mouse button down and send this event
to the mouse transition, so it will go back to the defined destinations and we can create those connections, and then we want to use the get agent
remaining distance action. And basically, we want to put this below the Get
mouse button down. And here, we don't
want to store results, but we want to trigger an event, and we can use the
finish transition and check the every
frame toggle here. So these actions will get
executed every frame. And then on finish, we want to create a new state by holding control and
drag the transition, and let's just
call this arrived. And let's add a finished
transition for now. And for now, this state
is going to be empty, but we are going to expand the functionality
in later videos. So now let's just connect the finish back to
wait for a click. Okay, Let's review the FSM. So we have this wait for click. It waits for the
left mouse button down and go to the
mouse down transition. And here we have the mouse pick, which is going to store
the valid click value as a bulion and a
target position. And we have the filter using the layer
mask and it sets to ground and make sure that we set the ground object
layer to also ground. I'm going to rename this
for clarity's sake. And then on here on the
devine destinations, we are testing the
valid click values. Then we are going
to target position. And here we are triggering
the set agent destination using the target
position variable that we've created from
the mouse peak here. And then we are waiting one frame and then
go to the next frame here. And basically, this way to arrive will stays
for a while until we either press the mouse left click or we arrive
on the destination. So let's just save
the scene here, and now let's give it a try. Okay. I think I'm going to stop this and
I'm going to make the same angle for our camera
to our scene view here. And the easy way to do it is by selecting the
main camera and then hold control SF and F
key on the keyboard. And this will snap the camera to the scene view
position automatically. If we go to the game view now, we should have the same
view as our scene view. And now we can save
the scene again, and now let's test this. Now it's running and let's select the player so
we can see the FSM. Right now, we are on the start state, which
is the wait for click. If I press click, it will
move to that position. Here, as you can see,
it waits to arrive and then it go to arrive and then go back to the
wait for click. But if we are moving and then
we click somewhere else, it will deviate to that position because
we have this mouse down event on our way to arrive and it will go back
to the defined destination. And let's just give it a try. Let's click to this position. It moves to that obstacles, and it will go around it. So it can avoid any obstacles
with this navigation mesh. Yeah, basically,
we are done with the basic click to
move mechanics, FSM, and of course, we are going to expand
this in later videos. A.
5. 04 Base Interactable FSM: Hello. Now we are going to continue develop our
point and click game. In this video, we are going to start to create an
interactable component. Intactable component is
a component that we can attach to an NPC or
other game object, and the player will be able to interact with those objects, either an NPC or other, for example, like an item
like a door or anything. And we want to make it as
modulized as possible. So interactable, we
will hold an actions. And then whenever we interact with an
interactable object, we won't trigger all
of the actions that are registered on
the interactable. The interactable
part of the video will be split to a
multiple videos. And now let's create the
base interactable component. So here, in the scene, I'm going to create a new three
d game object, a capsule. And let's just rename
this capsule to NPC one. And on the scene here, let's just reset the transform
and set the position y21, and we can move to a certain
location, for example here. And make sure that the transform or the
coordinate is set to local, so we can see the local
transform of an object here, and as you can see, the
z is facing that way. And with this interactable, we want to create a
default interact position, and this position will
dictate the player position whenever we want to approach this interactable game object. So for example, let's just
rotate this NPC by pressing E, we can switch to the
rotate control here, and then hold control, and we can rotate it by five
degrees incrementally. So for example, if we want to make this character
facing that way, and with this orientations, we can set the
interact position to run in front of this
NPC game object. So now let's create the FSM. I'm going to add an FSM here, and let's just call
this interactable. And here, we want to define the target position
of this interactable. So let's just change the
state name, define position. And basically, with
divine position, we want to get the owner first. And with G owner, we can save the game object where
this FSMs is attached to. So let's just create
a new variable. And let's just call this owner. And next, we need to add
a get position action. So let's just type get position, and we should be able to use
the Gt position action here. And let's put the get
position below the Get owner. And we can specify game object. Although we can use owner, but we can specify game object, and later we are going to use this owner variable for
running the action. So we need this variable anyway. So I'm going to use
that owner variable. And let's just store the vector position to
a new variable. And let's just call
this target position. And let's set the space to
world. Let's minimize this. The next thing that we want to add is the transform direction. So let's just type transform, and we should be able to use a transform
direction actions. Basically, this
is for converting a local directions of the player or a
certain game object, and it will change
those direction into a world space vector. So basically, we just need
to use the owner here, and we want to get the di, the forward directions,
which is the z axis, so the local directions
would be zero, zero, and one on the z axis. And this will be equal to the local directions of the blue axis of
this player here. But we need the value
in world space. In d space, the value is
not going to be 001 because 001 on oral space
will align with this arrow on the
view gizmo here, and this is the 001
on the world axis. So we need this value to be
converted in world space. Let's just save this to a
new variable called forward. And we want to dictate the distance from
the interactable to the target position. In order to do that, we need
to multiply the forward with a float number and this will change the
length of the vector. Here on the variable,
I'm going to create a new variable
called stopping distance. I'm going to expose this
as an input variable here, so we can see it here, and let's set its value by
default 201.5, for example. Now we have this value here. The next thing that
we want to add is the vector three multiply. Let's just search for multiply and pick the vector 31 here. And we want to multiply the forward direction with the stopping distance that
we have just created. And now we will have a longer or shorter forward depending on
the stopping distance value. In this case, it's
going to be longer because we set the value to 1.5. The next thing that
we want to add is the Vector three ad operation, so let's just search for it, and this is the one that
we want to use here. Vector three d. And basically, we need to put this
vector three at below the multiply because the order
is important in this case, because some actions realize on values that are generated
by previous action. Here the Vector three variables. Let's set this to
the target position, and we want to add
this position, or we want to offset this
position based on the forward. Because the forward doesn't contains position informations, I just contains
direction information, so we need to add both the get position result and with the transform
direction result. Now that we have added, this will change the target
position value actually. We don't need to store these operations into a new variable. This will override
the target position. Now we have finished set up
the define position state. We need to create
another state here. And let's just call
this interaction. And we need to create a
global transition here. I'm going to create a new event here and I'm going to
call this interacted. Let's at this as a global event here by checking this
wave icon form here. And now we can add
the global transition here and pick interacted. And now we want to go back to defined position whenever we finish running
the interaction. I'm going to add a
finish transition and go back to
defined interaction. For now, we are not going to do anything other
than debugging. Let's just open the
action browser again. I'm going to run
the debug log here. And let's set this to info. We can set a text, for example, interacted, and we can send this to Unity Log so we can see it on
the console here. Okay. Now we are just going to do debugging. Let's
save the scene. Next, we need to
modify the player FSM, which is the click
to move FSM here. And basically, we need to check if we are clicking
an interactable. And in order to do that, I'm going to add a new
layer for this NPC here. So let's just
create a new layer, and let's just call
this interact. And go back to the NPC, and we can pick
the interactable. And now let's go back to
the player game object. Here in the defined
destination state, we want to duplicate
the mouse peck here by pressing control
C and then control V, and we need to change the started peck object
to a new variable, so let's just create a new one. And let's just call this
valid interactable. And for the layer, let's change
this to the interactable. We don't need the position here, so let's just set this to none. But we want to store the game
object with this one here. So let's just create
a new variable, and let's just call
this interactable. And now that we have
add this mouse pick, let's just minimize
the mouse pick, and we need to create
another bull test here. Let's just duplicate this. And then let's just pick
the valid interactable. And in this case, we want to
change the true event here. Let's just create a new event. I. And let's just call
this go to interact. And let's add this transition,
go to interactable. Let's move this transition up, so it's nicely ordered here. And let's pick the go
to interactable event. I don't think we need this
finish here. Yeah, correct. We don't need this finish
because this finish, we want to set the bull test
here to the first bull test. But if we are setting this
finish transition here, Then if we are not
clicking interactable or if the valid interactable
bul in value is false, then it will go back to finish, and it won't evaluate
this second bull task. So we need to do that. So
let's just set this to none, and then we need to
create a new state. And we can create it by holding Control and drag
a new transition. This will create a new state. In this new state, we want to get
interact position. So in order to do that, we can use the get FSM
vector three action. So let's just type get FSM, and we should have a lot of get FSM with
different types here. So I'm going to
pick the vector 31. And now that we have
saved the game object, we can use that game object by specifying the game object, and we can pick the
interactable game object. The FSM name, it's going
to be interactable. So we can just type this. Because we know that on the FSM, basically the FSM
with the name of interactable is the one that have this target
position defined here. So we need to access
this variable. And here on the player, we can type the variable
name, it's target position. And this has to be exactly
the same case wise also. So always make sure to check
on your source FSM here. And store its value to
the target pause here. Once we have set up
the target pause here, we can just add a
finished transition and we can go to this
set destination. Now we have set up the
go to interactable. We need to trigger the interacted event
whenever the player arrive. So in order to do that, here, we can check inside
this way to arrive. In order to run the FSM, in the interacted event
on this FSM interactable. We need to go to
this arrived state. And here we want to check if a game object
is null or not. So let's just use game object. I think it's with space
game object is null. And let's check
the interactable. If it's null, then we want
to go to the finished state. And we can run this every frame. And if it's not null, then it
will stay in this arrived, and we want to also send an ev. So let's just add a send action here and make sure that this is below the
game object is null, so I'm going to drag
this to the top. And we can use the game object FSM here and specify
game object, and we can pick
the interactable. And at this point, interact won't be null
because if it's null, then it won't get
to this action. It will go to the
finished state here, as you can see, and it will
go to the first state. So we don't need to worry
for any null reference. And we know that the
FSM is called interact. And we want to send
a global event and we have created this
interacted. So we can use that. And by default, the
player might not be facing the
interactable game object. So in order to do that, we can add a smooth
looked at action. And for the target game object. We can use the interactable. And let's set the vector
21 on the y axis, so it will rotate on the y axis. Check the keep vertical
and set the speed 210, so it rotates quite quickly. And once it's finished, we want to run the
finish event also. Now let's save the scene, and let's give this a try. Now we can click on I'm going to open the console and we can
click the interactable. And as you can see here,
once it's arrived, we have this log output on
the console says interacted. So it means that
the states here, it's running, it gets fired. So it means that our interactable
component is working. And now, for example, if we stop this and if we change the stopping distance on the interactable FSMs
to a very far value, for example, four, then we will have a very far
stopping distance. And this might come handy
in your game design. So let's just give it
a try. There you go. It stop at that position, and it says interacted. So yeah, that is the basic
intractable component, and we are going to
expand this further. We are going to add
actions that we can pair or chain in the
intractable FSM.
6. 05 Base Action FSM: Hi. In this video, we are going to implement the action FSM. And this action is
going to be a template. Template is very powerful
in playmaker because it can create or it can convert
an FSM into an action. So those template can
be run as an action. Here I already created some
sort of a concept here, a flow chart, a graphics. And basically, any action FSM must have a global
transition called run action. And this is where all
of the actions happens. And with this agreement
that any action FSM needs to have a global
transition called run action, We can create different actions, and the interactable component can easily run those actions, even though each action has
like a different ability or capability like showing messages or moving an am object, like moving an NPC. Also some sort of creating interactions
with item like giving or receiving item and
any other actions that we are going to
implement in this scheme. So let's go back to unity. And here, the first thing
that we need to do is we need to create a
simple basic action, and right now, we are just going to show a message
in the console. To make this work,
and later, of course, we are going to implement
the dialogue manager where we can show
messages in the game. So let's select the NPC now, and let's create another FSM. Just to make things
easier to organize, I will always create an
action on the child object of the interactable game object or the game object that has interactable component
or FSMs attached to it. So here, let's just
create an mt game object, and let's just call
this base dialogue. And here I'm going
to create new FSM. And in this FSM, we are going to create
a basic dialogue FSM. So here we are not going to
do anything on the start, but let's create another state, which is the state
to show the message. And let's just call
this show dialogue. Right now, we only want
to show the message in the console so we can
use the debug log again. And for the text, we want
to create a variable. And basically, we want to create an array of string
because we want to have the capability to
create some sort of multiple dialogues that are continue after each
other consecutively. So here on the variable, let's just create a U
variable called messages. And let's change
this to an array. And for the type,
let's set this string. K. And this is going to
be an input variable. So let's just enable this. We are exposing this variable
to make it easier to modify via the inspector
without opening the FSM. Here, let's just
create one element, and let's just call
this test dialogue. And now we want to show this in our show dialog, the bug log. So we need to get the
value array or get array. I and basically, we want to get the first
one, which is index zero, and in order to
get a ray member, we need to sort it
into a variable, so let's just create
a new variable. For now, I'm going to
call this debug tax, and I'm going to
show the value in our debug log here by
selecting the variable. And if we go back to
the concept here, we have this global
transition called run action that we need to
add into each of the action. So I'm going to
create a new event, and let's just call
this run action. And enable the
global event here. And now we can add this Run
actions global transition. Okay, so now we have this
base dialog FSM setup. We need to create some sort of an action that can
run multiple FSM. So we can hook those actions into this interactable
component. And this run interaction
state can run multiple FSM or
multiple actions in it. So now we are going to create the run FSM action template. We can just create it here on
the base dialogue for now, and later we can
just delete the FSM, so I'm going to
right click here, and I'm going to
create a new FSM. We need to click it here, so
let's just create new FSM. And let's call this
FSM action un FSM. You can name it
anything you want. But for clarity's sake, I'm going to add a
prefix action for an FSM that are going to
be saved into a template, but it will be used as an
action as a custom actions, and I'm going to add
this action prefix. And later, we are
going to also have a template FSM that has
a template prefix on it, and that will act
as a different FSM. It's not going to
be an action FSM. And here on the
action run FSM here, we want to loop the array. First, we need to create
an input variable. So I'm going to create an
array variable called actions. And this is going to
be type of input, and input output is very
useful for creating template. Basically input variable,
we can fit a value or a variable from the FSM that is running that template
as an input variable. And for the output variable, this is a variable
that are going to be a result or a return from
that FSM action template. So for example, if
this FSM actions shod return any values or
any data or any object, then we can put it
on the output and the other FSMs that are running this action FSM can get those value once the actions
has finished running. Okay. So the next
thing that we want to add is a object variable. And this will be the current FSM because we
are going to loop the FSM. And for the type, we can change
this to a playmaker FSM. Okay. Now for this array float, we want to also change
the type to object, and then object type, we want to also pick
the player FSM. So this is going to be an
array that holds reference to the player FSM that we
are going to assign later. So here on the start, let's just rename the
state to Loop array. And I'm going to create a
local event called Loop, and let's add that
loop transition and as well the
finish transition. And here for the loop, let's create a new state. And let's just
call this run FSM. And for the finish, we want
to also create a new state. And inside this finished state, whenever we are running an FSM as an action
via a template, we need to run a finished FSM to let know that the action
has finished running. So we need to add the finished FSM action
here, and that's it. And whenever we are
running the FSM, we want to add a
finished transition, and then connect this finish
back to the loop array here. Okay. So here on the loop array, we want to use the array, get next action,
and this will look. Every member in our array, and for the array, we are
going to grab the actions. For the start and n index, we can set this 20, then this will loop
every member inside of our actions array or any
array that you want to loop. But if you want to loop from a certain starting index
or two a certain n index, you need to insert a
certain value here. And we need to set the loop even to loop here and
for finish to finish. For the result, we want
to save or we want to grab the member when we are looping this array
to the current FSM. So for example, if the array get next is starting
from the first index, then the current FSM will be the first FSM on
the actions array. Then we loop to the run FSM. When we are finished
entering this state again, then it will go to
the next member, and it will save those next
member to the current FSM, and it will do the same again. It will run the FSM again here. So now we have set
up the loop array. The next thing that
we want to do, we want to run the FSM, and we want to send the run action global
transitions event to this FSM. We can use a SN event action. But with this, if you
want to send an event, you need to grab the game object by specifying the
game object here, and you will need to
know the FSM name. So you need to get those information from
our current FSM here. It's a bit tedious, so there
is a better way to do this. I'm going to delete
the SN event here, and we can use the call method. And this is basically
accessing a method from a script if we have
a custom script that we want to run via Plemker, but we can also run
a method in FSM. Because basically when
we are transitioning from one state to another state
via transition even here, we are actually sending a method with a string
argument, so we can use that. Let me just show you
here to make it clearer. I'm going to select the behavior and then
pick the current FSM, and it will know that this
is a type of playmaker FSM. So it can list the methods
that are available, at least public methods that are available in this
current FSM because Playmaker FSM is basically also a class script that behave the same like any
other C shop script. So we can access
the public methods that are available in it. And I'm going to use
the SN event here. And SN event as
for a event name. And event name is basically the event that we
have created here. In this case, we want
to run the run action, because as we can see here, every action FSM should have run action
global transition. So that is the transition or the event that
we want to run. So we can easily just type
this with all capital, and this should run the
global transition run actions on that certain FSM. Okay, so now we
have set up this. We need to save
this as a template. So in order to do that, just right click here,
and we can save Tplate. And here we can go to
our project folder here. Plate Maker folder already
has a template folder, so we can just use
that if we want. I'm going to rename this
two action run FMS. This will indicate a plural FSM, so we can run multiple FSM,
and let's just save this. And then we don't need to
use the safe template here. We can just delete
this second FSM. Okay, now we have
created those template, and we are going to use
the template that we have just created on the
interacted state here. Here instead of running
the debug lock here, let's just use the FSM. Run FSM will enable us to run an FSM template that
we save in our project. So if I browse here, you see that we have
no category here, and we have action run FSM. And if I click this here, you see that we will
have an input actions, which is an array
of play Macer FSM. So we can just use
variable here, and we can just create a new variable that
we want to use. So let's just create a new
variable called actions. And we need to also hook the
finish event back to finish. So when the finished FSMs gets executed in our
FSM template here, the action, then this will get triggered and it will
go back to the start state. Okay. So now we have
created the actions. We want to make sure
that this actions is an input variable, so it is visible here. And now we can hook
our base dialogue FSM. So for example, if I
add a member here, we can drag the base dialogue, and it will register our FSM. And now let's save this. If everything runs correctly, we can see that it should show our first member of the
string here in our message, the Test dialogue
exclamation mark. And probably we want to
send the action back to the first state whenever
we finish showing the dialogue here or
showing the message. So let's just add a
finished transition and go back to the first state. Okay, now let's give it a try. Here, let's take a
look at our console, and I'm going to go
to the interactable. Okay. There seems
to be an issue. Let's take a look here. I'm going to click this again. Okay. It runs the interactions, but for some reason,
it doesn't run this. Okay. We can debug
this by selecting the base dialog and go
to the interactable, and it gets triggered
actually. Oh, yeah. I forget to enable the
cent Unity log here. So let's just stop this here. And on the run action, let's enable the cent unity log, so we can see the console. So it was actually
working before, but we don't see the message in console because we are not sending those message
to the console. Okay, now let's try this
again. There you go. We have this message
shown in the console, and it has this test
dialogue message. And the neat thing
with the setup is that if we
change the message, for example, to
Hey, how are you? For example. Then if
we run the game again, the message will be
different this time. So now we have the
basic actions running. Let's try to test
for multiple FSM. So I'm going to duplicate
the base dialogue, and let's just call
this second dialogue. Although since we are using an array of messages
or string here, we can create multiple
dialogue in one FSM. So we don't need to do this. But just to illustrate the multiple FSM or the action run FSMs
working with multiple FSM. Let's just give this a try. So let's just change the
second dialogue here. Message. That's good to here. And if everything
works correctly, then we should see two
message here. Oh, sorry. I forgot to assign
the second one, so I'm going to stop the
game here and go back to this interactable FSM here
and expand the actions. Let's increase the size. Then we want to drag
the second dialogue. Okay. So now, I think we
are done set up this. Let's just give another run. Okay, as you can see,
it works great here. We are seeing the first
message in the console, and we also see the second
message in the console. So it means that our run
FSM is working as it so, and in next lesson, we are going to
expand these actions. We are going to create
multiple different actions.
7. 06 Dialog Manager UI Setup: Now we are going to continue
to create our actions more usable because currently we only outputting
message to the Csole. So in order to make
a dialog messages, first, we need to define
the dialog manager. And first thing that
I want to do is I want to change the game
view from three aspect here to 16 by nine
aspect so we can design our UI according to
the screen ratio sizing. So here we want to create
a new Canvas under the UI. Let's create a new
Canvas game object. And with creating Canvas, it will automatically
create event system, and this will be used to handle the event from mouse clicking so our UI component can responds to our mouse position or mouse
status like clicking, hover and other stuff. Here, on the Canvas game object, we want to change the
Canvas scaler from constant pixel size to a
scale with screen size. And let's just make this a
full HD resolution ten ADP. So this is the width
and this is the hight, and let's just make the
match to middle 0.5. So it will try to match
the width and the height. If the resolutions on the target device or on
the user device changes, and this will decide
how do we want to match the UI layout to
those new screen sizes. I'm going to save
the scene here. And the next thing
that we want to create is we want to create an
empty game object here. And basically, this empty
game object will hold all of the dialogue window
component as a child here. So I'm going to change the
view to the view here, and let's just center to
our game object here. And this is our UI space. And I'm going to rename the game object to
dialogue Manager. And I'm going to set the
height to around 250. And I'm going to put its
position to this one here, this stretch on the bottom
area of our screen. So if you hold out, we can line or we can snap the settings and the anchor
preset to this position here, and we will have a very
wide panel below here. And now we can create
another game object, and the next game object, it's going to be an
image game object because this is going
to be our panel, and we can hide and
show this game object later to show any messages
that we want to show. So I'm going to
also stretch this, but I'm going to add a margin
on the rec transform here. At least I'm going to add 25 pixel on the left side and 25 pixels on the right side. And for the bottom side, let's just add this
like 40 pixels. So we should have
something like this. Or if we want to make it even more larger in
gap from the site, we can add like
150150, for example. Okay. Maybe this makes
more sense for dialog UI. And the next thing
that I want to do is, I want to make the color black, so I'm going to change
the color here and set the transparency
to around 50%. I should do the trick. And the next thing
that we want to do is we want to rename
this image to panel. And we need to add another child object
which is the text object, and I'm going to use
the text Mash pro here. Since this is a new project, we need to import
the TMP essential, so Let's just click this button. Now it has finished importing. We can close this,
and I'm going to also stretch the transform
of this tax object. So it fits our panel. But let's add a margin. I'm going to set this 240 by 40, and then top also 40. I think it's two far, 40, let's make this 20 on the top. And for the bottom,
we need to make this bigger than our
top margin because we want to have a button for a DLO button for
choosing an options. So I'm going to make
this probably around 60. Yeah. Six this should be good. And we can save the scene here. And we want to create the button that that
will be used for deciding if there are an
options or if we want to add a yes or no
options in our dialogue. So let's just create another
empty game object here. And I'm going to make
this stretch here below. But let's just set
the height 260. And then snap it again, and we want to add
a left margin. So let's just add like 500 or 600 and for the
right, let's add this 20. So now we should have something
looking like this here, and now we can add the
child game object. So I'm going to rename
this game object to button questions,
for example, And then we want to add
a child game object, which is a button, and we are going to use the
text mesh pro button here. And for the button, we can change the source image. I think I'm going to remove this source image because
sometimes it gets blurry, so I'm going to just
to set this two none. And let's set this two
color black color. This is going to
be the yes button. So let's just rename that. And we can just set
the text to it. And we want to
duplicate this button, and let's set this to no button. And now that we
have set this up, let's add a horizontal
layout group, and this will distribute
our button automatically. I want to stretch the child size of the button
at least on the width, so it will fill up our empty game object or the parent game object
here, the button questions. Let's add a spacing
like 20 pixels. This should do, and let's set the alignment
to middle center. We will have this center and we can increase the
height of the button here. I'm going to set this 250 or 45, so we will have
some sort of gap. And for the button,
probably we can add a gap here on the
parent game object. We can change the right margin
to run 25 or perhaps 40, so it a lines with
our text box here, and we should have something
looking like this right now. So basically, we have set up the UI for our dialog manager. In the next video,
we are going to create the logics or
the FSMs for this.
8. 07 Dialog Manager FSM Setup: Okay. Now we have set up
the dialogue manager UI. Let's create the functionality
for our dialogue manager. Let's select the dialog manager here and let's create a new FSM. And for this FSM, I'm going to call this
dialogue manager. And the first state, it's going to be an
initialized state. So let's just initialize this. And we want to create
a global variable. With global variable,
we can easily access that variable from any
FSM in our project. So the gist is that
we want to create a global variable that will hold reference to this game
object, the dialog manager, and any other object FSM can access the dialog manager
via that global variable. So let's go to the
playmaker menu here. Under the editor windows, we can just pick
global variables. And here, let's
add a game object. And let's just call
this dial up manager. Okay. Now, we have created
this global variable. We can just close the window. And for initializing, basically, we want to use the
get owner action and store the owner to a global
variable dialog manager. And this will save the
dialog manager game object into this variable. So we have a easy reference for other object to know where
this dialog manager is. Okay. And next thing that
we want to do is we want to disable the panel on start, so it gets hidden. And basically, we want to create a variable
game object here. And let's just call this panel. And to make it easier, we want to expose this
as an input variable, and we can direct the panel game object
to our inspector here. So we will have
reference to our panel. And here on the start state, we want to use the activate
game object action. And then we want to hide it. So we need to
specify game object, pick the variable that
we've just created, we just panel, and
disable the recursive, and also disable activate. And this will hide
the game object or it will uncheck the checkbox here
us hiding the game object. So go back to the dialogue
manager here, save the scene. And now we need to
create an event first. And this need to
be a global event because we want to access
this event from other FSM. I'm going to create
this show message and check this global
broadcast or global event, and let's create a new state, and let's just call
this in dialog window, and we want to add a global
transition show message. Here, basically, we want to get the message
length that we have, and then we want to deactivate the button questions
panel game object here, so it doesn't show
the button at first. And then we want to go to
the next state after that. So first, we need to
use the array length. And array length with
basically we'll get the member amounts of any
array that we have defined. And on the variable, we need to create a
new string array. So I'm going to pick array, and let's just call
this messages. And let's change
the type to string. And the string messages, let's make it as
an input variable. And here on the array length, we want to get the
length of our message. And let's save this
into a new variable, which is a type of integer, and this will automatically
create the variable, and I'm going to call
this messages length. Sorry. Messages length, like so, and y create this. And then the next thing
that we want to do is we want to use the
activate game object here. And basically, we want to
deactivate the questions panel. So let's just create a
new game object variable. And let's just call
this questions panel. And for this questions panel, we want to set this also
as an input variable, and we want to hide
that game object. So let's uncheck this
recursive and activate. And now we have this expose. We can drag the button
questions to the slot here. And then we can just
finish this state here, and we want to go
to the next state. So I'm going to create a new
state by holding control. And this is going to loop
for looping the messages. So we want to create
a loop messages state because we are using array, so we want to have
the capability of showing multiple texts using
this array of strings. Here in the loop messages, we want to use the
ray get next action. And basically array get
next actions will quickly look through all of the items of an array to perform
actions on them. So we can add this here, and we can pick the messages, and we can decide the
start index and n index. But if you want to look through all of the
members of our array, then we can just
leave this value to zero on the both start
index and n index. But if you have a
specific start index that you want to start from, or if there are specific n
index that you want to at, then you will need to insert
a certain value here. In this case, let's
just lift this to 00. And for the Loop event, we want to create an
event called Loop. We don't need this
to be a global, so let's just uncheck those. For the Loop event, we
want to pick the loop. And let's add the
loop transition here. And whenever we are looping
the messages array, we need to sore the result
into a string variable. So let's just create
a new variable, and let's just call
this current message. We will have a string here, and we can use the string
to show the message. We want to also save the
current index because we are going to need it later when
we are showing the buttons. So let's just save this into a new variable called
current index. And we need to add a
finished transition. And we want to finish the event by sending it to
the finish transition here. So let's just pick finish. And now whenever we
are loping the array, we want to go to a new state, and basically, we want
to show the message. And here on the show message, we want to activate the panel. So let's just add activate
game object action. And then we can pick
the panel variable, and we want to activate this, but we don't need to enable
the recursive options. So let's just check
the activate options. We can minimize this.
And then we can use the type writer. We
don't have that. So we need to download
it from ecosystem. So let's just open the
ecosystem browser here, and we can type type writer. Now we have the
actions that we need. We can just press the
get button and it will download these
actions into our project. Okay. Now it finish compiling, so let's just close
this ecosystem browser. And now let's just search for the string type writer
action. We can add this. And this will create a very
nice typewriting effect on our dialog text. And basically, we need to get the covered message string
as the base string, and we want to save this
to a result string. And for the result string, we need to create
a new variable. Let's just call
this type message. And we can just leave the
default setting here. And whenever we finish
the typewriter, we want to go to the next state. So let's just add
a new transition. I'm going to create
the transition first. Here. Let's just call this next, and we can add the
transition next. And here on the
type writer action. Let's just pick the next transition in the
finished event. And next, we need to show
this type message string, which is going to be
a animated string or string that change over time to this text
mesh pro game object on our dialog panel. And in order to do that, we need to download
a custom action for modifying or accessing the text Mash pro functionality in unity. And I'm going to put the link to the Gita page for
this custom action. And here, basically,
you can just download the repo to a ZIP. Once you've downloaded,
you should have a ZIP file similar like this, and we can drag this folder. So I'm going to drag the Text Mh pro playmaker folder here into our project folder. So let's just open
the project folder here by right clicking
it and show Explorer, should open the project folder. Go to the access folder and inside the playmaker
custom actions, I'm going to drag
our folder here. And once it's
finished extracting, let's just rename
this to Text MSP. Okay. So let's just close this folder and let's
head back to Unity, and it will compile the new actions that
we've just imported. Okay. Now it's done. And let's go back to
the playmaker editor. Let's select the
dialogue Manager. And here, after we are updating the text
or the string here, we can just minimize this now. And add a new action, and now we should
have new group, which is going to be
the tex Mash pro here. And as you can see, we have
a lot of subcategory here, and the one that
we want to use is the tex Mash pro GI basic, and we want to set the set
tex mash pro I tax here. So let's just use this. And then we can
specify game object. And for the game object, we need to create a variable. So let's just create a new
variable game object here, and let's just call
this dialogue tax, and let's enable
the input variable, so we can access it here, and let's just direct the
TMP game object here. And now we want to
use that game object. And for the text, we are going
to use the type message, and let's enable every frame. So the text will get updated every frame when
we are in the state. And basically, here we want
to add a on click event. So let's just use the UI on click on point
or click event. And we can just set the
game object to the panel. So let's just
specify game object and then pick the
panel game object. And for the event target, we want to set this two self, so it will trigger
any transition that we have added here, and let's create another event
called complete message. And we want to add
that transition. And here on the point
or click event, we want to go to that
complete message, then we want to create a new state out of
this transition. And in this complete message, we want to add a
couple of actions. So let's just rename
the state first, and let's just call
this complete text. And here, we want to use
the text Ms pro again. So let's just for I
think it's the UI basic. Yeah. And we want to set the
text Ms pro I text again. We need to pick the game object. From the variable,
which is dial up text. And for the text, we want to set this to
the current message. So we want to complete
this upon clicking. So whenever user
click the panel, it should skip the typing and then show the
complete text here. Then we want to add
a next transition, and add on click event again. We can pick the panel, then we want to go to the next. And here we want to go back
to the loop message here. But if the text finish showing, we should fire the next event, so we need to create
a new state here. And we can call this
wait for click. And let's just add a
finished transition. And we want to use the on
point or click event again, set the same game object, which is panel, and let's
just call the finish. And now we have this. But when we are finishing the showing the all
of the message, then we want to hide the panel. So let's just create
a new state here. And let's just call
this end of message. And here, basically, we
want to hide the panel. So let's just add and
activate game object action, we can pick the panel. And disable it or the activate it by
unchecking the activate, and we want to also
uncheck the recursive. Okay. So this is the
basic dialog manager, and now we are done with this. Next, we are going to implement
the action to use this. And of course, once we are adding functionality
for the questions, we are going to modify
our dialogue manager.
9. 08 Send Dialog Action: Now let's modify
the dialog actions or the one that we have
created for this NPC here. And basically, we want to modify the run effem. Let
me check here. We have this interactable
base dialog. Okay. We want to modify
this base dialog FSM, so it will run
multiple messages. Right now here on
the show dialogue, we are only debugging
the first message, but we want to send this array text to our dialogue manager and show it using the
dialogue manager. Let's just delete
this ray get and debug log here and
to show a dialogue. We want to create a FSM template
to be used as an action. So let's just add
another FSM here. And let's just call this
action sen dialogue. And basically, on the
first state here, we want to rename
this two SN dialogue, and let's add a
finished transition, and then we want to
end the FSM here. For ending the FSM, we can just add finished FSM. Because this is going to
be an action that we are going to use using
the run FSM action, so we need to run this FSM to notify that action that this template has
finished running. Let's go back to the Send
dialogue, state here. And basically, we want to send the array string
array of messages. So let's just create array. And let's just call
this messages. And this should be
a type of string, and we want to make this
as an input variable. We also need to add a
couple of string variable. So let's just add the first one. And this will be
the question no. Although we haven't
implemented this yet, but let's just add this now. And this will be
the question yes. And this will be the copy for the button text for the
yes button and the no button. And we also want to send
the questions bulion. And this should be a type of bully, let's just change this. Okay. For now, this should do. Let's set up the state here. The first one that we want
to send is the messages. Let's just use the
set FSM array. And we want to send this
to a specific game object, which is the dialog
manager that we have defined on our
global variable. And since it only has one FSM, we don't need to specify the SSM name for
this dialog manager, but we need to specify
the variable name, so I'm going to type messages. And let's double
check this again. If we go to dialog manager, we should have the messages. Yeah, this message array of
string, so we have this. Let's go back to this
base dialogue here. And now we want to set
the messages variable on the dialogue manager to use the values from our messages
here that we have defined. And we want to check
these copy values here. Let's minimize this.
And we need to set a couple of FSM
string and FSM b. So let's just specify this
to the dialogue manager. We haven't set up
the variable name, so let's just set the
value for now here. This won't do
anything because it won't find the variable name. But once we've implement
this, this should work. So I'm going to copy this here, and let's set this to the
string. Let's minimize this. And let's just set the ble also. And we need to specify the dialogue manager here and set the value to
the questions here. And we also haven't
defined this, so we cannot put
any variable name. Onto it. And the next thing that we want to do is we
want to send an event. So let's just use
the send event here. For the event target, we need to set to
the game object FSM and specify game object, which is going to be the
dialogue manager again. And we can just leave the
FSM name empty and we want to send the global
event show message. Here. Okay. So now whenever
it finished the state, it will go to the N FSM, and it will finish the
template. We have this error. Icon. It doesn't look very good. So let's just quickly
implement those variable. So here, let's add a string, and let's just call
this questions Q yes, Q underscore yes, and
this is going to be the input and create
another string. This should be the Q no. And let's create a bullion, and let's just call
this questions and set this to also
as an input variable. And now we have defined this variable on the
dialogue manager. We can go back to the
base dialogue here, and now we can set those
name as the variable name. This should be the same Q, yes, because we have
defined the same name. This is or underscore, and this will be the questions. Okay. You can name the variable anything that you want or you can
follow my convention. It's really up to
you. And now we have set up this FM template. Let's save this as a template. I'm going to call this action San dialog. And let's save this. We don't want to use this in this FSM because we are
going to delete this, so let's just remove
the component here. And now in this show dialogue, we can use the run
FSM action here, and then we can pick the action underscore
sen dialog tplate here. And for the message, we can just send the
messages that we have here. Okay. We need to also
expose this variable, the no, the yes, and
the question variable. But for now, we can
just lift this. Once we are going to
implement the interaction, then we are going
to change this. So if we go back here, you see that we
should be able to run the dialogue or
to send the dialogue. And here on the event, we want to send the state back to the first state whenever we finish this event here. And this is why we
need the finish FSM on our template because this will trigger
this event here. So let's save the scene, and now let's delete
the second dialogue. And under the NPC interactable, we want to set the
action back to one, so it will only trigger
this base dialogue FSM. And now we can have
multiple message. Let's just change this
to something else. Let's just type the weather
is very nice today. Okay, so we should have
two dialogue here, the first dialogue, and this
is the second dialogue. Let's save the scene, and
now let's give it a try. I'm going to select the
dialogue manager so we can see what happens
inside the FSM. And as you can see here, it shows the message. And if I click, it continues the second message, and we can close this
by clicking it again. It will close the window. But as you can see, whenever
we are interacting, then we are pressing this I. We also move the player. So we want to prevent that. And we need to also
hide the button. So here, let's add a
couple of modification. We should activate
the game object here. Okay, I put the
wrong variable here. This should be the
questions panel. So let's just save this gain. And now with this
clicking and it moved the character instead of keeping the character
on that position, we need to create
some sort of a bulion that are indicating that we are opening the
dialog window. And with this bion whenever
this bulion is true, we want to ignore any
clicks on our player FSM. So basically, we want
to set this bulion to true whenever we are
activating the panel here. In order to do that, let's
create a global variable. And let's just
call this UI open. And this is going to
be a type of bull. Let's just call this UI
opened. L et's close this. And now we want to set a bullion value using the bull
value set bull value here. Drag this to the top
of our stack action, and then pick the UI open
variable and set this to true. We can copy this actions by pressing controls while
highlighting the action. And let's go to the end
of message state here, and we want to
paste this actions, and we want to uncheck this. Okay. So basically, whenever we are deactivating the panel, then we want to disable or set the UI open bulion
value to falls. Okay, save this. And now we want to go to the
player game object, and we want to modify
this FSM here. So basically, we want
to test a bulion value. If the bion value is true, then we want to go
back to finish. So here, let's just
duplicate the bull test. We should have two
valid intractable. Okay. Let's keep the second one, and let's change the first one to use the globals UI open, and we want to set the
second one to none. But we want to set the
first one to finish. So if UI or the
dialogue UI is opened, then we want to cancel
this defined destination, and it will go back to the finish transition to
the first state here. And if it's false, it means that the UI is closed, then we want to ignore
this bull test, and it will check for
the other two bull task, depending on the condition. Let's save the scene, and now
let's give it a try again. Okay. It's showing the dialogue and we don't have
the button anymore. If I click this, it
show the second one. And if I click this again, it will close the window
and we can move around. Let's just try it again while
we are on the dialogue, we cannot go anywhere. But we need to add
functionality where if we click outside of the UI here, then we should be able to cancel dialogue and move the
player to that position. Okay, so now let's
implement that. First, we need to
create an empty button or a transparent button
or run or a canvas here. Here on the Canvas, I'm going to create a new button from the UI, and let's just call
this empty area. And I'm going to put this
on top on the stack here, so it gets rendered first before the other
UI dialog manager. And here on the button, we want to expand this transform to
cover the screen area, and we want to also
delete the text object. And for the image here, we want to set the
source image to none, and let's set the
color transparency or alpha value to zero. It is transparent. And here
on the dialogue manager, let's create a new variable, and this is going to be
a type of game object. And let's just call
this empty area. And I'm going to enable
the input variable here so we can access it
easily on the inspector. And let's drag the empty area game object
into this slot here. Next, we want to add a new
event called cancel dialogue. And here, we want to add this cancel dialogue on the
complete text state here. On the show message state, and also on the wait for click. So whenever we are
given any chance to have input like mouse
click on the dialogue UI, we want to have also the
options to cancel dialogue. And here, basically, we
need to copy these actions. I can press Control C and
Control V. It will copy it and we want to
pick the empty area, and if we click the empty area, then we want to send the
cancel dialogue event. Let's just copy this action by pressing Control C again
on the second one here, and we can paste it on the state here on
the wait for click, and also on the show messages, so we can highlight this. And then press Control V, it will paste this below
the highlighted action. So basically, we need to have
two poin or click event, first panel, and the
second one empty area. And for the cancel dialogue, we want to go to the
end of messages. And this should
cancel the dialog if we press or if we click the mouse outside of the
dialog window because we are going to click those
empty area button. There is one thing that we
need to do here is basically, we need to add a
bullion variable, and this is going to be the
reset variable for resetting our array get nex because when
we are canceling dialogue, there is a chance that
these actions doesn't finish looping all of
the member iterations. So whenever we are entering
the array get next, it will keep the current index behind the actions
or behind the scene, and it will continue
that index when we are showing the next dialogue
or a different dialogue. So we need to reset the we need to use these
reset flag options. And basically, this asked
for a bulion value. And whenever we are
passing a bulion, if the bulion value is true, then whenever we are executing
this array get next, the iterator or the index
will reset from zero. And after we are resetting
this array get next, this bleion will change
to falls automatically. So in order to reset this, whenever we are initializing
the dialog window, we want to set that bulion
reset value to true. So the flow will be that whenever we are starting
the dialog window, we are initializing
here and we are setting the reset
bulion to True. When we are entering
the second state, the array get next
will gets reset, and then the reset bulion
will turns to falle. We can see it on the run time. I will show it in a bit. But another thing that I
want to add is I want to add weight actions on the
init dialog window. And I want to send the finish after a fraction of a second, so we don't have
infinite look when we are already arrive
on the NPC position, and we are trying to
conversate again. And I'm going to set
the value to 0.2, and now let's give this a try. And now let's go to this NPC, and now we can cancel this dialogue by clicking
outside the window. And if we click this again, it will show the dialogue again. And let me just show you here. If I disable this weight action, And let's just click this
again. There you go. If we arrive on
the position here, and if I click on the NPC, there is a chance all of this transition
happened in one frame. So it evaluates the
clicks in one frame, and we are canceling
the dialog because the NPC position is outside
of the UI dialog window. So this is why I added
the weight action. And this way we can
try to conversate. Okay, there is a bug here. For some reason, I connect
this finish to a wrong state, so this needs to be
to the loop message. Okay, I'm going to stop
this and let's just modify this on edit mode here
and save the scene again. And now let's give it a try. So we can conversate here. Okay, nice, and let's
try to conversate again. We can talk again,
and we can cancel. We can talk, we can cancel, and we can talk again, and
we'll reset the dialogue. Okay. So yeah, that is
basically how we create the sen dialogue actions to interact with the
dialogue manager.
10. 09 Dialog Options: In this video, we are going to continue our dialog manager, and we are going to add the dialog options functionality with this yes and no button. So in order to do that, let's go to the dialog manager, game object here, and now we are going to expand this FSM. Okay, so first, we need to
create a couple of events. The first one would be the
yes action. No action. Okay. So the next thing that
we want to do is we want to show the questions whenever we are
completing the text here. And basically, the
thing that we need to add is the conditional
expression. And this is basically a way to easily do a conditional
expressions for a variables without having a multiple actions or a stack of actions to evaluate
that condition. So here, basically,
we want to check if the current
index is already at the end or the last index of the string array inside the
messages are a string here, and if the Boolean variable
questions is true, then we want to
show the questions. So here to evaluate a variable. If the variable name
has a space like this, then we need to put it
inside $1 sign inside this parentheses and put the variable name
here, for example. And here, as you can see,
the variable was not found, but if I type dialog text, then it found the variable here. But since most of
the variable that we are going to compare, which
is the current index, the message length
doesn't have space in it, and also the questions, then we can type the name right away. So I'm going to check if the current index is equal
to the message length. I think it's messages length. Yeah. But subtract with one because the array index
always starts from zero, so the last index is going to be always the length
substract or minus by one. And we want to check also
if the questions is true. And since the questions
is a bulion variable, we don't need to
type equal true. This will evaluate you true, and if we want to e if
the bleion is false, we can just add an exclamation
mark in front of it. Okay, so this is the conditional expression
that we want to add. And if it's true, then we want to send
a new event here. So we need to also
create show question. And here, I'm going to add that show questions transition, and we want to send it
if this value is true. So we can send the
show questions. And here we don't need to
check every frame because this will be evaluated
whenever we enter the state. So we should have all
of this value already initialized whenever
we're entering this complete text state. And whenever we show questions, we want to create a new state
and go to that state here, and we can call this
wait for answers. And basically, whenever we
are waiting for answers, we want to set the button text for the yes button and the
no button accordingly. So we can use the set text mesh P GI text and pick the
button game object, and we haven't defined that yet, so let's just create
a new variable. And this will be a
type of game object. And this will be the
questions yes button. And I'm going to set the
input to be enabled. And another one is going
to be the no button. And let's enable the input also. So now we can assign the
yes and no button here. And you expand the
button questions here, and yes buttons should
be on the yes button, and no button should be
on the no button here. And I think we can
just hide this Q and Q yes because we don't need this to be exposed in the inspector. So let's just uncheck
the input options for the Q and Q and make this inspector more
simpler and easy to read. So let's just save
this. And here, we want to modify
the yes button. And let's duplicate this action and change this to
the no button here. Okay, there was a mistake here, so let's just fix this quick. This is the yes and no button, but we need to create
another game object for the Q yes or yes button tax. And enable the input. And another one should be
a type also game object. But this is for the no button
text and enable the input. And we need to expand the yes and no button and direct
the text accordingly. So this should go to
the yes button tax, and this one should go
to the no button tax. And this is the game object
that we need to use actually. So let's just change this s, yes button tax, and this
is the no button text. And for the text, we
want to set this to the Q, This one to the QS. We already set up
the text appearance or the button text copy, and now we want to also
activate the questions panel, so we can use the
activate game object. Let's just direct this down
here, specify game object, and we want to pick
the questions panel, and we want to activate it. Here on initializing, we are always deactivating
the questions panel. So if the dialogue doesn't
have any questions at all, then the questions will
not get activated. But if we go to the state and we are to show the
questions panel, then this will get activated. And then we need to
wait for a click. So we need to add
the click sorry, not on pointer, but on UI
button on click event. And let's just
delete the pointer. Click. And here, we can
just specify game object, and then we can just change the variable
to the yes button, and this should trigger
the yes action. And we are going to
add the transition. Yes, as well. No action, and we want to add
the cancel dialogue also. And cancel dialogue should go
to the end of message here. And we can just duplicate
this click event here, and change this to the button
and send the no action. And lastly that we
want to add is this on pointer click event
to the empty area. So let's just copy this action
here and paste it here, and this should trigger
the cancel dialogue. And now we have this
yes and no transition, we need to add a new state
for each of the transition. This is going to be
the yes response. Let's just type yes response. And this is going to
be the no response. Another thing that
we need to add is we need to add a object variable. And let's just call
this sender FSM. And we are going to send the FSM the dialogue FSM or the NPC
FSM to this dialogue manager. Whenever we are interacting with an MPC that has a dialog
FSMs attached to it, we want to send that FSM also. And the object type, we need to change this to pla maker FSM. Right now it's
going to be empty, but we are going to set
up the state anyway. Basically on each
of the state here, we just want to use the
call method action, and basically, we want to send an event to the sender FSM. Let's just use the send event and just type the event name, and this is going
to be yes action. This is going to
be the yes action, and I'm going to
duplicate this or copy this call method and paste
this on then response, and this is going
to be then action. And let's just add a finished transition and go
to the end of message here. And also for the neuro response, we want to add the
finished transition and connect this to
the end of message. Okay. So now we have set up the options or the
button interactions with the dialog manager.
We can save the scene. Next, we need to modify the base dialog FSM here
that we have on our NPC. So I'm going to move
this down here. And here we are going to add
a event called s action. But let's make this global. And the no action. Also enable the
global tech here. And then we want to
create a new state, and we can just call the
state run yes actions. Here on the variable, we need
to define another variable. This time is going
to be a type of ray, and let's just call
this yes actions. For the type, I'm going
to change this two object and set the object
type to playmaker FSM. And I'm going to create
another variable called no actions. And this will be also the
same changes to object and set this to playmaker
FSM. And now we have this. Let's just expose both of the
variable to this inspector. And we want to add
another state. Or we can just set
up the yes state and then change this
by duplicating it. So let's just add a
global transition and set the yes action as the transition and add a finish local transition and connect this to
the first state. And when running the yes action, we can use the run FSM action, and we already define the
template for running an action. So let's just pick here on the category and
use the run FSM. And for the actions, we want to send the yes action. And whenever finish the event, we want to send the
finished transition. Okay. So now we have this setup. We can just duplicate this by pressing control
C and then control V and change the global
transition to the no action, and we can just rename
this to run no actions. And for the actions that we want to send
is the no actions. And let's connect this
to the first date. Okay, so now we have this setup. We need to add a
couple of variable. Basically, we need to
add a bleion variable. So let's just call
this Q as question. And this would be
a type of bleion. And let's enable the input so we can easily modify it here. And the next one that we want
to add is a type of string. This will be the Q yes tax. Sorry, yes tax. Also check the input. And the last one would be
the Q no tax or string. And let's just add this,
enable the input here. So now we can customize the response button text
via this dialog FSM here. And basically, whenever we
are sending the dialog here, we want to send this
additional information. So the first thing that we
need to do is we need to edit the SN dialog template
here. Let's go here. And as you can see,
we already defined this Qs Q and the bleion, but we haven't exposed that yet. So now we can just
easily expose it on the variable by
checking the input. So we can input this variable
from the run FSM template. Okay, save the scene here, let's go back to the
base dialogue. FSM here. Now on the run FSM, we should see additional fields or variable that we
can customize here. For the no, I'm going
to set this to the QO. For the S questions, I'm going to set this
to the QS questions. And for the yes, I'm going
to set this to the Qs. Okay. Now let's save this. Later, we are going to convert
this FSM into a template, so we can easily use this
actions on another game object. But right now we can just
keep this as a local FSM. And now let's just delete
the second text here. I'm going to set this back 21, and we can set an answer. I'm feeling great, for example. Yes, or if no, then I'm
a bit sick, for example. And we can enable
the S questions. And also, we can trigger
actions if we are responding different options by adding an FSM to this
no and yes actions. So now we have set this up. I'm going to add one actions to then and also one actions
to the yes actions here. And let's just duplicate
this base dialogue. And let's just call
this one yes response. And we can just disable the
questions and delete all of this field here and
set the actions to zero, and we want to show
different message because this is
the yes response. Let's just say
that that's great. And we can duplicate this and we can call this or rename
this to no response, and let's just type
get well soon. So we can see
different responses. And now on the base dialog, we can just drag this game
object to the FSM slot, and it will read the FSM that are attached to
this yes response, and for the no response,
we can do the same. Put it on the no actions. Let's save the scene here. Another thing that we
forgot is we need to send the sender FSM or this FSM because we already create this
sender FSM variable here. And it tries to run this event, but the sender FSM
is none or no. So yeah, let's go to
the base dialogue here. And on the variable, we need to add a object
variable with a type of FSM. So let's just call
the sender FSM. And then we can change this
to playmaker FSM and enable the input and to connect this, we can just direct the header of the playmaker FSM
to the slot here, and it will register that one. Now we have set this up. We need to also send the sender
via the send dialog here. So if we added this, we should add a new
variable type of object, and let's just call
the sender FSM. And for the type, let's change
the supply maker FSM and enable the input so we can
see it on the run FSM action. And on the state here, we
want to set FSM object, not game object,
but object here. And put this on top here. And we want to send to
the dialogue manager, same as this other set FSM
ray and string and Boulan. So let's just specify
game object and pick the dialog manager
from the global variable. And we know that the
variable name is the same, which is Sender FSM, so we can just type it
and send the sender FSM. Let's double check on
the dialog manager. The name is yeah, Sender
FSM with capital FSM. Okay. So yeah, let's go back
to the base dialogue here. We already have the sender FSM, so we can just because we
modify the send dialog, and we are exposing
the sender FSM. So now if we go to the run FSM action that are running the action
San dialog template, then we can see the sender FSM. So let's just enable
the use variable button and pick the sender FSM. Let's save the scene, and now let's give this another try. Okay, so I'm going to skip Davi. And if we press the button, it should trigger the
message. That's great. And if you talk to
this person again, you see that ops, I think it doesn't reset. Okay. We need to check
for this bug, but yeah, let's just check
the no response, and it will respond
to the second one. I'm going to check the
dialogue manager here. Okay. It still waits for click. And if we finish this, Okay. It ends the messages. Okay, yeah, I found
the issue here. Basically, whenever we are waiting for a click
here, when it finished, the finish will always go
to the end of message, and it will never evaluate our questions Bulen like we have here on
the complete text. So in order to fix this, we need to create
a new state from finish loop message because
there is a chance that we are finishing our
strings of messages on the loop state not
on the complete text. If the text finish typewriting itself and goes
to the wait for click, and it will go to
the Look message. And it will skip the state. Basically, the
state will only get executed whenever we are
skipping the typewriting effect, and it will go to the
complete text here. So in order to fix this, yeah, let's just change the finish
transition and hold click. I'm going to create a new state. And let's just check questions. And I'm going to use
the bul test here, and we want to check
the questions bulion, if it's true or false, then we want to send
different event. So here I'm going to use the show questions and
a finish transition. Show questions should go to the wait for answer state here, and finish should go
to the state here. And now here we want to send the Show questions
event if it's true, and we want to send the
finished event if it's false. And we don't need to
check every frame because this will be evaluated as soon
we enter the state, and we should have already
the value initialized. So let's save this. And now let's give another try. Okay, I'm going to try to click
this. Okay. That's great. And now, there you go. We can show the questions again, and we can response
differently this time. And Yeah. It works. It works
great, actually, and I can try to conversate repeatedly
without any issues here. And the cancel
dialogue still works. As you can see here, if we're showing the state, we can also cancel dialogue, and we can talk
to the NPC again. So, yeah, that is
basically how we can create the dialogue options and execute different actions. And with this base dialogue, it's quite powerful
actually because we can use different FSM here to trigger some other stuff
that we want to whenever we responds to a certain
questions. Yes. Okay.
11. 10 Activate Deactivate Multiple FSM: Hi, in the last video, we have created the dialog options, and now we can trigger another FSM action
using these options. And now we are going to create an activate FSM or the
activating FSM actions, so we can keep the response
that has been triggered. So for example, if we
trigger the yes response, then we want to keep
those dialogue intact. This is useful for an epic
whenever it receives an item, or if an eps at certain stage or certain phase of the game needs to have
different dialogue, then we can use this action. In order to create this action, let's create an
empty game object, and let's call
this yes activate. I'm going to put this
below the yes response, and let's create a new FSM. Basically, inside this FSM, we want to create a new state, and in this new state, we want to run the
activate the activate. FSM. And we need to add
a global transition. And let's just
choose custom event. Custom event is basically the
event that we have created, and we take or we marked
it as a global transition, and let's pick run action
because we want to run this FSM using the
Run FSM action. And now we can create a
local event called Run FSM. And here on the variables. Let's add a bleion variable. And let's just
call this Run FSM. And let's enable the input tech, so it's feasible
on the inspector. And then we want to create
another two different array. First one is the
FSMs to activate. And we want to
change the type to object and object type
to playmaker FSM. And I'm going to also
enable the input. And the second one would
be the same array, but this is going to be
the FSMs to deactivate. I'm going to change the type to playmaker FSM and
enable the input. Now we should have
those variable exposed in the inspector. Here, we want to add
a local transition, which is the run FSM, and we want to create
a new state here. And basically, in the
run FSM state here or the state that are coming
from this run FSM transition, we want to add the
run FSM action. And use the template that
we have just created, which is this one
here, run FSMs. And for the action, we want
to pass the FSMs to activate. So basically, we want to trigger the one that we
are activating it. And this is actually optional
because if we uncheck this, then we won't trigger this. So in order to
create those option, let's add a bull test here. And let's check if the run
FSMs bullion is true or not. And if it's true, then
we want to run the FSM, but if it's fall, then we want
to stay on the state here. And now the next thing
that we need to do is we need to create
another FSM to create the template to run de activate and deactivate FSM. So let's just save it in first, and here I'm going
to add a new FSM. And for this FSM, let's just rename this to action, activate multiple SM. Here inside this second FSM, we are going to convert
this into a template later. The first thing that we want
to add is the variables. I'm going to add
an object variable and I'm going to call
this current FSM, and I'm going to change its
type to play maker FSM. Then the other variable
is going to be an array, and this is going to
be the FSM activate, and we want to change the type and similar to the first
FSM that we've created, and let's enable the input here. Another one it's
for the activating. Let's just change the type. And enable the input. So now we have two
inputs variable that we can send when using
the run FSM later. And here, the first
state is going to be the sorry, the activate FSM. And here we want to use
the array get next action. So I'm going to
type ray get next. And we need to create
a local event called loop to loop the array
get next action. And for the array, we want to set or get the FSM
to the activate. And let's just set the loop
event to loop transition, and we want to add
that transition. And let's create
a new state here, and let's just call
this disabled FSM. And here, whenever
we are looping, we want to save the result into the current FSM variable
that we have created. So now on the disabled FSM, let's add a finished transition, and then connect the
finished transition back to the activate FSM. Here, we want to use
the set property. I think we have
set property here. Yeah. And now for
the target object, we want to pick the
current FSM and we can pick the
enable property here, and we want to uncheck this. And basically, this will
uncheck this checkbox, the property enable if the
actions gets executed. So if we set this value, and it will enable
the component, but if we disable this, then it will disable
the component. Let's just re enable this. Now we need to add a finished transition and
then go to a new state here. And basically, to make
it things easier, we can just copy these
actions and put it here, and here we want
to activate FSM. So let's just change
this to FSM to activate, and then we want to add
the loop transition. And here we need to set the
finished event to finish. So once it's finished
loop the array, we go to the next state here, and we want to add also
the finished state here. And let's create a new state. And this one is going to be the opposite
of the first one, which is the activate
or enable to make it more synchronized with its naming with
the first one here. And let's add a finish
transition here. And we want to connect the finish transition
to the activate FSM. And here, we can duplicate
the set property here. Paste it here, and
this time we want to check this because we
want to enable the FSM. So now basically, this we
look through the FSMs to activate and put each of the member into this
current FSM variable. And while we are looping, we are going to enable
each of the current FSMs. And now we need to add a finished transition because the finished event as for it. So let's just create
a new state here, and let's just call this finish. And I'm going to add the
finished FSM action. Okay. Now, so we have
created this template. Let's just save
this as a template. And I'm going to
call this actions activate multiple
sorry, multiple FSMs. I don't think we need to
use the save template, so let's just press no, and let's just delete this FSM. And now on this s activate, I'm going to call
this s activate. L et's add a run FSM action, and we want to put this
on top of the bul test, and let's pick the action
activate multiple FSM. For both of these array, we want to use variable, so we can just use the
activate and deactivate array, and this will send any FSMs
that we have set up here. And whenever it's finished, we want to keep this MT, but we want to send
the run FSMs if the run FSM value or the
Bulen variable value is true. So let's just save this. And now we can actually duplicate this, and let's just call
this no activate. And basically, we
want to change of the FS active status using
this activate action. So for the yes activate, let's say we want to Activate the yes response, and then we want to disable then response and
the base dialog. So this should disable
the other two, and we want to run the FSM because whenever
this gets triggered, we want to trigger
the yes response. And for the activate,
we want to do the same, one on the FSM to activate
and two on the activate. And for the activate, we want to put the S response
and the base dialogue. And for the activate, we want to add the nu response, and also run the FSM. Let's save this on
the base dialogue for the yes actions
and the no actions, we want to change this to
the yes activate instead. So for the yes actions, we want to run the yes activate, and for the no response, we want to run the sorry, not no response, but
the no activate. And basically, since we
already had this run FSM, whenever this gets triggered, the no activate will also
trigger then response. So it will also show the same order of dialogue
as we have before, but it will change the
active status of our FSM. And on start, we want to
disable the yes response, and we want to also
disable then response. Let's save this, and now
let's give it a try. So here, I'm going to
talk to this person here. And if we pick one
of the options, it should trigger the
response. That's great. And if we try to talk talk to this person again,
Okay. Let's check. There seems to be an issue here. So on our Okay, y. Sorry, my mistake. I forgot to add the
other actions here. So basically, to make this work, we need to increase the size
of our interactable actions, and we want to add the
remaining response also here. And basically, by default, or when we are
starting the scene, the yes and no response won't be triggered
because by default, it was disabled the FSM,
as you can see here. But when the yes activate or
the no activate kicks in, then the active
status will change, and the other two
will be disabled, and the one that are intended
is going to be activated. Let's just rename this,
so it's not confusing. It should be no activates the same with the game
object name here. Save the scene again. And
now let's give it a try. Okay. So let's just
talk to this person. And we can cancel this. And if this is canceled, then the order or the active status of the FSMs are not
going to be changed. So if we talk to the NPC again, it will show the same message. But if I responds, then it will show this message. And if I talk to him
again, as you can see, we have the yes response because the FSMs gets
disabled the other FSM. For example, this
base dialogue and no, and if we restart the game and let's try
to pick the no option, we should have a
similar response. So if I talk, it will have
the similar response. Later, we are going to
create also a save system, and we want to also
save this state. We for example, if we
gave an item to an NPC, then we want to have
different response kind of bake or set permanently
to that NPC. So the next time we
talk to that NPC, it will show the dialogue
that should be shown whenever that NPC has received
an item, for example. And we want to save those state. Yeah, this is basically how we create activate
multiple FSMs. Another thing that
I want to do is probably I want to make
this as a template. For example, we can
just save this as a template. Let's
just rename this. And now we want to
save this template, and this should be a template, not an action because
we want to add this template to an FSM
instead of running it. So I'm going to
call this template, and let's just call this
activate multiple FSMs. And if you want, you can
use the safe template here. And now once we use
the template here, as you can see, we can see it, but we have these options here. So we can change the options for the FSM to activate and activate on the
inspector here. And for the no activate, we can just try to
reset this FSM, so it's resets everything, and let's just use the template
activate multiple FSM. Here, by default, it already picks this FSM, so
let's just fix that. Here on the variable. I think, yeah, let's
just clear this, set this 29 and set the size 20, and set this size also 20. And for the run FSM
let's just uncheck this, we want to save this
value by default. Now let's try to reset this and add template. There you go. Now once we have reset the FSM. We don't have those
options anymore. Now we can add this
on the inspector. And now let's just set
up reset up this again, and we want to sorry, we want to disable
the yes response, and we want to enable
the no response instead. And let's save the scene,
and I'm going to check our yes response or
yes activate here. Okay, we still have it because when we change the template, we reset the template,
it doesn't change this. So yeah, it works fine. And this makes it easier when we later want to create
another activate, for example, and we
can just add an FSM, and we can just
pick the template. And then we can just set up the FSMs to activate
and deactivate here without worrying how to set up the FSMs
all over again. So let's just delete this and I'm going to save the scene. And now let's give it one more try because we have
changed this to a template. Okay. As you can see, it
still works just like before, so everything is
good, I think. Yeah. In the next video, we are going to continue develop this game.
12. 11 Item Definition and Inventory: In this lesson, we are going to implement the inventory
and item system. So first, in order to do that, we need to create a
custom scriptable object, and this is to make easier
to create item definition, and we can hold a couple of letter that we can use
later in playmaker. And to create this
scriptable object, we need to create a
very simple script. So let's create a new folder, and let's just call this script. And inside this folder, let's create a new
sheet sharp script. And I'm going to call
this item class. Let's open the script. And this is going to
be a very easy script. So don't worry. Don't be afraid. I'm going to guide you
every step of the way. First, let's just delete all of this built in method from unity, and we want to change the base class type from mono behavior to
scriptable objects. If you type script, it show this intelligence, and we can use this by pressing enter and it
will autocomplete. I need to delete this backslash. And then the next
thing that we want to do is we want to create
a couple of variable, and it's going to be
a type of public. When we set this to public, this makes it easier to
dit on the inspector, and we can also
retrieve the value from playmaker later using get
property or set property. So the first variable type
is going to be a string, and let's just call this good, and this is going to be the unique identifier
for each item, so we can compare if a certain item is similar to the other item
that we can use this value. It's just for creating
a unique identifier. And then we want to create
the second variable, also a type of string, and let's just call this name. But since scriptable object
already has a name property, this hides inherited members. So we need to add a new keyword before the
string keyword here, type public new string name and then semicolon at the end. And then we can
add a new string, and this is going to
be the description, and we can also create
a sprite object here, and this is going
to be the image. And then upon instantiating the script object or creating
the item definition. We want to generate the
guid if this grid is empty. So in order to do that, we can use the validate method, and this will get
trigger every time we change a certain value on the inspector,
this will be called. So in order to make sure that we only fill the grid one time, we need to check if the guid
using the string data type, and then we can check
isnull or empty, and then we can test the
g or the grid variable. And here, if it's empty, then we want to fill it. We want to generate
it automatically using the system namespace, and it has the GID
class or struck, and we can use the new GID method and this will automatically generate a ID. But then we need to
convert this two string. And then we can end it with
semicolon and press save. And the other thing
that we want to do is, we want to put this item
class inside a name space. So it's nice and organized. So let's just put this on the point and
click, for example. Game. And let's just cut all of this code here and paste it
inside this name space. And this will make it
easier to search it on the custom variable
definitions on playmaker when we are generating a reference to this data type. So the next thing that we
want to do is we want to add a create asset
menu attribute. And basically, this will create a new asset menu that we can use whenever we want to create a new item class object
or scriptable object. So first, we need to pass the
file name that we want to use with equal sign or
a sign operator here. We want to set the
name of the file name, so I'm going to call this
item definition or item de. And the second one
will be the menu name, and for the menu name, I'm going to pick item
definition. Like so. Okay. Now we can
save this script, and we can just close the fisL studio because we are not going
to use it anymore. Now when we are back in UT, after it finished compiles, we should be able to
create item definition. In order to do that,
I'm going to create a new folder in the assets, and I'm going to call this
data inside this data, I'm going to create a subfolder and let's just call the items. And inside this items folder, we can create a new
item definition now. As you can see,
we have this menu because we have set up the menu inside the greet menu attributes in our
scriptable object. So let's just press this menu, and it will automatically
create a new object. And we can change this
two lighter, for example. And now, whenever we
try to enter the name, for example, let's add a name. It will automatically generate the grid as you can see here. So I'm going to type
this name lighter, and I'm going to
add a description, for example, a how fiel lighter. And for the image, we can pick the
lighter image that we have prepared when we
are setting this project. So I'm going to
use that. And then I'm going to create a
new item definitions, and let's just set this two key. Rename that two key, and for the name of the
object is going to be key. And it also generates
this grid unique grid, as you can see, it's different
from the lighter one. And we can set the description a key to
the bathroom, for example. And for the image, we can pix these items underscore three. And now we should
have this item. And the next thing
that we want to create is we want to create a
variable type definition. So here in the data folder, let's just right click,
go to the create menu, and under the
playmaker menu here, we should be able to see this new custom variable
type definition. So here, once this is created, we can create a variable
type definition. So I'm going to create
a new variable type, and we can just call this item. And for the type, we
can type the namespace. Which is, let's just take
a look one more time. To make sure it's
point and click game, and we need the class name. So let's just copy this
keyword, the namespace, and remember the class name and back in unity
on the data folder. We can paste the name space
and then the class name, which is item class. And this will create a
variable types that we can pick on the playmaker
editor or variable panel. For example, if we select like this NPC here and
go to the variable, you see that we will
have this item, and then we can
create a variable and this variable can select the item definitions
that we have created. Another thing that we want
to do in this lesson, we want to prepare
the inventory array. So in order to do that, let's just create a
new global variables, so open the global
variable window here, and let's create a new array, and let's just call
this inventory. For the type, we
can pick the item. And let's just press yes, and this we'll create an array
with a type of item class. Now we can set the
size here and we can add a item to our inventory, and in the next video, we are going to create
actions to give item and to receive items
from NPC when interacting.
13. 12 Give Item Template: In this video, we are going to continue working on the
item and inventory. And this time, we are going to create an NPC where this NPC, it's going to give an
item to the player. So in order to do that, let's just duplicate this NPC
dialogue here that we have. I've renamed this
NPC to NPC dialogue, so we know what this
NPC does actually, and to duplicate this, let's just press control
D or command D on MAC. And now we have a
duplicate NPC here. I'm going to reorganize
the hierarchy, Let's rename this NPC to
give item, for example. And let's reposition this NPC so we can interact on different
NPC in our scene here, and I'm going to rotate the NPC slightly
here on the y axis. So it kind of facing
this direction. And here, let's just delete
all of the child object. And we want to reset the action, so I'm going to set this
back to one for now, and we need to create the dialogue template because right now the dialogue
that we have created, it's still not a template. It's an FSM, so
let's just create it so we can reuse this
easily on other NBC. I'm going to duplicate
this base dialogue just to create this template here because I'm going to
reset all of this variable. So let's just set
this message 20, the no actions 20 in size, also with yes
actions, set the 20, disable the ask questions, the no string variable and
the s string variable, and let's just set
the sender FSM 29. Okay. Now we have save
this player, FSM, let's go to the
playmaker window here, and here on the FSM. We can right click here and
then press save template. And let's just call this
template Underscore dialogue. FSM, and save this. It doesn't matter to use this or not because we are going
to delete this now. Now we have the
dialogue template. Let's go back to
the gift item here. And now let's create
a child object, and this is going to
be the yes response. And let's duplicate this and
let's call this no response. And for the yes response, let's create a new FSM, and this is going to
be the gif item FSM. And this is going to be
quite straightforward. First, let's define the
variable that we need. We need to create an array, and this is going
to be the call. And this is going to be
called chain actions, where it's going to be an
array of FSM that we can assign so this gift item can run a series of
actions if we wanted. And for the array type, let's change this two object, and the object type, I'm going to pick playmaker FSM. And let's enable
the input checkbox, so it's available
on the Inspector. And the next one that we need to create is the item to give. And for the type, let's
set this two item, and we also want to enable the input checkbox so we
can change the object here. And here on the FSM, we want to create a new state, and let's just rename
this give item. And add a global
transition custom event. Let's pick Run action. And I'm going to add a
finished transition. And with this finish, I'm going to create a
new state here, and let's just call this Run actions and add a
finished transition also, and we want to connect finish
back to the first state. So here on this state
here on the gift item. Let's add a array add action. And basically, we just
want to give the in the item that we have
set up here so we can access the global
variable inventory here, and for the value, we want to pass the variable
item to give. And this will be all for
this give item state. And here on the
run action state, we want to use the
run FSM action. And basically, we want to run the custom action that we
have created from a template. Here, let's just pick
the action run FSM. For the actions, let's just
pick the chain actions. On finish event, we
want to set to finish, and this should be all
for the give item FSM. Now we want to save this as a template.
Let's just do that. For this one, I'm going to call this template underscore,
give item FSM. And we can use this here.
Now we have the setup. Let's set up the dialogue here, I'm going to add another FSM, and I'm going to pick
the template dialog FSM here and this will get triggered
by the interactable FSM. Let's just drag this
into this action slot. So whenever the player
click on this NPC, it will go to this NPC and it will trigger the second FSM. Here on the FSM, we can
say the message or set the message like do
you want this key, for example, because
for example, if we open the global
variable window, we see that our inventory, we already have lighter. I want to make it this
NPC is giving us the key, and we want to add an actions
and also the S actions. For the s actions, let's just direct
this yes response. For the actions, we want to add the FSM first to this no
response game object, and let's just pick
a dial of FSM. And direct this no response
to that no action slot here, and enable the ask questions. And let's just set then to N, for example. Yes, to sure. And for the sender action, we want to drag this own FSM
itself to the slot here. And the same goes
to other dialogue. So for example, in the response, we want to drag the FSM
itself to the sender FSM. And here, the other thing
that we want to set is, I think this will be all
for the dial of FSM here. But here on the yes response, we want to add a
dial up template also to say something when the NPC is giving
the item to the player. So here we can expand
the chain action and we can add the
playmaker FSM here. And for example, here, we
can just say that use it wisely. There is a tipo here. Let's just fix that and
drag the FSM to the sender. I don't think we need to
set the others because this is going to be a
message, not a dialogue. And for the item to give, I'm going to pick the
key that we've created on the other video when
we are defining the item. Let's save the scene here, and I think it's all set
up on the side here. And for this, yeah, we already set up this here
and also the no action. Here, we need to like,
input a message. For example, when
we refuse the NPC, when he wants to give an
item. Let's just say that. Suit yourself, for example. Okay, so I think
we are all set up. Let's just save the scene here, and now let's give it a try. Okay. Here, let's take a closer look to the
global window here, global variable windows, and let's try to talk
to this NPC here. And let's try NFs, and it says, suit yourself. And if we talk to
this NPC again, if we pick this S answer, it will say a different thing, which is use it wisely, and it works our dialogue. And as you can see
here, in our inventory, we have the key item received. And the good thing with
this is when we stop this, it will reset the array, so changes during run
time won't be safe. And this is actually
good because we don't have to reset
the variable manually. Okay, yeah, that is
basically how we create the gift item
template, and later, we are going to create the opposite template where
we are giving an item to a NPC and we will have different response depending
if we have the item or not.
14. 13 Take Item Template: In this video, we are going to continue the item
action, and this time, we are going to create
the take item template for an NPC to take an
item from our inventory. So I'm going to duplicate
this NPC gift item. And for now, let's just disable the NPC
give item original. And we want to rea the
duplicated one to NPC take item. And here, let's expand
the yes response. And this is basically
a give item template. So let's just set this non here, and this will reset our FSM. And here for this FSM, let's just change this to
take item for the FSM name. And here inside
the take item FSM, we want to create another state. And this state is going to check if we have
the item or not. So let's just call
this check item. And we want to add a global transition
custom event run action. So we can run this using
the interactable or any other run action
FSM custom action. And then we want to
create a local event called Success and fail. And we need this
option because when an NPC is going to take
an item from the player, we want to have a
two output depends on the availability of that
item inside our inventory. If we don't have
it, then we should trigger the failed event. And if we have it, then we should trigger
the success event. So let's add those
transition success and fail to this
tech item state. And basically, inside
the check item state, we want to use the
array contains. And here we can go and pick
our global inventory array. And for the item that
we want to check, we want to create a
variable for that. So let's just create
a new item variable, and let's just call
this item to take, and we want to expose
this as an input. Back to our state tab here, we want to use variable
for the value, and now we can use
the item to take. And we can trigger the event. So if it's contained or
if we does have the item, then we want you to
trigger the success event. And if we don't have it, then we want to trigger
the failed event. Now let's just create two new
state from this transition. And here we can just call it
gift for the success event. And for the failed event, let's just call don't have And basically
on this gift state. We want to remove the
item from our inventory. So we can use the
array to remove. And then we need to pick
the global inventory and here for the value, we can just pick
the item to take, and this will return the
item from the array. And after we remove this, we want to run an FSM actions. So we need to create
two new array. And this is called Success
action. There is a typo. And for the type, I'm going
to change this to object and playmaker FSM and
enable the input. And then I want to also
create another array, and this is for failed actions. And for the failed actions
is going to be the same. We should pick playmaker FSM
and enable the input also. And now, as you can
see, the inspector, it doesn't really
organize right now, so we can organize it
by adding category. Here, we can add
actions category for the success actions and set the failed actions
to that category. And now we see our inspector variable in an organized group. And for the item, we can just
leave the category empty, so it sits on a separate
sections of our inspector here. This make it easier to read the inspector or the variable that this FSM template have. Next, we want to run each of these actions depending
on the state. Here on the give state. Here I made a mistake. The array removed should
be on the gif state, so I'm going just to cut this action and paste it
inside the gift state. And then we want to
add the run FSM. And we can just pick the action and use
the action run FSM. And for the action, we can just add the success
actions here, and we want to trigger finish. So we need to add a
finished transition, and now we can pick the
finished transition. And whenever we
finish the action, we want to go back
to the first state. So let's just copy this action
here and paste this here. And inside Don't have state, we only want to run
the failed action, and we want to trigger
the finished transition. Go back to the first state. So here we want to
remove the item because we have successfully give
our item to the NPC. And here, since we
don't have any item, then we don't need
to remove anything. We only need to run
the failed action. And now the take item
template it's done. We can save this as a template. So I'm going to rename this
to template, take item FSM. And we can use this now here. And just to test this, let's pick the same item that
we have on our inventory. So let's just pick the lighter. And for the failed action, we need to create a new empty game object
to hold the action. And let's just create
a new empty here, and let's just call this
down or doesn't have. And here, let's add
a playmaker FSM, and we can pick the dialogue
template dialogue FSM here. Let's add the message and direct the playmaker
FSM as the sender. And for the message,
let's just say, you don't have a here
on the yes response, we can just drag the doesn't
have as the failed action. And for the success action, we can just drag
this message here. Let's just say thanks, man. For example, and drag
this to the slot here. So now we have set
up the take item FSM here on the main
NPC game object. We need to change a couple of
strings on the dialog FSM. The first dialog FSM here. Let's just say that do
you have a lighter? Can I have it? And here, I think this
is already set up. Just to make sure,
let's just direct this one more time
to the slot here. And for the yes action, it should trigger
this that one here. Yeah, it's correct.
So let's just direct this one more
time, just to make sure. And for the response, I think this is also correct. Yeah. And let's select
the no response. Let's just say something else. Let's just say that that's
a shame, for example. Okay. So now I'm going to
save the scene here. And let's check the game object already using the template. Yes. We need to change all
of this FSM into a template, to make it easier to
design the gameplay, and later if we need to
modify one of the FSM, we can only modify the template, and it will get applied across the game object that are using
those template as an FSM. Make it easier to edit
things and to fix things. Okay, so now let's
give it a try here, and let's try to interact. And we don't need to worry with the NPC give item because
we have disabled it. Here in the globals.
Highlight the inventory. We can check our item. Let's just interact
with this person here. And if I say Na, then it will trigger
this dialogue, and we keep the item. But if we give this
item to this NPC here, and as you can see, the lighter gets removed
from our inventory, and it will respond a
different dialogue here. In this case, it
says, T thanks, man. And with this take
item template, we can trigger
some other things, for example, like opening
a door or something else. So if we give an item, then we have access
to new areas, for example, we can just do that using the success actions. Yeah, if we stop this
and we should have the lighter return because changes on runtime
doesn't get safe. With that, we can conclude
our take item lessons. Next, we will need to
create a UI for the item, but I think we are going
to cover that a bit later.
15. 14 Tidying FSM: In this lessons, we are
going to clean up some of the FSM here because I just noticed that like
our interactable, we are still using a base FSM. It's not a template here, and other NPC have this interactable because we copied the NPC from
the first one. So we need to make
sure that it's using FSM template to make it easier to fix things
when we need it later. So I'm going just to duplicate
the take item NPC here. And open the pla
Maker window here, under the interactable FSM. Let's go here and let's set
the actions 20 in size. And for stopping distance, we can set this to
default 1.5. It's okay. And here, since we already
reset the variable, and this is the default value of the variables that
we want it to be. We can just right click and
then press save template. And let's call this
template interactable. And it doesn't
really matter if we use save or not because we are
going to delete this here. And now let's apply
this to our other NPC. So here we can just pick
the template interactable, but we are going to
lose the settings here. So let's just remember this. Basically, we want to
access the base dialogue, yes, response and no response. So let's just pick
the interactable. Now set this back to three, and let's expand this and we want to get the base dialogue, and then the yes response
and the no response. Because this two other
FSM or game object, yes, activate and no activate is
going to be triggered by this base dial up game
object here, as you can see. So we don't need to
worry about that. And I think this is good here. Let's just select the other
NPC here, like this one here. And since this only
have one FSM reference, this is quite easy to fix, and this is basically
this game object sorry, this FSM here. So let's just pick the
temperate intractable again. Set this b21 and drag this one here.
And this should work. And then on this one here, we can just pick the
intractable template. Set this 21, and then we
can just direct this here. And let's just give it a try
to see if everything working correctly or not with
this template here. Okay. If I press sure,
it takes our item. Yeah. So now if we try to give it again,
it will response. You don't have it because
yeah, we don't have it. So it's working very
well, actually. And we can also interact
with this person here. If we say I'm a bit
sick, get well soon, and it will keep those
interactions because we have this activate multiple FSM
in the base dialogue here. So, yeah, that's for
setting up the template, and then we are
going to continue working on the game in
the next video. Oh.
16. 15 NPC Move Action: In this video, we are going
to create an NPC move action. This action is going to move the NPC using the
NMS agent component. And with this action,
we can make it so the NPC can move to
a certain position, and this would come handy in our point and click
game development. Now let's just duplicate
one of the NPC here, and let's rename this
one to NPC move, and let's reposition this NPC to a certain position,
for example, in this area here, I'm
going to rotate it, so it's facing this direction. And now we want to
delete this second FSM. And I think we can safely delete the child object for now. With this NPC move here, let's add a new FSM. Let's open the
playmaker editor here, and I'm going to
right click here. Oops, and I'm going to create
a new FSM. Where is it? Let's just select the
game object again, and here under the FSM name, we can add a new FSM. And let's call this FSM move. So there are a couple of variables that we
need to create. Let's create the variable
needed for this action. First, let's create a
game object variable, and let's call this vector, and this is going to be
the child object that have the animator
components attached to it. And we need also a vector t, and this would be
the target position. And we need another
game object variable, and this will be the
target game object. Let's just type this target. And we need to also
create a string variable. And this would be the
animator speed reference. Then we want to create
an array variable. And let's just call
this chained actions. For the type, as usual, set this two object, and then we need to pick the play maker FSM. We want to expose a
couple of the variable. First, we want to
expose the actor, so let's just enable the input. The imeter speed reference,
we want to expose this. And then we also want to expose the target variable
and the chain actions. And we want to keep
the target positions private or hidden in the FSM. So for the animator
speed reference, let's set the value
by default two speed, but later we can change this
in the inspector here. Okay. So now on start, we won't do anything, but we need to create
another state, and let's call this move. And then we want to add
a global transition to the state here and
pick custom event, and we can pick run action. And we need to add a
finished transition. So for the move, we want to set the agent destination
to the target position. But as you know here, the variable target
position is not exposed, so we need to set
this value here. On start, we want to get the position from the
target game object. So let's just pick the target
game object by specifying game object and then pick the variable here
and pick target. And for the factor, we want to save this to target position. This will get the position of
the target game object and it will save this position as a vector, then
we can use that. And here, basically, we
want to go to the next tape when The agent destinations
path pending is done. So when the path of the
movement is generated, then we want to trigger finish, then it will go to
the next state. And then on the second state, we want to remain this
to wait until arrive. For the wait until arrive state, we want to add the get agent, sorry, agent remaining distance. And here we want to
trigger the arrived event. So if it's arrived, then we
want to trigger the finish, and we need to enable
the every frame. Now we want to add the
finished transition. Then we want to go
to the next state, and when it's finished, then we want to run
the chain action. So let's just rename this. And here we want to add
the run FSM action, and we want to pick
the action run FSM, and we need to pass the
chain actions here. So this will trigger
the chain action. And now we need to create
another anti game object. It can be the child
of the NPC move. So let's just create
the target position, and let's set this position
to here and the direction, for example, to this
direction here. And now let's just
rename this two target, and I'm going to enable
the icon for it, so we can see it on
the scene view here. And now on the NPC move, I'm going to drag this second FSM to this action slot on
the interactable FSM. And then for the target, I'm going to pick this target
game object as the target. Now if the player
interacts with this NPC, it so trigger this move action. So let's give it a
try. Okay. There is one error because we don't have mesh agent attached to
the NPC move game object. So let's just add that. So I'm going to add an agent here. And now I'm going to put
this agent on top here. By dragging it and
save the scene again, and now we should clear out the error message that
we were having before. So let's just save the scene again and now let's
give it a try. If we click on this NPC here, it should move the NPC, as you can see, it moves and it triggers
the chain actions. We have a working move
actions right now, and next, we are going to add
a character model, and we want to also
sing the animations. When the character is moving, we want to play the
walk animations, and if it stop, we want to
play the idle animation. And then later we want to
turn this into a template.
17. 16 Add Model and Animation to NPC: Now let's continue
our NPC move action, and now we want
to add the model, so the model we'll
play the animation accordingly when moving
and when standing still. So first, let's prepare
a couple of things. I'm going to create a
new animations folder. So let's go to create folder
and then type animations. And here inside the animations, let's create a new
animator controller. Let's call this people. And now let's open the
animator controller. Let's create a new blend tree, and for this bland tree, let's call this idle dash walk. Here inside this blend tree, by default, it will
have a parameter blend. So this will create a float parameter
blend on the animator, but let's rename this
parameter chose speed, and we are going to
use this value to drive the motions
that are playing. So if it's zero, then it should
play the idle animation, and if it's one or if
it's greater than zero, then we want to play
the walking animation. So here on the side here, when the blender is selected, we can see its inspector. Under the motion section, we can add a motion field. So let's press this
and press this twice. And the first one, we want
to use the male idle A. This is the first
animations for idling, and for the walking, we want to use the male walk, but the first one,
not the second one, because the second one
is with root motions, and we don't want to use
the root motions actually. So let's just pick
the first one, and we should have
these animations when we are importing the two, tiny people a set pack. So now we have this set up. This should trigger our
animations correctly. So now if we play
these animations, you see it's idling, but if I direct the speed, it will change to walk. And vice versa. So we
can use this value to dictate the animations
of the character. So now we are done with
the animator setup. Let's go to the scene here. Go to the two tiny
people folder. Under the TT demo folder. We should have a lot of prefs. And let's pick the
police character, and let's wreck this police
to the child of the NPC move. And we need to
reset it transform. Let's just reset this,
right click and then reset. And for the y position, we want to move this
by negative one. So it's aligned with our
capsule game object. And here on the
parent game object, we can just remove
the mash render and also the mash
filter component here. Let's remove this. Now we should have
this. And here, under the NPC move, we want to set the actor to the child object that has the model and the
animations in it. So let's just sect
the TT model police. And under this TT
demo police model, we want to pick
the P Controller. So let's just pick the
people Controller. Okay. Let's save the scene here. And here on the NPC move, we should have set the animator speed reference
to speed by default, because we did the same on
our animator controller. But if for some reason, the game object has a different
reference float variable, then we need to
change the name so it matches the one that has
been set up in the animator. So once we have
set up the actor, we need to modify the FSM. So let's go to the
playmaker window here, and under the Move FSM, we want to add a
couple of things. So here, When the NPC is
waiting until it's arrived, it means that it's moving. We want to set the animator or the speed float
animator to one. So let's just use the set
animator float action. And for the game object, we want to specify game object, and then we want to pick
the actor variable. And for the parameter name, let's use variable and then pick the animator
speed reference, and we can safely
set this value to one because we know
that in this state, the NPC it's moving, and then let's copy this
set animator float action, and whenever we arrive, we are going to the next state. So here in the next state, we can just move this to the top and then set
the value to zero. So let's just save this. And now let's press play. And let's give it a try. So now it's playing
the idle animations, as you can see, and if
we go to this NPC here, it will move to that position. Yeah. So that is how we
set up the character and the animations to synchronize
with the move actions. Now let's turn this
actions into a template. So in order to do that, I'm going to duplicate
the game object here. And for the second game object, I'm going to set
the actor to none. And for the target,
we want to also set this to non because it's a scene reference K. And now that
we have set this up, let's go to the
move FSM, and here, let's just save
this as a template, and this is going
to be a template, not an action, so let's
just type a template. Let's just call this move NPC. And save this. We
don't need to use this in this object because we
are going to delete this. But here on the NPC move, we want to use the template. Let's just pick
the template here, and it will get reset, and now we can set the actor to this TT Do police game object
and for the target, we can just pick this
target game object. Let's save this. Now if
we give this another try, it should also work. Okay. It's working fine. So yeah, now we have the move actions and the NPC animations also
synchronize with these actions.
18. 17 Replace Player Model and Add Animation: Next, let's replace
the player model with the player character. Now in order to do
that, let's go to the project folder and inside
the two T people folder, we have this T T demo folder, and inside this folder,
we have prefe folder. And for the player, we are
going to use the Do male A. S, not demo male A. It's going to be D
M B pre let's just drag this pref and make
it the of the player. And let's just reset
its transform. And here, let's set the y
position two negative one. So it's align with the
capsule game object. And now we can go to
the player game object. We can remove the mash filter, and we can also remove
the mash render. Now we have this set up.
And for the child object, we want to add the
controller that we have just created in
the previous lessons. We can use the P
Controller because the controller actually can be shared between
NPC and player. And now let's select
the player game object, and let's open the
playmaker Editor window. And here in the
click to move FSM, we want to add a
couple of actions. Basically, on the
way to arrive state, here, we want to get the
fellocity of the agent. So let's just type get felocpy, and we should be able to filter out the get
agent felocity here. And here we put it on top. And then we can
check every frame, and we can save the
velocity magnitude or the square magnitude. I'm going to pick
square magnitude because this is more
performance because there are no root square
calculation with this value. But for magnitude, there will be root square calculation since we are running this
actions every frame, I believe that velocity square magnitude
should be better. So let's just create
a new variable, and let's just call
this player velocity. Now we have this. Let's
minimize the other two action. And then we want to use the
set eimator float action. And for the action, we want to put this below
the get agent velocity, and let's create a
couple of variable. So first, I'm going to create
a new game object variable, and let's just call this tor, and let's expose this. And then I want to also create a string variable called the
animator speed reference, and expose this variable also. And I'm going to set this value to be string called
speed by default. But since we expose
this variable, we can easily change
this on the inspector. Now let's go back
to the state tab, and for the game object, let's specify a
game object here, and then let's pick
the actor game object. And for the parameter, we want to set this to the
animator speed reference. And then for the
value of the float, we want to pick the
player velocity here. Let's check every frame, and we can lift this on update. And now let's save this, and let's give it a try. Okay, there seems to
be an issue here. Yeah, I forgot you
set the actor. So let's just drag the child game object
into the actor slot here. Let's save this again, and now
let's give it another try. As you can see, it
walks and it stops. And the rotations is a bit slow, so we can increase the value
to make it more perfect. Here on the player game object, on the NF mass agent component, we can increase the
angular speed value. I'm going to make this 2720 and save this and this
make the rotations si. And I believe this works better. Okay. Now we have replaced
the player character. Let's continue to develop
our game in next lesson.
19. 18 Inventory UI Panel Setup: In this video, we are going to create the UI for
showing our inventory. Let's go to the view in the scene view here and
let's focus on the Canvas, and let's expand the Canvas
on our sample scene here. I'm going to create a new
empty child game object here, and I'm going to make sure that this child game object
stretch to the screen here, and let's rename this inventory. And we want to create
a child object, which is an image, and this
is going to be our panel. We're going to
rename this panel. And we can make the
transform to also stretch, but we want to add a
margin on the left side by 400 and right side also 400 and top by 200
and bottom by 300. Now we have this panel here, and let's change the color to the black transparent that
I've saved before here, which is 40% or 40 in
the Alpha value here, and the color is black, and we want to add
the background. So this is going to
be also an image, and let's stretch
this background here. Pick the same color, and now we can delete the image
on the panel game object. So let's just delete
the image component, and let's rename
this two background. And for the
background, let's add a margin on the top by 100, and we want to put a title here. So let's just create a new
UI and Pi tax Mash pro. And let's put this on
top, this one here, by pressing all and shift, you can select this, and it will adjust
automatically here, and let's expand this. And now let's rename
the text to inventory. And we can increase
the font size, that's set this 260 or even 70, and then we can set the
alignment center and middle. Now we want to add a scroll view on the
background game object. Let's just select the
background game object, go to the UI menu, and let's pick the scroll view, and this is going to
be the items holder, and we want to also expand
this stretch to our panel. But we want to add a margin on the left
side by 25 pixels, right also 25 pixels, and the bottom 225 pixels also. And here we can just disable the image component
on the scroll view, so we don't have this white background color, tinted white. And let's change
the movement type to clamped and make sure that the movement type will clam depending on the
content size window. So we can only scroll to the bottom part of
the window size. We cannot scroll much further. And here on the child
of the scroll view, we have this viewport
and we have the content. So for the content, we want
to add a grid layout group, and this will make sure that the child objects will be
arranged in a grid manner, and let's create the item entry. And for now, let's create it as a child of the content,
so we can see it. So go to the UI menu
and pick the image. I'm going to duplicate this
image so we can see it nicely aligned and
select the content. Now we can adjust the
spacing and stuff. First, we can add the padding. Let's add ten to each of the
padding here, ten pixels. And for the spacing, let's make this
around 20 pixels. W spacing, we will have
space between item entry, and let's rename the
first one to item I. And for the content game object, we want to also add a content size fitter component and make sure the vertical fit
it sets to preferred size. So by using this
content size fitter, it will change the height of this content game object
depending on the child member. So if we have a
lot of inventory, then the height will expand to accommodate the child game
object or the item UI entry. And this will make the size of the height content change dynamically based on
the child game object, and this will also
trigger the scroll bar to react and adjust its scroller
so we can scroll the view. Let's save this here.
The other thing that we want to prepare is we want
to create the info panel. This info panel will show
whenever we hover to the item, and it will show the item
name and item description. So let's just create a panel or an image as a
child of the inventory. And this is going to
be the info panel. So let's rename the game object. And for the info panel. Let's change its size its width
to 400 and height to 200. And we want to also change the anchor to
the top left here. So we can use the mouse position to reposition this info panel. And I'm going to
change the pivot the x pivot to negative 0.1. So it's slightly offsetted from our left side of the panel, and for the y pivot, I'm going to make this 1.1, so it's slightly offsetted
also on the y axis. So we will have a slightly
distanced pivot to our panel, and this will align nicely whenever we
trigger its position, then we will have space between the mouse position
and the info panel. And for the info panel, let's change the color to
this black transparent. And we want to also add
a child tax object. So I'm going to add a tax here. And let's stretch this to
the size of the info panel. But let's add a padding on each of the side of this panel here. And for the font size, let's set auto size, but not by much. So let's just set
the minimum to like 22 and the maximum to 38. So the font sizing will adjust automatically depending on
how many character we have, so it fits this window. Let's save the scene here. And yeah, we have set up
the inventory Panel UI. And next, we are going to
create functionality for this.
20. 19 Inventory Panel UI Functionality: Hi, in this video,
we are going to continue our
inventory UI system, and right now we
are going to create the functionality for
this inventory UI. So let's get started.
Okay. First, we want to expand the
Canvas game object here, and under the
inventory game object, we want to create a new FSM. Let's just create one FSM here, and let's just call
this inventory. Okay. So now that we have
created the FSM here, let's create Git
owner action here, and we want to save the owner, the owner game object here, the inventory game object
into a global variable. So I'm going to go
to the Globals, and I'm going to create a
new global variable here. And I'm going to call
this inventory Manager. Now we have this
new game object. It dict owner will store the game object reference
to this global variable, and we can get the inventory game object via this variable. This makes it easier
for other FSM to access the inventory FSM from
this inventory game object. And then the next thing
that we want to do is we want to cache a
new line character. And we need this
to define the text of our item information here. We want to show the item name and then the item descriptions, and to break the line, we
need this new line character. And in order to do that, we need to open our
ecosystem roser, and then we want
to get new line. Here we have this
action called Get new line character.
Let's just get this. Now is compiling and
once it is done, let's add that action. Let's just type get new
line character, and here, let's just store the new
line to a string variable, and let's just call
this new line. The next thing
that we want to do is we want to
deactivate the panel, and we also want to deactivate the info panel,
a smaller one here. Let's just add a
activate game object and put this below here, s Let's just put this
activate game object below and disable the
recursive options. For the specified game object, we want to create
a new variable. Let's call this panel. And let's duplicate this action. So we have two
activate game object. Let's just minimize this. This one here, Let's just
create a new variable, and let's just call
this info panel. And now we will have two new game object variable in our variable.
Let's expose them. The first one, I'm going
to expose as an input. And for the panel, let's also expose this
variable as an input. And here, let's assign
the game object. First, we want to drag
the panel game object to the panel slot and the info panel to the
info panel slot here. Let's save the scene. So now we are done here with
the initialization, let's just rename
the statue in it. And here, let's add a
finished transition, and let's create
a new state here. And this is actually for
refreshing the inventory. So we want to refresh
the inventory. I mean, we want to delete all of the inventory item entry, and then we want to
generate a new one based on our inventory
array changes. So if there are any changes, we want to refresh the UI. So in order to do that, let's
just create a new event, and let's just call
this refresh inventory. And let's make this
a global event, and I'm going to add
a global transition. Here, we want to remove all. In order to do that, we need to also download a custom action. Let's just open ecosystem again and I'm going to
search for child here, and we so be having the
destroy children action. It sounds bad, but, it's
basically just destroying the child objects. Pun intended. Let's just press get here. Now, it's finish compiling. Let's add the
destroyed children. I'm going to type destroy and we will have this destroyed
children action. In order to do this,
we need to create a new variable that
will reference to the scroller view and the
content game object here. Here under the
inventor game object, let's create a new
game object variable. Let's just call
this item parent. We want to also expose this. Now we can wreck the
content game object as the value for this
item parent field. And then here we want to destroy all of the child of
the content game object. So basically the item
parent game object here. And now let's add a
finished transition. So once we destroy all
of the entry, I mean, the child game object
of the content, so it's going to be
this item UI here. We want to go to the
next state here, and then we want to loop the inventor array from
the global variable. So in order to do that, let's just use the
array get next action, and this will loop the array, and let's pick the
global inventory, and let's just set the
start and index 20. And we want to loop the event. So in order to do that,
I'm going to create a new local event called Loop, and here I'm going to add the loop transition and
the finished transition. When we are looping,
we want to go to the loop transition. And basically, we want to go to a new state when we
are looping here. And let's rename the
state to loop inventory, so we know when it's finished, we want to go to
finish transition, and here on the loop inventory. We are done, basically, we want to save the value of
our inventory on every loop, let's just create a new
variable that we hold this. Let's type current item. We need to also have a
reference to the item UI prefab but the game object that we are going to
copy, for example, here. Let's just create
a new game object. And let's just call
this item prefeb. Although it's not
a prefe actually, is a live game
object on our scene, but we can copy that. So let's just expose
on input here. And on the item prefe slot here, let's just direct the item UI. Now I'm going to delete
the second object here. And for this item UI, I'm going to put this as a
child of the viewport now. It's not going to be the
child of the content anymore, and let's just disable this
game object so we can see it. And let's go back
to the inventory. Now we should have
the item prefabs. Now we have the current item. Here, we want to add a
finished transition, and when it's finished, we want to go to
the loop inventory, and when it finished
looping the inventory, we want to go to a new state that where we are going to stay idle for
this inventory FSM. Let's just rename this idle. Here on this new state here, we want to rename this
to set up item entry. And basically, there
will be a lot of action. The first one, we want to use
the create object action. Let's just type create object. And with this create object, basically, we want to
copy the item pref. Let's just pick the item prefs. For the parent, we want to make sure it goes to the content, so it should be the item parent. And the spawn point, we
can just leave this blank, and then we want to store the
object into a new variable. Let's just create
a new variable, and let's just call
this item entry. Now we have this game
object reference, the copy, the copy game object. Let's just minimize this action. And then the next thing that
we want to do is we want to get the property from our c
object here, the item class. So let's just get property here, and then we can use variable and then pick
the current item. And here we should be
able to pick the images, the name, and the description. So first, let's
just grab the name. Let's save this to a new
variable called item name. Let's just copy
this property here. And I'm going to pick
the description now here and get the string and save the description into
a new variable called item description with
a shorter item desk. Let's just minimize this
and we can copy this here. And for the third one, we want to get the image and we
want to get the sprite. And here we can save this new variable
called item sprite. Okay. So now we have
get all of the data that we need to instantiate to populate the item
entry and to show the correct information on
the inventory panel UI. Now we need to set up
the FSM on the item UI. Let's just set up the item UI, and then let's create
a new FSM here. And on the item UI here, let's create the
variables that we need. First, we need a string
variable called description. And this is going to be a
type of string presenter. The next one is going to be the name. This
is also string. And for the image, let's just create a new
variable sprite and set the type to sprite.
This one here. And then we want to create a
new factor three variable, and this is going to be
the N three position. Basically, the
position of this UI, and you will see in the sac that why are we needing
this variable? Now, here we have set this up. On the start state, here, we want to set up the
display of the item, so here we can just use
the UI image set sprite. And then for the prt, we can just pick the
sprite variable. And right now, that would
be all for the item UI. Let's go back to the inventory. Now we have set up the FSM and the variables on the
item UI game object, we can use the set
FSM string action to set the value on one of
the variable on the item UI. So let's just pick
the game object and for the game object, it's going to be the item
entry because we want to modify the spawn UI here, which is the item entry, and we can leave the FSM name empty because the UI
only have one FSM, so it will refer to the FSM. And for the variable
name, It is called name, and we want to set this value to the item name that we've grabbed previously using
this get property. So let's just duplicate
this FSM string action, and then we want to send to
the description variable. And we want to set
the description value variable on the item UI to this set value using the item description that we just grab from
this get property. So now we have set
up the FSM string. The last one that
we want to do is we want to set an FSM sprite, but we don't have that, so
we can use set FSM object. Let's put this pillow
here and do the same. We want to pick the game object, the item entry, and
for the variable name, it's going to be sprite. And for the value, we want to pick the item sprite. This will send the sprite
to the sprite variable. Now we have set up
all of this action. The last thing that we
want to set up is we want to set the scale
because from my test, when we are spawning the
UI, the scale is off, so I'm going to
force the scale of the UI using the set scale. And we can just pick
the game object, which is the item. And for the scale, we want to set all of
them 21 on each axis. So we can use this
float variable instead of creating
a new variable, and let's just type one on
all axis and minimize this. Then we want to activate the
object because by default, the object is the activated. The copy will also be activated. So let's just use the
activate game object, disable recursive, and then we want to activate
the item entry game object. Okay. Now we have finish
set up this here. Now let's just give it a try and see how does it work so far. Basically, when we
start the game, when it's finished initializing, it will go to the
finished state and it should refresh the inventory. And then when it's finished
refreshing the inventory, it should go to this idol until we refresh the
inventory again. Let's just press play, and we should be able to, right now, it's working, but For some reason, the panel doesn't get hidden, so we need to deactivate it. So this is where I'm wrong, I need to deactivate this, and I need to also deactivate
the info panel on start. So let's just save this
again. Let's give it a try. Okay. Now, basically, we don't have a way to
show the inventory now, so we can just try to enable
it from the inspector here, and as you can see,
we have the lighter. So right now, the refresh inventory event and the states are all
working good, actually. And now we want to create a behavior where when
we hover the item, we should see some sort of
a item info or description. So in order to do that,
we need to create A couple of events.
The first one would be the show item info, and make this global, and the second one
would be the item info. And this also needs
to be global. For showing and
disabling the panel, I'm going to create another
event called show inventory. And make this also global. Here on the idle state, we want to add the
show item info and we want to also add
the height item info. For this transition,
we want to create a new state both on the height item info
and the show item info. Let's rename the first
state to show info, and here this one, let's name this to Hide info. Basically, when we
are showing the info, We want to set the
info panel position. We need to use the set position, and then we can just pick
the game object info panel. For the position, we haven't
created a variable yet, but we can just create let's just call
this invo position. And we are going to set this
value from the item UI FSM. So let's just leave
this zero for now. And then we want to activate
the game object info panel. Let's just use the
activate game object, disable recursive,
specify game object, and then select the info panel. Let's make the set
positions on top here, and let's just minimize it
and minimize this one also. And then we want
to build a string. So let's just use a
build string action. And for this build string, we want to use the item name. And then second, we want to use the new line character that
we've cache or we save on it. So the next line will be
below the item name string. So the next line is going
to be the item description. And we are going to
set the item name and item description
from the item UI. Okay. So I think
the built string, we need to store
this to a result. So let's just create
a new variable, and let's just call
this info string, and let's just minimize this. And the next thing
that we want to do is basically we want to change
the text of the info panel. Let's just use the
set text mesh. Let's just search for the
text mesh pro UGI text. This one here. And we want to create a new variable to
hold this info tex. Let's just create
a new variable. Let's just call this info text. For the text, we want to use
the build string result, which is the info string here. Once we have set this all up, we want to add a
finished transition, and then we want to
go back to the idle. Case. Now we have this here, Let's go to the
variable and let's expose the info
text variable here, and now we can expand
the info panel and direct the game object
to this infotex slot here. Let's save the scene here. Now upon hiding, we want just to deactivate the info
panel. It's very easy. So we can just use the activate game object and disable both
recursive and activate, and then we can just pick
the info panel variable. And we need to add the finished transition to go back to the idle state here. And then we want to create the functionality to
show and hide the panel. Let's just create a
new Boulan variable that will hold this state. So let's just call this panel. Let's just call
this panel opened, and by default, it's
going to be false. So let's just add a transition, the show inventory
transition from idle here, and let's create a new state. And let's just call
this togal panel. And basically inside
the state here, we want to flip the bulion. So we can use the bulion flip, and bulion flip we flip the bulion back and forth from false to true and true
to false and so forth. So whenever we enter this state, this value always change
to the opposite value, and we can use this value to activate or
activate the panel. So let's just use the
activate game object. And disable the recursive, and we can put this below here, and we need to pick
the panel variable, which is the main panel here. And for the value,
we want to set this to the panel open variable. So the activate game object. Activate value will be depend on our panel open that are
being flipped all the time. Whenever we enter the state. Let's just add a
transition finish and to go back to the idol. Now we should have
something like this here. Since this is a global event, we can trigger this
from another FSM, but we can also trigger this
from the button callback. And now let's just create
a button group here. For make it easier button group. And this is going to be let's go to the scene view here
and I'm going to put this button group on the top right of the
screen, make it bigger. I'm going to make sure to
round this value here, maybe 2250 or 300 in width
and make this also 300. The next thing that
we want to do is probably we want to add
a vertical layout group, and now we can add a button. Let's just add a button
text Mach pro here. Let's set the size of
the button to 250, the height 260, for example. Here on the button group, let's set the child
alignment to upper center, and let's add a padding. We have space on the left, but on the top and the bottom. K. This is going to be
the inventory button. Let's just type
inventory button. And let's rename the
text value to inventory. I'm going to make the
out of size tech, so we will have a bigger value. I'm going to set the
maximum to run 40, so it's smaller, but it's quite readable from
our game view. I'm going to say
the scene again. And now we can create an
FSM to trigger the panel, but it will be easier if we just add an on
click event here, and we can the
inventory game object. And here under the function, we can access the playmaker FSM, and we can send an event, and we can type the event. So we know that the event name is show inventory all caps, so let's just type this. And this is the
global inventory. Sorry, this is the
global event that we've expose on the
inventory FSM here. There you go, so we can
use this name here, and this basically will
trigger the event. Every time and it will
toggle the panel. So we can easily show and
hide the inventory panel by clicking this button.
So now let's save this. We already set up this, but we need to set up the
item UI FSM right now. So now let's just start
working on this FSM. First, let's just add a finished transition because we finish initializing this, and let's just call this in it. Let's create a new
state from this here. And I'm going to call this
wait for Mouse Hover. And basically, we
can just create a local event called
for example, on Hover. And then on exit. So let's just add on hover here, go to the other state, and then for the other state, we can just add on exit and then go to
the wait for hover. Basically, on the
wait for hover, we want to send the item info
to the inventory manager. So we can use the send event. And now we have cached the inventory game object
into a global variable. We can just pick
the game object FSM here and specify game object, and then we can pick the
global inventory manager. For the vN, we don't need to set the FSM name because
inventory only has one FSM, and we can pick the global evN, and we want to hide
item info here. Because whenever
we are hovering, we want to show it here, and when we are exiting,
we go back to the state, we want to hide the, sorry, I add it to the wrong state, so let's just cut this action
by pressing control X. And then here, I press control
V two paste the action, and then we can copy this
se event to the state here. But instead of hiding, we want to show the
item information here. Okay. And the other thing that we want to add
on this date here, we want to use the UI
pointer enter event. So this will works
when the mouse are entering the
UI space or area, then this will get
triggered and we can trigger the on hover event. And we can copy this sorry,
we cannot copy this. We need to add a
different action here, let's just add the pointer
exit event this time, and when exit, we want to
trigger the on exit transition. And basically for the wait
for Hover, we are done, but for the update descriptions, there are a couple of things
that we need to do here. So before we are
sending the event, we need to send the
data of our item I. First, we want to
get its position. L et's use the get
position here, put it on top, and
we can use owner. But we want to store this two a vector entry position
that we've created before, and this is where we are
going to use this variable to send this position into
the inventory manager. And then we want to use the set FSM vector
three variable, so we can set a vector three
variable on other FSM. And here we can just pick the
global inventory manager, and then if I
remember correctly, the name is item position. So let's just check
for a moment here. In the inventory, when
we are showing the info, we are getting the value
from the invoke position. So the name is info position. Make sure we type
that name correctly. Oh, sorry, not item
but info position. So let's just type
invoke position. We want to set the value to the entry position variable that we have just
grabbed before. And then we can use the
set FSM string to send the name and the description of this item that we have here, so let's just pick the global
inventory manager again. And for the variable name, we are going to
overwrite the item name. With the name of
the game object, and we can duplicate
this FSM here, and then we can overwrite
the item description, and we want to pass
the description. Now we have set up the position, the string and the name and the description string
here. Let's save the scene. Now let's check one more time. When we are showing the info, what variable did we use
on the built string here. We use the item name
and item description. So it's all correct. Now let's test this and
hopefully all works great. Okay. If I open the inventory
panel here, as you can see, we can show and hide
the inventory using that click event on the
inventory button here, we can send an event. And here, for example, if we ho over the lighter, we should be able to see that, as you can see, but
the position is wrong. So let's just check. I
found the issue here. Basically, when we are setting the set
position info panel, we need to make sure that we are using the world
space because we are getting the info position in
world space, for example, if we select the IMI
game object here, we are getting the world
space of the position. We need to make sure that
the info panel set position, it's also ino space, and it was on local space here, let's just select this world, and let's give it an try. Okay. Now as you can
see, if we hover, it shows the panel pop up
on the correct position, and if we exit the UI or the
item UI, it hides itself. And now, a small changes that we need to do is
we need to trigger the refresh inventory whenever we receive or we remove an item. So here on the gift and take
item, we want to addit that. So here on the NPC take item, whenever we are
changing the inventory, either via take item
FSM or give item FSM, we need to change this, so
let's just addit this here, and for the take item,
whenever we give The item when we
remove the item, we want to call the
refreshed inventory. In order to do that, let's
just add a sign event here. And we can access the game object FSM via
the global variable, which is the inventory
manager here, and then we can call the global
event refresh inventory. And here we can just copy this action here by
pressing Control C, and then I can select
the gift item NPC here, and I can edit the template. And here, basically, whenever
we receive the item here, we can just run the same refreshed global event from the inventory manager. Case. Now let's give it a try. I'm going to disable the take item NPC and
enable the gift item, so we should be
receiving the item, and now let's test this. Let's talk with this NPC here and there seems to be an issue here where we
don't see the dialogue. After looking into the problem, I found the issue
that the inventory game object for some reasons, have a text mesh pro tax UI
components attached to it. And this could happen
for a couple of reasons. The first thing that I've
noticed that when we add this text mesh pro
UI text action, I might have clicked
the warning button that adds this component
automatically into the inventory game object. And this text mesh
pro component is now covering the recast
to this dialog panel. So we can just safely
delete this component here, and we can also delete the
CVAs render component. So now let's give
this another try. And let's take the item. Let's not take it, but
let's see our inventor. Okay. We only have lighter, and the NPC is offering
offering us a key. Let's press sure. And let's check our inventory. There you go. We have inventory, the lighter, and the key. And we can see both
information very nicely. Now let's give this another try, let's disable the gift item, and let's enable
the NPC take item, and let's check
the yes response. It as for the lighter, so we should see that
our lighter gets removed when we are
interacting with this NPC. Now we have the lighter. If we talk to this
NPC, for example, if we gift our lighter here, sure, we should ok, there seems to be an issue here. We still have our lighter. Let's check this problem. So yeah, the problem
is that here on our take it
template FSM here, whenever we give our
item to the NPC here, we are running this
FSM success actions, and it will run the
list of FSM array on our take item FSM here. It will trigger the
success actions, and it will run the finished transition
when it's finished. So it this sN event never
really gets executed. So in order to do that, to fix this, we need to
move this to the top here, and we need to make sure that
this event gets executed before this run FSM is running. So let's just minimize
all of this here. I'm going to save our project, so it will save the changes
on the template FSM. And now let's give
this another try. And, I have this Tgal Breck pron enabled on the inventory, so let's just disable this
and save the scene again. And now let's try, sorry. Let's check our inventory first. We have lighter. Let's
talk to this NPC here, and let's press sure. And then if we go to
our inventory panel, you see that we don't
have inventory anymore. And in our inventory
global variable, we don't have item also anymore. So, this is quite
a lengthy lessons, but yeah, because
basically there are a lot of things that
needs to be set up, yeah. But with this setup, basically we can create a very
modular inventory system, and we are going to continue to add more features
in the next lesson. H
21. 20 Save and Load Concept: Now we are going to create the safe system for our
point and click game. And basically, there are two things that we need
to save in this game. First is the transform
of an object. Either is it a player or an NPC? We need to record its
position and its rotations whenever we are saving or whenever the object
has finished moving. And we also want to save the
active state on each FSM. For example, this
NPC dialogue here, if we check the inspector
here on the intractable, you see that we have
this list of actions, which is an FSMs actually, and this are the FSMs
on the child object, and we want to record the active state of
each of the FSM. So for example, if the base
dialogue is activated, and if we check the
inspector here, the intractable
component, I mean, we know that the other FSMs
that are being tracked by this interactable component is the yes response and
the no response. So we want to record all of
those FSM active states. In this case, currently, the base dialogue is activated, the yes response
is de activated, and then response is
also de activated. And if we talk to this
NPC, for example, if we try to interact
with this NPC here, and then we response from
one of these two options. You see that the active
state will change. Now the base dialogue
is disabled. The yes response is activated, and that no response
is still disabled. So we want to keep
track of these changes, and we want to convert the value of this Bula into a string, either zero or one. So we can easily save this data into our safe file
on under this, so we can continue the
progress or the game progress, and we can load
those save states from string back to bion Okay. And the thing that
we need to only keep track is the actions
on the interactable. Because this is the
one that are going to get triggered whenever
the player interact. So if there are
changes of state, then we want to change the
state only on these FSMs. And we don't need to think about the other FSM like this S
activate and no activate, because these FSMs only change the active status
on the FSM objects. So yeah, that is the basic
for the states recording. And here, I've already created
some sort of diagram here. So basically, for the
transform is quite easy. We want just to record the
position and rotations. And for the states, we want to record all of this FSM states. F Boulan converted
to a string format. For example, if the start
dialogue is disabled, and yes, response is enabled, and this one is disabled, then the string format will be 01 and zero from
the top to bottom. And we want to save all of
this here to our safe manager, and inside the safe manager, we are going to use a custom actions called JS Safe and JCN load
that I've created, and it's available on ecosystem. And then once we've
create the safe manager, whenever we are loading, we are going to
load the data from the disc also from
this load manager, and then we are going to
apply the transform to the object that it's
transformed was safe before. And then we are going to apply the position
and rotations, and the same goes
with the states. We are going to apply
the state that are safe in string back
to bul and then apply those values to enable or disable the states depending
on the safe value. And you might wonder,
how do we keep track which object
gets which data? It's actually quite simple. Basically, we create
a for example, I'm going to create
a new node here. We are going to create
a couple of array. So for the array, let's
just call this entity name. And this one for
states, for example, Then we want to save
the game object name that holds this
intractable component. This should be the
game object name, and we need to make sure that the game object names is
unique on each object. There are no different
game objects with same name, for example. Then we want to save this
to an entity states data, for example, and this will
be a type of FSM array. But it's string, for example. And this will be also
a string. FSM array. String. And whenever we save
a new NPC, for example, we are going to store
the game object name into this array of string, and we are going to
save the state of the FSM to this states data. So whenever we add a new entry, both of this string
game object name and the states data are going to be filled on the same
index of this array. And this will be our identifier. Whenever we are loading later, we can search for the game object name on the
entity name states array. And once if it's found, then we want to copy
the index value, then we can use that index value to get
the entity states data. So that is the basic
disk of the safe system. And the same goes with the applied
transform, for example, for the applied transform, we are going to need to create a separate identifier here. For example, I'm going to
create an array string called entity named
TR S for transform, and this is also
FSM array string. And this would be also
the game object name. Then we can add another array, for example, the position, and this would be a type
of FSM array vector t. Then we want to save
also the rotation, and this needs to be
on a different array. This is going to be the
FSM array vector t also. Whenever we want to get the transform that
we are going to apply to a specific game object, then we can look through
this entity name transform. Based on the game object name, and once we found the entry, we can get the index and
we can use the index to retrieve the entity
position and entity rotation, then we can apply those
values to the game object. This way, we can create a complex safe system
with different objects that can store its position
rotations and the FSM states, and then later, it
can be reloaded to the game objects when the player continue the
progress of the game. So that is the basic
concept of the safe system, and if there are more questions, feel free to ask in the
questions and answers section.
22. 21 Setup Save Manager: So now we are going
to working on the safe and load
system mechanics. And the first thing
that we need to create is we need to
create the save manager. So I'm going to create a
new empty game object, and we can just
reset its transform. And let's rename this
to save Manager. And I'm going to put
this game object on top of our scene here. Let's take the scene. And now we want to create a new FSM. I'm going to make the
FSM window bigger and press at FSM to
create a new one. And here, first, we want to create a state
to save the data. Here let's create a new state, and let's just call
this loop all it FSM. Basically, we want
to look all of the record transform and
the record state FSM from the entity and we
want to run each of the FSM run actions transition. In order to do that, we need
to create a global variable. Let's just go to the editor
Windows global variable. And here, I already
have mine opened. Let's just create a new array. And let's just call
this NTT saver FSM. For the type, we want to
change this two object, and we want to
pick the playmaker FSM as the object.
Now we have this. We can loop this saver FSM by using the array,
get next action. And then we want to pick the global array that
we've just created. We can leave the
start and N index 20. It will loop all of
the member here, and we want to
create a loop event. Then we want to add
that loop event here. Then we want to also
pick the loop event, and for the finish, we can
pick a finish transition. I think we need to
add that first so let's just add the
transition finish, and now we should be able
to pick finish transition. We need to also create a
global event called save, and let's mark this
as a global so we can easily trigger this
transition from other FSM. Let's add a global
transition save here. And now we want to
save the result into a single variable or a single
playmaker FSM variable that we can manipulate with. Let's just create a
new variable here, and let's just call
this current FSM. And this will create a
new variable that are compatible with the
array object type here, the play Mer FSM. And then basically
when we are looping, sorry, when we are looping, so we need to create a new state from the
loop transition. We want to invoke
each saver FSM. So let's just rename
this to invoke each FSM. And then here on the
invoke each FSM, we want to use the call method. Action here, and we can pick the current FSM
as the behavior. And for the method here, we want to run the
SN event string, and we want to run
the run action given. So the entity saver FSM for either the
transform or the states, we also have a global
transition run actions just like any other actions or template that we
are using for the NPC. This is to make it easier to
run the state that we want to run whenever we are
loading or saving a data. Let's save the scene here. And now, if it's finished, then we want to go
to a new state, then we want to save the data. So let's just call
this save all data. And basically, we need to import a custom actions
that I have just created, and it's available on ecosystem. Right now, let's just go to the add ons menu here
under ecosystem. Let's open the brocer, and let's just type JSN. And we should be receiving
the result here, and the action is called JS
and save and s and load. Let's just press get
for the JC and save, and let's also get
the Ks and load. Right now, the script is
compiling, and now it's done. So let's just close
the ecosystem here. And if I type save here, we should have the
JCN save actions, and this action can
save a lot of variable, including vector types and
also an array variable type. Here on the JCN save, we need to save a couple of
array that we need to create. Under variable, let's
just create a new array, and this will be the
entity name transform. And this is for transform, and we want to change the
type from flow to a string. It's going to be an
array of string, and I'm going to
create another array, and this is going to be
the entity position. For the entity position, the type should be vector three, and I'm going to also
create the entity rotation, and this should also
be vector three. Now we have all of the
variable that we need to save the transform
of an object. Here on save all data, we want to adjust
the array variable. Member here, 23, and the first one would be
the entity transform. The second one would
be the position, and the third one
would be the rotation. Now this save whatever
values that we have here. And basically, we need to prepare this value
in a new state. So here, I'm going to create
a new state, and basically, we are going to check
the entity name, and we need to create a global event to be used
as a global transition. So let's just type
record position, for example, and
make this global. And then I'm going to add a global transition
record position here. Basically, we want to check if the entity name
transform array does contain the entity name that
we are checking currently. Here, we want to use the
array contains action, and then we want to check
the entity name transform. For the value, we want to create a new variable
type of string. Let's just call this
current entity. And we are going to set
this value whenever we are saving the FSM objects, and we are going
to grab the name of each FSM that is
currently invoking, and we can compare
this value here. And basically, we need to
create two new local events. First one is add, and
second one is replace. And let's add both of those
transition at and replace. Basically, if the array does contain the
name of the object, then we want to use the replace transition
here on the event. We want to use the
replace because we already have the
data save previously, so we want to override it. And if the entity name
transform does not have the name safe in its array, then we want to send
the ad event here. Let's just create
the ad state and the replaced state. Okay. So for the add state, I'm going to rename
this two ad transform, and we want to use the array ad. For the array ad, we want
to pick the name transform, and then we want to pass
the current entity value as the new value that we are
going to add to this array. And then we are going to also create another
array ad here. And for this one, we want
to add the position. We need to create
also a new variable. And let's just call
this current position. Later we are going
to set this value. Then the last one, we
want to add a rotation. Let's just pick the
entity rotations array, and then for the value, we want to add the new variable
called current rotation. Then we can just add finished transition
whenever we are finished, adding those values
to the arrays. Let's disconnect finish back
to this loop all entity FSM. Then here we want to
replace the transform. So once we found the
name inside the array, we can save its index. So we need to save this
to a new variable. Let's just call
this current index. Then here, we can set the
array based on its index, so we can use this
ray set action. And here we only want to set the position and using
the current index, and we want to set this to the
current position variable. And for the other one that we want to set
is the rotation. Let's just adjust this order, put the rotation below. Here for the array, let's
just pick entity rotation, and then the index should
be current index also, and for the value, we can
use the current rotation. Now this replace the
value if the entity that contains the object name that are currently
recording its position. So let's just minimize this at a finish transition and connect this to the loop
all it FSM state. So basically here, what
is going to happen here. Whenever we trigger
the state here, it will loop the
entity saver FSM, and then when it's looping, it will invoke each FSM, and each FSM event
will be invoked. The run action event will be invoked on that specific FSM, and on that FSM, the run actions will actually invoke this
record position. After we are setting the
current entity name, the position, and the rotation from that FSM from
each of this FSM here. And now let's save this. And I'm going to add
a finish transition from save all data to
the start state here. And basically on start state, we need to initialize
a couple of things. So let's just call this
initialized and here, basically, we want to get the owner of this game object and save this
to a new global variable. Let's just create a new global variable type
of game object. Let's call this safe manager. And let's save this to the
safe manager global variable. And this will make it easy to access the safe manager
from other game object. And we want to create a button to test
this functionality. So here on the Canvas
under the button group, the inventory button here, I'm going to duplicate this
inventory button twice. And the first one, I'm going to rename this to safe button. And the third one is going
to be the load button, and we can remove the on click event on each
of the button. And then let's expand the
text game object here, and let's change its caption to save and this one to load, for example, let's
save the scene again. And here on the save manager inside the initialized state, we want to add the UI
button array action. And this makes it easier for us to pair a couple of buttons to trigger certain event here. So where is that? Okay, I put it on
the wrong state, so let's just cut these actions. Go to initialize and
then paste it here. And basically, we want to
only access two button here. For the button, let's just
expose the game object. So let's just type
the safe button here, and the type be game object. And we can expose this. And I'm going to add
a new category UI. And then let's just
create a load button. And for the variable type, change this to game object. And let's also enable the input check box and
add the UI category. So it's categorized nicely
here in the Inspector. And now we can pick those variable for the safe
button and the load button. But Load button, we haven't
implemented that yet, so we are going to
set up this later. But for safe, we can
pick the safe event. Whenever this button
gets pressed, it will trigger this safe event. And now we can put
the load button and the safe button accordingly to the slot
in the inspector here. Let's save the scene here. And now let's set
up the safe and the FSM template for the object that are going to change in position
during the gameplay. Now we need to create
that custom action, so I'm going to create a
temporary empty game object just to create these actions. So let's just add an FSM here. And for this FSM, I'm going to call this Action record Tit transform. Basically on the
first state here, we can just We can just
rename this two initialize. Inside this initialize, we want to get the
name of the owner. Let's just use the
get name here. And basically, we need to create a new variable called owner here and start the name to a new variable
called tit name. And for the owner, we
want to expose this as an input because this is
going to be a custom action, so we can assign this variable from the run FSM action later. Here on the state here, whenever we finish initializing, we want to go to
another state here, and basically we want
to grab the transform. So let's just call
this grab transform. And basically, we want
to get the position, and then we also want
to get the rotation. And here we want to get
the position of its owner, so we can just specify
game object because we are going to receive this
value in this owner variable. And for the position, we want to save Sorry. For the position, let's
just change the order here and set this also to
the oder variable. For the position, we
want to save this to a new variable called position, and make sure the
space is rolled. And for the get rotation, we want to get its uler angles, and let's save this as rotation, and we can just minimize this. And now whenever
we are finished, grabbing the transform, we
want to go to another state. And we want to save this
value into the safe manager. So here, first, we need to
use the Set FSM string. And basically, we want to
save or we want to send the name of this game object so we can set the value to
the variable entity name. And for the variable name, it's called current entity on safe manager that we
are checking against. And then we can
leave the FSM name. Empty because safe manager
only consists of one FSM. And here on the game object, we can specify game object, then we can pick the
global safe manager. And this is why we are preparing the global variable to hold
the safe manager to make it easier to access this from any actions that are going to communicate
with the safe manager. Next thing that
we want to add is that we want to add the
set FSM factor three. So let's just use the set
FSM factor three action. And then here, put it below. We can just pick the
safe manager again. And for the name, it's going to be the current position and current rotation. So the first one,
we can just type current position and sets
its value to position. And then we can
duplicate this action, and this is going to be
the current rotation. And we can set its value to the rotation that
we grabbed before. And now we have set all of the variable needed to be
sa in the safe manager. We can send an event. To the Safe manager. Let's just pick game object FSM here, specify a game object, and then we can search for the safe manager
in the global variable, and we want to send the
record position global event. If we go to global event, we should be able to see
this record position. And this will record the position of the
owner of this action. Let's just save
this as a template, and let's just call this action
record entity transform. Now we have set this up. We can just delete
this game object here. And now we can try this on
our NPC move game object, and we want to create
another FSM to record this. Here, let's just add
let's add a new FSM here. Let's call this FSM record
TT transform, for example. Here, on start, we
want to get the owner. Let's just use the
get owner action. And then we want to store into a new
variable called owner, and we want to get
the FSM component. Let's just get FSM component. I think this is custom action. Let's just open the
ecosystem here. And I'm going to I'm going
to type FSM component and we should be able to download
the get component. This one here. Get
FSM component. Let's just press, get. And now
we have import the action. Let's just search for get FSM
component. Now I have it. But this requires FSM name, so we want to create
a new variable. And let's just call
this this FSM name. And for the result, we need to save this to a
Plam FSM variable. So let's just create a
new object variable, and let's just call
this this FSM. And for the type, let's
change it to Playmaker FSM. And now we can save this
to this FSM variable. And basically, we want to send this FSM to the
entity FSM saver, global variable
that we've created here when we are creating
the safe manager. So now let's add an
array ad action. And then here, we want to take the global
entity saver FSM, and we want to add
this FSM here. Let's just minimize
all of this here. Now we want to create
another state, and then we want to add a
global transition run action, so we can use that the one
that we have created before. Inside this run
action, basically, we want to only use
the FSM action. And then here we can pick the action record entity transform that
we've just created. And for the owner, we can pick the variable owner that
we've grab here on start. And let's edit this action, and I'm going to make sure
that here on the SN event. I'm going to add a
finish FSM action. And this is needed to stop the FSM from running
whenever it's being used. So for example, here on the
record entity transform, this will trigger
the finish event. Okay. Let's just save
this scene here. And now we need to create
the load transform action. So let's just create the action. Now I'm going to create
another anti game object. And I'm going to
add an FSM here, and let's just call this
action load entity transform. Basically here, on
the first state, we want to get the FSM array
from the safe manager. So let's get an FSM array here. Let's specify game object, pick the safe manager. And here we need to grab the let's take a look for a
moment. The variable name. I'm going to rename
this to entities, so we know it's an array to make it
more clearer entities, and this so be also its and this is going
to be also entities. Now we have saved this. Go
back to the new game object, and on the first state here, let's pick the entities position and we can save this to a new variable with
the same type, so we need to create
those variable. Let's just call this
entity position and create another one
called entities rotation. And the last one is going
to be the entity's name. For the name, let's set
the type to string. For the position,
it's going to be a vector t and the same
goes with the rotation. It should be also a vector t. Now we have set up this array. Let's just store the
values that we are getting from the safe manager
to the safe position here. Let's duplicate this action, and let's grab the rotation this time and save it to the
entities rotations. Let's minimize this. I'm
going to copy this again, minimize the second one, and this one will be
the name transform. Let's take a quick look here. Yeah, this entity's
name transform. So this should be correct. And let's save this to the I
think we need to reset this, so I'm going to
reset this actions because it won't read
the entity's name, because it was previously used for storing Vector
three array variable. Let's just pick the entity's
name and I'm going to retype the variable name here, and we want to specify the safe manager
as the source FSM. Now we have set this all up. Let's just rename this go
entities transform data. And here, let's add a
finished transition, and we want to go to
the next state here. And basically, we want
to check states data. And here we can use the
array contains again, and we want to check the
entity's name variable, and we want to check against a new string that
we are going to create, which is called entity name. If we do have the name
inside these entity names, then we want to
send a event here, and otherwise, we want to send
the not found event here. And here, we can add load, and then we can add not found
as the not contained event. Let's add both of
those transition. And here, if it's loading, then we want to go
to the state here below and we want to
extract the transform data. Basically, when we are
checking the name, we want to save the index here. So let's just create a new
variable called index. And now we want to
use the array gap. Action. And this will get a specific value from an
array based on its index, so we can get its
position, for example. And then we can get using its index to get
the position and we can store the value
to a new variable. Let's just call
this position data. And we can duplicate this. For the second one, we want to iterate through to the
entity's rotations, and we want to save this to a new variable called
rotation data. Now we can just at a finished transition and
go to the other state here, and we want to apply the data. Let's just call this apply data. And when we are
applying the data, we need to create
a new variable. Let's just add a set
position action, and we want to create a new
variable called entity, and then we want to
set its position to the position data and make
sure that the space is led, because we are saving
in real space, and for the other action that we want to use
is the set rotation. Here, we want to use the same game object,
which is the entity, and we can paste the
rotation data into the uler angles value here field and make sure the
space is also rolled. And now we can minimize
this action here. We can add a finish transition. And whenever it's finished, then we want to run
the finish FSM action. Let's just rename this
to finish action. If it's not found,
then we want to go to a new state just for the
bugging. The bug here. And we can add a D bug log
and probably say warning, and we can send this to Unity log so we can see it
on the console here. And we can type like entity Name is not found in transform
record, for example. We know there is an error
here and we can just add another finished transition and then connect to
the finish action. Here, let's just call this
get data and then apply data. And then we need to make
sure that a couple of variable here are
exposed as an input. First, the entity, we
want to make sure this is an input variable
and the entity name is also an input variable. So we need to send this value whenever we
are using this action. Now we can just save the template here by pressing right click and
then pick save template, and then we can
just save this as action load entity transform. We can just use it because we are going to delete this anyway. Now on the NPC move here, we can add a new FSM. Let's just call this
load entity transform. Here on start, we want to do the same as we did on the safe. So first, we want to get the owner and save this
to any variable owner. And then we want
to get the name. Let's just pick the
owner variable and store this as the name variable. And then we want
to minimize this, and we want to get FSM
component again here. And for the FSM name, we need to create a new
variable called this FSM name. Then for the result, we need to create a
new object variable. S object variable here. Let's just call this this FSM. And for the result, we can pick this FSM. And then we want to add this
FSM that we've grabbed using the Get FSM component to
an array using ray ad, and here we need to create a new global array variable
called entity loader FSM, and this would be
a type of object, and then pick playmaker
as the object type, and we want to add the
FSM to this array here. Let's just pick the global
entity loader FSM array, and then we can pass the di. Okay, this is an FSM object. I need to change the type. I forgot to change this. Let's change this FSM
to the playmaker FSM. Yes, and then here, we should be able
to pick this FSM, and we should be able to store this FSM to the
entity loader FM. So now we need to add
another state here for loading and add a global
run action transition. And here inside this run action, we want to run an FSM. And for this FSM, we want to pick the action
load entity transform. And this will ask for the entity game object,
which is the owner, and for the name,
we can just pass the name, and let's save this. And now we have set up the transform loader template
on this NPC move here. This one here, we want to create a load mechanics
in the safe manager. In order to do that, we
need to add a new event. Let's call it load and make
sure this is a global event. And let's create a new
state for loading here. And basically, we want to
load the data from this. So here I'm going to rename
the state to load from disc. And I'm going to add a global
transition peak load here. And here inside the
initialize the button array, for this load button, we can send the event to load whenever we
are clicking here. So let's just set
this two load here. And now inside the
load from this state, we want to use the
Jasen load action. And basically, we want to do the same with the safe
all data here. So for example, right now, we have three array variable, and this is the order,
the name transform, the position, and the rotations. We want to make
sure that we have the same order in
our load action. So let's just set the
same amount here. And for the first one, it should be the entity's
name transform. The second one should
be the position, and the third one
would be the rotation. So basically, this will
load the data from our JC that we saved in the disc before in this
safe all data state. And this will load all of the
data that are saved before, and then we can use
this for the NPC or the objects that requires its recorded position
and rotation. So now I'm going to add
a finished transition, and we want to go to
another state here. And basically, we want
to loop the loader FSM. So in order to do that, we need to use the
array gat next. Probably, I'm going to rename
this loop all loader FSM. And here for the array, we can pick the globals and then pick the entity loader FSM. And then we want to store the current iterations to
the results slot here. So let's just pick
the current FSM. We can use this because it has the same data
type playmaker FSM, and these are being used in
the loop entity FSM here. So now when we have the result, we want to look
through it and then invoke the run actions on
each of these loader FSM. So here, let's just rename
the state to invoke each FSM. Since the name has been used, then we can pick another one
like invoke each loader FSM. And then inside this state here, we want to use the
call method action. And then here, we want
to use the variable, and we want to use
the current FSM. And for the method, we
can use the send event. And since we are using
the run action to invoke the saver
and the loader FSM. We can just type run action. L et's add a finished
transition here. And let's connect this
to the looping here. And basically,
when it's looping, we want to go to the
loop transition, and when it's finished, we want to add a
finished transition and then set the finished event
to the finished transition. And whenever we finish looping
all of the loader FSM, then we want to go back
to the start state here. So let's just save this. And now let's give this a try. So basically, the NPC move here, the record entity transform
and the load titor transform, both are registering itself to the entity safer FSM
and entity loader FSM. L et's check the settings here. We should have the
FSM name expose. We haven't exposed that,
so I'm going to expose the one on the load and
the transform here. Set this as input, and then here we want to
copy the name of the FSM. The same goes with the
record entity transform. Let's just expose this
FSM name variable, and we can just copy the record transform name into this field here
and let's save this. Now let's give this a try. By default, when we
are running the game, We should be able to see that this entity loader FSM
will have a member now. So as you can see here, the entity saver has a FSM registered to
the first element, and the same goes with
the entity loader. It has this FSM. And this is referred
to each one of these. Record will go to
the entity saver and load it transform will go
to the entity loader FSM. Right now, we have
this registered. Let's try to interact
with this police officer. And once he is moved, let's save the gain. There seems to be an issue here where it says
that access path to. Let me check of this issue here. Okay. So I found the issue, and it was basically a
silly mistake that I did. I haven't set the file name,
so we need to set that. So I'm going to give this
file name, Jason, Save Jason. And let's just duplicate
this string here, copy and paste this on
the load from this. So it has the same name
as the safe action. H, sorry. I think
it was cut before, so let's just paste this again, and I'm going to save the scene. And now we can test
this But before that, let's make the record entity transform to a template and also the lot entity
transform FSM. I'm going to delete the FSM name here,
this variable here, and I'm going to save
this as a template, and I'm going to call this
template record transform. And we want to use
the save template to this NPC move here. Now we can copy the name and paste this into this FSM name. And the same goes with the
load entity transform. We want to save the template, and we want to rename this
two template load transform. And basically, we want to copy the name to this
variable slot here. And make sure that this
FSM name is exposed so. In order to do that, we can just addit the template here
and go to the variables and select this
FSM name and make sure the input was checked because this
was unchecked before, and I had to check this. And the same goes with the
record entity transform. So if we dit this,
make sure that this FSM name input
option is checked, so we can set up the
value in the inspector. So now we have saved the record entity transform and load entity transform
into a template. We can use that
also to the player. So let's add new FSM
twice on the player. So we have two new FSM, and let's just call
this record transform. And the second one will
be the load transform. And we can use the template
that we've just saved here, let's pick the template
record transform, and this one will be the
template load transform. Now we need to copy the name and paste this to the
input field here, and the saving goes with the load transform
and paste it here. Now let's save the scene, and now let's give this a try. So let's interact with this police officer and once it's finished moving,
let's save the data. Now it's gets safe. And if we stop the game
and we try this again, Let's try to load this. And as you can see, there, it loads the data of
the police officer, as well, the player,
and it loads both its position
and its rotation. And now we can check the GSN data that we've
saved on this here. So for example, I've
already opened the folder. Basically, it's on my user
name, app data, Local. And since I haven't changed the default company name
in the player setting, so it's in the
default company and the project name playmaker
point and click. And this is the save data. If I open this, As
you can see here, we have a JCN but it's
not formated correctly, so we can just copy this. If we want to see in
a formatted manner, and we can go to this website. It's called jcnlin.com. We can paste the data and validate the JCN as you can see, it will format the
JCN correctly, and the entities
name transform array has two string values, the player name and
the NTC move name. And both the position and
also the rotation also have two vector values for its
position and its rotation. And as you can see here, this entries corresponds
to each entity transform. So for example, the first one would be the player position, and the second one will
be the NPC position, and the same goes
with the rotation. The first one is the
player rotation, and the second one
is the NPC rotation. And as you can see here,
using this approach, we can get the index from the name transform
and using that index, we can access the position
and the rotation. So that is basically how we set up the safe system
for the transform, and we'll also work on the safe system to save
the states on each NPC because there will be
different states on the NPC depending on the face or
on the moment of the game. For example, if we give an item or if we take an
item from an NPC.
23. 22 Record Entity State: Now, let's continue to
work on our safe system, and this time, we want to
create the record state action. So here we want to save
the dialogue state here. So, for example, here
on the NPC dialogue, we have the three actions that are assigned in the
interactable component. And right now, the one
that it's enabled, it's the based dialogue. And yes, response is
disabled actually here, as you can see, and the
same goes with no response. It is disabled. And we want to save
this value for all of the FSM that are assigned in
the interactable FSM here. So we want to save the state. And in order to do that, let's create a new action. So I'm going to create
an anti game object. This way, I can create an FSM, and we can save this as
a template right away. And basically on
the first state, we want to initialize. And we want to use
the set string value because we are going to save those FSM states
value in a string. That's why we need to
create a new string here. And let's just call this FSM
states. And let's clear it. So we want to set an empty
value on the string value. This will clear it. And then we want to get
the name of the owner. So let's just use
the get name action. And here we can create
a new variable. Let's just call this owner and put this below
the set string, and we want to store the name, and let's just call
this entity name. And basically the
owner variable, we want to expose this. So let's just expose this
under the input option here. And then we can finish
the state here, and then we want to
go to the next state. And basically, we want
to look through the FSM. Look through the FSMs
that are assigned here on the interactable FSM. So in order to do that, we need to create an
array variable type of playmaker FSM. So let's just create an array. And let's just call
this FSM list. And for the type, let's change this two object and set the object
type to playmaker FSM, and we want to expose this. Okay, now that we have
created this array, let's just look
through that array, and we can use the
array get next. And basically, we want
to pick the FSM list here and we want
to loop the event. We don't need to change
the start and end index. This will loop through all of the members of this FSM list. Let's add a loop event, and I'm going to add the loop transition as well
the finished transition here. And when it's looping, we want to go to the Loop event, and if it's finished, we want to go to the
finished event. So loop here, we want to go to the other state to
a new state here, and we can call this get FSM
active state, for example. Now that we are looking
through the FSM list, we need to save this
two A variable, so let's just create
a new variable, and let's just call
this current FSM. And then here in the GT
FSM active state here, we want to use the GT property. Get property and set property is actually
using reflection, and this is a bit slow, but if we use it only once, every couple of times, for example, we don't use it in an update or every frame state, then we should be okay. Another note that
we want to avoid using Get and Set
property when building for mobile platform because not all mobile platform
supports this reflection. Okay, so now we want to
pick the current FSM here. And basically, we
want just to get the enabled properties here, and we want to store the value to the new variable,
new Bullion variable. And let's just call
this FSM enable state. And now we have a bul in value. We need to convert
this two A string. So in order to do that, we can use the convert
bull to string action. Here, we can just pick the bullion that
we've just created, and we need to store the value into a new
temporary string variable. Let's just create the variable, and we can just call
this state in string. And for the false string, we want to set this 20, and for the true string, we want to set this 21, and we want to put this below the gut property and
then we want to use the built string action to build the state string that we are going to save
in our save system. So basically, we want to
set the string part to, and then we can get
the FSM states, the one that we've cleared in
the initialized state here. And then we want to set the second element
to state in string. So this will save this
value to the FSM state, and we want to store the result back to
the FSM state string. This way, when we are
looping this FSM here, on the next iteration, the state in string
will be added after the previous value that been saved in the previous iteration. So now we can just
disable this at two N, for example, because we are not using separators, so we
can just uncheck this. And now that we are done here, let's add a finished transition. And let's go back
to the loop state. And basically, when
we are finished, we want to go to
another state here, and then we want to send the states to save manager. Or we can just call
it two manager. Okay, so now here
in the state here, we want to set an FSM string. And basically, we want to specify the safe
manager game object, so we can go to the
Globals, pick Safe manager. And here we want
to save the value, but this is something that
we haven't specified yet. So let's just save
the scene here, and let's go to
the Safe manager. And basically here
on the Safe Manager, we want to add the
mechanics to record states. So first, we want to create a new state to
record the states. I'm going to create
new one here, and let's just call this Cech entity name for
states because we already used this here and let's just
rename this two for transform because this is the one for recording the position. So we want to check the name
from the transform list. And here, we want to
create a new global event, and let's call
this record state. And let's set this
as a global event. Let's add a global transition here and pick the record state
that we've just created. And basically, we want
to add two transition, add and replace, similar to what we've done with
this record position. And here, basically, we
want to check if an array contains the name that
we are sending from the action that we've
created before. So let's just use the
array contains here. And basically, we want to create a new
variable in this case. So let's just create a
new entity's name states, for example, and let's
set this to an array, and this should be
a type of string. So let's just sorry. We can pick it right away here. We don't need to pick object, so let's just set
this to string. And then we want to check this array if it's contain the current entity
that we are recording. So we need to create this
variable also and this will be set from the action that we
are currently creating here. So going back to
the Safe manager. Let's just call the Oh, we already have the
variable current entity. So we are going to use
the same one that we are using here on
the record position. Okay. Now let's just pick
current entity here, and then we want
to grab the index, so we can pick the
current index, and we can use the same
variable because recording states and re position almost never happens
at the same time. So we can reuse the variable. And then we can just go to
a different states here. For adding, we want
to add a new entry, so we can just use
the array add action. The first one, we want to add the current entity name
into the name state. So let's just pick the current entity variable as the value and the array
entity's name state, and this will add the value if the current entity exists or doesn't contained in
the entity name state. And then we want to
add the data here. Let's just now we need to create another array of
strings that are going to save the active
stats FSM that we are saving. In order to do that, let's
just go to the variable tab here and pick array type, and we want to call this
NTT states, for example. This should be also
a type of string. Since we are passing
the states into a string to a value
of zero and one, and then we can just pick
the entity states data, and then we want to create a
new variable in this case, let's just call this
current states data. And now we have this. We want to add a finished transition, whenever it's finished, go
back to the safe state here. And for the other state, we want to replace the value. Here on the second state, we can use the array Set action, and here in the ray set action, we can just grab the
entity states data. And since we are checking if it's contains and
if it's contained, then we are saving the index, then we can use the index, which is in the current
index variable, and we want to set the value
to the current state data. Now let's just save this and then go back
to the first state. We going to rename the
state here at states data, and for the other one, we are going to rename this
to replace states data. Now we are done with
the record states. We can continue defining
the action here, and now we can send
the variable name, which is going to be the
I think it's let's check. It's the current state data
that we want to send here. So let's just sec here
and copy the name, and let's go back
to game object. And here we want to set the
variable name to this here, and we want to set the value
that we've built here, the FSM states, the one that we are building in
the build string here. And then we want to also set the name of the current entity that are currently
recording, for example. So let's just use
the set FSM string. The same goes with
the game object. We want to pick
the save manager. For the variable, it's called current entity because we want to send the
entity name here, and here we can pick
the entity name that we are saving in the
initialized state here. Now we have set up the data, the states data and
the entity name. Now we want to send
an event here. Let's just use the
send event action. And we need to specify
game object FSM, specify a game object, and then pick the safe
manager again here, and we can use the global
event record states. And then we want to add
the finished FSM states. Okay. So to make sure
that when we are sending, we already finished saving
or setting the FSM string, let's make this an
action sequence state, and this will make sure the
order of the execution of each actions are going to
be in this actions order. So let's save the scene. Now let's convert
this 28 template. And let's just call this action. Record entity states,
and we can use it. It doesn't really
matter, actually. And we can just delete this, and now we can use it. But before that, let's
create the it stats action.
24. 23 Load Entity State: And now let's create
the load action for the entity state here. I'm going to create
another anti game object, and let's create a new FSM
on this anti game object. And now let's set up the action that we
are going to create. So the first state,
let's just call this GT entities states. And basically here, we
want to get an FSM array. And we want to pick
the safe manager. And we want to get the
entities states array. And for the value variable, we need to create one here. Let's create an array of string. Let's just call
this the same name, so we are not confused. States data, and we will
also need to create another string of array that
will hold the entity's name. So let's just change
this to a string, and this will be
the states name. For a type, let's
set this to string. And basically, we
want to save this entity states data to
the entity states data. And let's check
the safe manager. Okay. Here, we have the
entity's name states. So we want to use this array. Let's just copy the name. And then go back to
this game object here, and we want to get
FSM array again. Pick the safe manager again. And then for the variable name, let's just paste
the variable name that I've copied earlier, and under the store value, we want to save it to
the state's name here. I don't think we need
to use copy values, so let's just uncheck
this and minimize this. And let's add a
finish transition. Go to a new state here, and we want to check
the state's data. And basically here on
the check states data, we want to check if the
array or the entities array that contains the name of the entities that are
sending this action. Let's just use the array contains And here we want to check the
entity states name, and we want to check against the variable that
we are going to create. Let's just call
this entity name. And for this entity name, we need to expose this. Let's just select the
variable and then expose via input checkbox. And we will also need to create another
array type of FSM. Let's just call this FSM list. And change the type
to object so we can select the
playmaker FSM type, and we want to also
expose this one here. And go back here.
We want to save the index if the entity name is found inside this
entity state name. Let's create a new
variable called index, and we want to create
two new event here. The first one will be load. The second one will be
not found, for example. Here, let's add the
load transition and the not found transition. A And basically,
if it's contained, then we want to go
to the load event, and if it's not contained, then we want to go to the not found, so we can debug this. And for the load, let's
just create a new state, and we want to
extract state data. And here inside the
extract states data, we want to use the
array get action, and we want to pick the
entity states data, and we want to get the
member from the index that we've grabbed when we are
checking this states data here. And then we want to save
this to a new variable, let's just call this
loaded states data. And then we want to reset the index value here because we are going to
reuse this variable. So let's just use a set
integer value action, and let's pick the index
variable and set this 20. And now let's add a
finished transition, and then we need to
go to a new states. And here, basically,
we want to process State data. Inside the state here, we want to get the length of the string that
we've extract here, the loaded states data because this is going
to be a string. Now we can use the
get string length, and let's grab the loaded
states data and we want to save the result into a new
variable called data length. And when we are finish
getting the string length, we want to add a
finished transition, and then now we want to
look through this string. So here, we can just call
this loop state data. And here, basically, we want
to use the loop action, and we look through an integer
that we are passing here, so we can use the data length, and this will look through how many character we have
on the loaded states data. And basically, we want to store the current loop
into an integer, which is index that
we've reset here. It starts from zero, and then we want to add
a custom event loop. Sorry, not load, but it should be transition event,
custom event loop. And at a finished transition. And for loop, we want to go
down here to a new state, and we want to set
the FSM state. So here, basically, we want to get the substring of our data. We can use the get
substring action, and then we want to get
the loaded states data. And then for the start index, we want to use the index
that we are currently looping and the length
one would be enough, so we want to only get one
character on the index, and now we can save
this result into a new variable called
current value, for example, and now we need to parse the
string into A B. So in order to do that, we need to use the
string compare. And here we need to put this
below the gat substring, and now we want to compare the current value. And
for the current value. We want to check if
the value is one, and we don't need the
equal and not equal event, so let's just leave this empty. And for the store result, we want to save this to
a new bleion variable. So let's just call
this ble state. And basically, if the
current value is one, then this will be true. Other than that,
it will be false, and we can use this
bleion state to enable or disable the
FSM from the FSM list. So here, we want to use the
array gt and basically, we want to get
from the FSM list. And for the index, we can use the same index that we are
currently looping because basically the index
will represent the states the FSM states
that were previously saved. So the index should be the same. And now when we are
getting the FSM list, we can save this into a new
variable called current FSM, for example, and this
will be the type of play makeer FSMS
you can see here. And now after we are
getting the array, we want to use the
set property action. And let's just pick
this one here. And then we want to set the property from
the current FSM here and pick the enabled state, and for the value, we want to use variable and then
pick the bull state. And this will enable
or disable depending on the Boulan state when
we are comparing here. So now that we are
finish setting the FSM, we can add a
finished transition, and then we can go back to the loop states here and
on the finish state, we can go to next state. Basically in this state here, we only want to finish this FSM, so it will finish running. And now that we have set up the no found,
we want to debug this. Let's just create a new state, and let's just
call this the bug. Inside this the bug here, we want to use the debug log. And for the log level, we can change this two warning and we can send a
text like entry or entity is not found in the saved states
that, for example. And then we can
enable the sent to Unit log so we can see
on the console here. At a finished transition, and then let's go to the
finished state here. Now let's save the scene and
we have this action set up. Let's check the variable, and we basically need
to make sure that this entity name and
FSM list is exposed. So we have done that. And now let's save
this as template, and I'm going to call
this action load, entity states We can just use it doesn't really
matter and we can bled this. Now we need to set up
the NPC dialogue here. Basically, we need
to create a new FSM. Let's just add a plan maker FSM. Let's just call
this record states, and let's add this here. In the record FSM, we need to create a
new string variable. And let's call this FSM name. And let's expose this
string variable. And go back to the state
here on this first state. We want to get the owner. So let's just use the
get owner action. And here we can save
this to a new variable. Let's just call this owner. And basically, we want
to get FSM array. And we can just use
the owner because basically we want to get this array of actions
here on the interactable, and we don't need
to set up the name. We can just search for
the variable name, and this will search
through all of the FSM in the owner in the same level
of this NPC dialogue, so it will check the
neighboring FSM. And then we want
to store this to a new array variable
that we need to create. So let's just create
an array variable, and let's just call
this FSM list. For the type, we want
to change this to object and then
select playmaker FSM. Here, we want to save
this to FSM list. And we don't need
to copy the value. So let's just uncheck that. And then we want to use
the get FSM component. And this is basically
an actions from ecosystem we have downloaded
in the previous video. If you can found this
get FSM component, you can just search
in the ecosystem. And basically, we
want to use owner. We want to pick
we want to select use owner in the game
object sections here field. And for the FSM name, we want to use this FSM
name, and for the result, we need to create a
new object variable, and let's just call
this this FSM. And for the type, this
needs to be playmaker FSM. And we want to save the FSM
to this FSM variable here. And basically, we want to
add this FSM that we've grabbed using the
Get FSM component to a global array variable, which is the entity saver
FSM, and Basically, every template FSM, either for recording states or recording transform
on initialized. On start, we need to save the FSM reference to
this entity saver array, and this is the
arrays that are being looped by the safe
manager whenever it wants to save something and the loader counterpart is being used when it's
going to load the data. So yeah, we need to save reference of the FSMs that
are going to be recorded. And now we can add
a new states here, and we can just
call the save here. And we can add a global
transition custom events, and we are going to use
the run action here. And basically here we
only want to run an FSM. So we can just do
that easily here. And for the template, we are going to select the
actions record entity states. And for the FSM list, we can just use
variable and then pass the FSM list that
we've grab here. And for the owner, we
can just send the owner, and we can save
the scene here and let's save this as a template, and let's just call this
template record states. We can use template here, and now basically
on this FSM name, the variable that we've exposed, we need to copy the
name of the FSM. And now we need to create
the load states template. Let's just add another
playmaker FSM, and let's just call
this load states, and similar to record
states template. We want to initialize
this first. We can just use the get owner
r to make things faster, we can just paste template here. Use the template record states, and now it is paste. Let's just delete these actions. And the start should move
to the state two here, and let's just call this in it. Now we have all of the
actions that we need, but instead of saving, we want to load here, and for loading, basically, we want to use the
actions entity states, and we need the
entity name here. So we can just convert
from the owner, and owner will be a game object, but we can convert this
value and it will be saved into the entity name. And here for the FSM list, we can just pick
the FSM list here, and this should work. And now that we
have set this up, let's save this as
a template also. And let's just call this
template load states, and let's save this
use the safe template, and then we can
copy this FSM name into this FSM name slots. Now we have set this up. Now let's take a look
and let's test this out. Here on the safe manager, let's zoom this a bit. Yeah, there's a couple of things that I forgot to set up here. And basically here on the tech entity name
for states here, we haven't set up
the contained and not contain event. So
we need to do that. And if it's contained,
we want to go to replace, and if
it's not contained, then we want to go to add, and this will make sure that the data are being saved
correctly in the array. And here on the save all data. Basically, we haven't saved the additional array that
we need to save load. So we need to change
this amount to five because we have two
new additional array, and this would be
the name states and the fourth or the fifth one should be
the entity states data. And this way we are
going to save all of the array that are being
processed in the record states. And the same goes with
the load from this here. We need to also change this
array variable amount, and we need to add the entity name states and
the entity states data. And this needs to be in the same order with
the safe actions. So if it's name transform,
position, rotation, name states and states data, then this should be also the same name transform
position rotation, name state, states data. So, we have fixed those and
now We need to also fix one other thing that I
did by mistake here on the load state template because we are pasting
from the safe states. In the initialized states here, I forgot to change the
array. Variable here. We should be adding
this FSM to the loader instead FSM because this is basically a template
two load state. So we need to put this FSM in
the loader FSM array list. So now we have fixed those
things and save this. And there is also one thing
that we forgot to set up here on the action load
entity states here. If we edit this, on the
loop state data here, we haven't set up the event. So we need to set
this two loop here, and if it's finished, we need
to go to the finish event. Now let's save the scene, and now let's save the project, and let's give this a try. So let's talk to this MPC here, It should give that's
great response. So let's just save. And
now let's stop the game, and then let's run this again, and now let's try to load it. It's loaded, and let's
talk to this MPC here. Okay. There you go.
It says that's great. Now if we try to create
a new safe here, And then let's talk to this NPC and it will go and then talk to
this person here, and let's just
respond to the other. Okay let's just save
this, and if we stop, and then if we run this again, we should be able to sorry, let's just stop and then load. We need to fix this bug
because it will always go to the last destination, but now we can just top the game first and we are going
to address this. Now let's press load here, and if we talk, it will
mention get well soon. So it will record the states of the conversation that
we have on an NPCs. Now we have implemented
the record transform and record states. The last thing that
we need to implement is the record inventory.
25. 24 Record Inventory: Hi. In this video,
we are going to implement the safe system
for the inventory, so we can keep track the changes in the inventory and we
can save it to this, and we can load all of those inventory in the next
session of the gameplay. So in order to do that, first, we will need to create a global array variables that will hold all of the items
available in the game. So now let's just create sory Here under the
new variable window, let's create new inventory
database variable. And this will be
a type of array. And the type will be the item. This is the custom variable
that we have defined, which is an item class. And we want to
populate this array with every item
available in this games. So I'm going to set
this 23, for example, under the projects
that and items, we should have these items. And we only have two so far, so I'm going to put two of them here and then set this
size to two for now. So basically, this is the item reference that we can look whenever we are loading later because basically
we can only save the grid data of the items. For example, if I
highlight an item here, we can only save this
grid string data. So we will keep track
what item that we have by saving this grid into a new array of string
in the safe manager. Okay, now we have created
this new variable. Let's select the save manager. And then under the
playmaker editor, we want to create a new
states to handle this. So basically, when we are finished looping
all of the entity FSM instead going to the
save all data state, we want to go to
another state first. And here, basically we
will save the inventory. So the next thing that
we want to do is we want to create a new variable. And let's just call
this inventory grids. Since we are going to save
this grids into this array, and let's pick an array, and for the type,
this can be a string. And now basically here
on the state here, we want to remove
or clear the array. So we want to use the
array remove all. And we are not using clear because clear
basically just clear the value on every entry, but it will keep the size
and remove all, basically, we'll delete all of the entry, and we'll make the array
size back to zero. So we want to do
that. Let's pick inventory guilt and we want
to clear inventory goods, for example, here we want to
add a finished transition. And then on the next stage. We want to loop our in array item for any item that
currently the player have, so we can use the
array get next here. And then we can pick the
global variable inventory, and we need to add a loop transition and
a finished transition. And let's rename the state
here to loop inventory. And for the loop event,
we want to go to the loop transition and the
same with finished event, we want to go to
the finished event. And we want to save
the resulting or the member the entry that we are getting to a single
variable of item. So let's just create
a new variable. And let's just call
this current item. And next, we want to go
to the loop state here. And when we are looping, we want to get its
grid and save it. So let's just call this
safe item grid and here, basically, we want to use
the get property action. And we can pick the
current item FSM, and then we can get the
grid and get the string. And let's just save
this to a new variable, and let's call this
current item grid. And then we want to
add this value to the inventory grid that
we are clearing here. So let's just use the array ad. And for the array, we can
pick the inventory grids, and for the value, we can
use the current item gods. Basically, this will
save the grid that we've retrieved from the current item and save this to the
array of string here. And when this finish, we want to go back
to loop inventory, and then once the
loop is finished, then we want to save
all of the data here. We want to go to
the save all data. And basically, we need
to add an entry here. And we want to save
the inventory grids to the safe file that we are saving using this
G and safe action. Now we have created
the safe mechanics. Next, we need to create
the load mechanics. And basically, we are going to do the same as save mechanics. But instead of getting
all of the items, we are going to parse all of the guids that we
load from the disc. So here in the load
from this state, we need to increase the array
variable amount to six, and then we want to
load the sixth member 115 to the inventory
g ray variable here. And this will load the string
of guids to this array, and then we can loop
this on a new state when we are finished looping
all of the loader FSM here. So instead of going
to the initialize, we want to go to a
new state first here, and we want to clear
previous inventory. And here, basically, we want
to use the array remove all, and we want to remove the inventory in the
global variable. So we want to clear
the inventory right now because we are going to look through
all of the goods, and we're going to re add those items from the safe
data into the inventory. So if we don't remove it, then we might have
double items as a bug as a resulting bug because we are not clearing
the inventory first. So now when we finish or
removing all of the inventory, we can go to a new state here. And then we want to look through the grids that we've saved. So we can call this loop grids, and here, as usual, we can use the array get next, and then we can pick the
inventory goods variable, and as usual, we need to add the loop and finish transition
for looping and array. And let's set the
event accordingly. And here we want to save the resulting to the
current item good. And when looking, we want to
go to another state here. And basically, we want to
look the item database here, and this is where we will need the inventory database on
the global variable here. So basically, we want to
add a ray get next again, and we want to look through the global inventory database, and we need to add the loop
and finish transition. So basically, this
is a nested loop. First, we are looping the gits and while we are
looping the gits, we are also looping
the item database here and set the
event accordingly. And then save the result to current item because this is going to be a type
of item class. And then when we look
both of this value, the g and the grids
and the item database, we want to compare the grids. Here, basically, we want to
rename this to compare GIDs, and then we want to use
the GT property action. Then we want to get the current
item and we want to get its grid and store the
grid to a new variable, and we cannot reuse the current item grid
because we want to compare this value with the
variable current item grid. Let's just call
this compare grid. Let's minimize this and let's
add the string com action. Here we can compare the current item grid that
we are evaluating here. With the grid that we are grabbing from the current
item from the item database. Let's use variable here, and then let's use the
compared guid and basically, we can reuse the event
that we have here. If it's equal, then we
want to add the item, so let's just use ad
and if it's not equal, then we want to use
the finish event here. Let's add both the add event
and finished transition. Now we have both
transitions added. When adding the item, we want to go to
a new state here, and then we want to
add item to inventory. Here, basically, we
want to only use the array add action. And then we want to pick the inventory array from
the Goble variables, and we want to add
the current item. Because when we are
getting the current item, here we are comparing the grid of the
current item that we are evaluating from the grid
and with the compared grid, which we retrieve from
the current item here. So if it's equal, then that is the item that
we are looking for. Hence, we can add the item
to our inventory here. Now let's just add a
finished transition. And when we finish here, we want to Go back to the
loop item database here. Here in the compared
grids, if it's finished, then it means it's not equal, then we want to go back to
the loop item database also. So we will check
for another entry. And then if the loop item
database is finished, we want to go back
to the loop goods. Basically, this
will look through the next goods and it
will do the same again. I will look through the item
database to find a match. And when we are finished
looping the goods, then we want to go to the new state where we are going to
refresh the inventory. Here, let's just call
this refresh inventory. Inside this refreshed
inventory state, we want to use the
send event action. And for the target, this is
going to be game object FSM, and we can specify
the game object here. We can select the variable, and under the globals, we can access the inventory
manager because we want to send the refresh event. Here under the
send global event, we should have the refreshed
inventory events exposed, and then this
should be all here. And here after its finished
refreshing the inventory, then we want to go back
to the initialized state. And let's save this. And
now let's test this out. So I'm going to press play. Okay, now it's running. Let's check our inventory. We don't we have a lighter. And now let's talk
to this person here. Okay, I don't want
to give my lighter. I want to instead of, I want to get the key
from this NPC here. Okay. Now we have this key here. Let's check our inventory. Okay. Yes, we have the key. Now let's save this. And
then let's stop the game, and let's play it again. And let's load the game and check our inventory.
And there you go. We have the lighter and our key loaded because basically when
we're starting a new game, for example, here, we should
have only the lighter. And if we check the safe, the JC safe data, let me just
open the file first here. We can see here, but
we need to parse this, so I'm going to copy all of this here and we'll open my browser, and let's open the
Json Lind website here and validate this. Now we should have a inventory
quids variable here, and we should have
the goods saved. And we can check this
because this is start with one F A 22 here,
let's just take a look. Basically on our
key or the lighter, yes, the lighter has that
grid, that correct grid. And sorry, not this one
here, but this one. The second one
start with 30 38f7. So if we check this, we should be able to
see it on our key. Yeah. K. Yeah, that
is basically how we save a inventory by utilizing the database
here and saving its gid. And that's why we are having
this grid value to make it easier to keep track
of things because this grid value is
going to be unique, and it has very small
chances that are generating the same exact
grid on two occasions. We can easily use this to
make a unique identifier.
26. 25 Audio and Animation Action: In this video, we
are going to create another interactable
action such as playing audio and playing
animations on NPC. But before we start to do that, let's pause this video, and I'll give you a challenge. Try to create the
actions yourself and let me know how it
goes in the QN A section. Okay, so now I'm going to show you how to create these actions. I hope you succeeded in your challenge on how
to create since we have been creating a lot of custom template and actions
in the previous lessons. So this one should be
very straightforward. Okay, so now, the first thing that we want to
try is we want to try to create an audio whenever we are
interacting with an NPC. So, for example, if we talk to this NPC dialogue person here, we want to play an audio. So first, let's go
to the scene here, and then let's add a new FSM. I'm going to create a
empty child game object. And this will be
the talking audio. And I'm going to
add a new FSM here. Opening the playmaker editor, let's create the Play
audio template FSM here. I'm going to rename this
to play Audio template. And I'm going to add a
audio clip variable, and this will be the Audio, and we can expose this. It's available in the Inspector. And here, let's create a new state and let's rename
this state to play Audio. And we can just add a global transition
from the custom event. Let's pick the run actions. And with this setup, we should be able to execute this FSM via the
interactable FSM. So here in the play audio state, let's add play sound action, and we have play audio
play and play sound. Basically, the difference
is that audio play requires an audio
source in the object, but play sound does not
require audio source, and it will create a temporary instance
when playing an audio, and then it will gets destroyed after the audio is being played. So I'm going to
use the play sound instead to make things simpler, but this sound is going
to be a treat sound, so it will be relative to the game object position,
which is what we wanted. And Another thing that
I want to do is I want to remove the audio
listener from the main camera, and instead, I'm going to put the audio listener on
the player game object. So all of the sound will be relative to the player position. Here. Okay. So now let's go back to the talking
audio, game object here, and here, let's just select to use Variable and pick
the Audio variable. And now we have created the FSM. Next, I want to convert
this to a template. So let's just pick
safe template, and I'm going to call
this template play Audio. And we can use the safe
template in this FSM here. And now we can just
pick any audio. So for this example, I'm going to use the
mail A dialogue here. And next, let's
create the template that plays custom
animations on an MPC. So in order to do that, let's just create another
empty game object here. And let's just call
this trigger animation. And here, let's add a new FSM on the trigger
animation scape object. And here we can
add a new states. And for the second state, let's just call this
play custom animation. And let's add a
global transition, custom event, and pi run action. And here we can use the
set animator trigger. But set animator
trigger requires a game object that have an animator component
attached to it. So in order to work
with this warning, we need to create
a new variable, a type of game object, and
let's just call this animator. And we want to expose
this so we can select the animator game object
easily via the inspector. And the other thing that we
need is a string variable, and this is going to be
the animator trigger. And we want to also expose this. So now we can set to specify game object here
under the game object, and then we can pick the variable that we've
implemented here, animator. And for the trigger, we want
to also use a variable, and this time we want to
pick animator trigger. So this should work, but we need to assign
this correctly. So first, we need to prepare an NPC model for this
NPC dialogue here. So the first thing that I want
to do is I want to remove the capsule component here
and also the mess render, And then let's just grab one of the character from
this TTD move folder, and under the prefep, I'm
going to grab the male A here. And let's put this as a child game object
of the NPC dialogue. And now let's set this 20 on
the y axis, it's rotations. And for the position, I'm going to set this
two negative one. So it aligns with the dialog
capsule collider there. And now we have this game object or this model attached to it. We can use this animator
as a trigger animation. So let's just drag
the game object to the animator slot here. And now we need to
use a controller. So I'm going to pick
P Controller here, and we can add a new
animations inside of it. So here inside the animator, when we are selecting this, we should be able to see
the P Controller animator, but right now we are inside
the idle walk plan tree. So let's go to the
base layer here, and we can create a new state. And for example, let's
call this state talking. And we can create
transition from the bland t or the default animation to the talking state. So let's make a transition, and we want to also
create a transition to go back from the talking to
the idle walk state here. So first, when we are
entering the talking, we want to trigger the state when certain parameters
is triggered. So in this case, we want to add a
trigger parameter, and let's just call this talk. And we can use this trigger to trigger the
talking animation. So with the transition
from the idle to walk to talking is selected. Here under the inspector, we should be able
to add a condition, and now we can select a couple of parameters
that we have created. In this case, we have speed, which is a type of float, and we have t which
is a type of trigger. In this case, I'm going
to use the trigger one, which is talk so we can
just select talk trigger. And we can disable the
has exit animations. So the transition will
occurs instantly, whenever we are whatever
state we are playing before. It will go to the talking
animation directly. And for the state or the transition from talking
to the idle walk state, we just want to use
the has exit time, and we don't need to
put any conditions. And in this case, this will let the talking animations
play until the end, and then it will go back to
the idle walk state here. So now we have this
trigger defined. We can go back to
the game view here, and under the
trigger animations, we can use the top trigger. So let's just type this, and this is case sensitive. So for example, if
we type it this way, then I need to make
sure that I also type it the same way down
to the capitalization. So let's just rename
this because I type it incorrectly before.
And let's save this. Okay. So the next
thing that we want to do is we want to
trigger this animation. So here on the interactable FSM, we can increase the
size of the actions, and then we can drag
the trigger animation. And this will always be triggered
because we don't change this FSM enable status since we are not adding this on the yes activate and
the activate FSM. So we don't change the
FSM activate status. And this worked well with
our intention because we want to make sure that every time we talk with this NPC, the NPC plays the animations. And we also need to trigger the talking audio, and
we haven't done that. So let's go back to
the NPC dialogue here and add more actions here, and we can drag the talking audio game object
to one of the slot here. Okay, let's save this. And now let's give this a try. Okay. Let's talk
to this NPC here. Could you be go home. Okay. So Could you be. I go jump. Shu k m f. Okay, there seems to be an
issue with the animations. Let's just inspect this
whenever we try to talk. Could you be jump Shook Op. So we need to fix this issue. Let's check this out. Here, if we select
the game object that has the people
controller animator, we can open the
animation window under the animation and pick the
animations, not the animator. And now if we duck
this below here, if we pick the other animations. We don't see it. Okay.
This is my mistake. I forgot to assign an animation. So here, let's just select the game object with the animator controller and
open the animator window. And I haven't set
anyimations in this. So by selecting
the talking state, we can we can assign a
motion in the inspector. Let's just press this button, and I'm going to pick the
male handshake animations. And if you have imported the every day motion pack
free from the asset store, you should be able to find these animations
in your project. Okay, so now let's go back to the game view here and
let's give this another try. Could you be. Jump Shook feet. It plays the
animations quite well, and it's synchronize also
with the audio playing. Could you be? I go jump. Shoot K O feet. Okay. So yeah, I hope you managed to do this template
actions by yourself. And if you manage to do it, then you should
be able to create any custom FSM that
can be triggered when a player is interacting
to a certain NPC or to a certain object even to
another object other than NPC, such as like a door or cabinet, for example, we can
trigger some animations.
27. 26 Camera Manager: Hi, in this video, we
are going to create a camera manager and
a camera switcher. So this camera manager will handle all of the
camera in our scene. It will receive registrations
from each of the camera, and then we can
create some sort of a trigger area to change camera when player
enters a certain area. So in order to do that, let's create a new
empty game object for the camera manager. Here on the scene, I'm going
to create a new empty, and let's call this
camera Manager. And we want to group all of this manager into one game
object under one game object. So let's create another
anti game object. Let's reset it, and let's
just call this managers, and I'm going to put
this game object on the top of this hierarchy. And I'm going to direct
the safe manager to become the child of
this manager game object. And the same goes with
the camera manager. I'm going to direct
this game object also to be the child of this
manager's game object. In this way, we will have a nicer or a much
organized scene here, and we know where to
search for our manager. So let's save the scene
here and I'm going to reset the transform of
this camera manager. You don't need to do
that. It's just I'm a bit obsessive compulsive
with these values. And now let's create the FSM
for this camera manager. So in order to do that, let's right click here
and add the new FSM, and we can just call this camera manager
as the name here. And then the first thing that we want to do is
we want to create a global game object variable to store reference to
this camera manager. So other game object can easily reference to the game object
of the camera manager. So let's just select
a variable type here, and then select game object, and let's just call
this camera manager. And now we have a
couple of manager. It's better to create
a category for it. So let's just create a new
category called Manager. Now as you can see, the camera manager Variable is under the manager category, and we can select
the other manager like Safe manager here, and now we can pick
a category here, and it will group the variable
in the same category. This makes things easier
to see or to navigate. And then I want to do the same with the inventory manager. And now let's also do the same
with the dialogue manager. Okay. So now we have organized the Manager Variable
game object. Let's save the scene again, and let's save the project
this time because we want to save this
global settings here. And now back to the
camera manager FSM. On the first state, let's
rename the state to initialize. And basically, this is for initializing the
camera manager here. And inside this
initialized state, basically, we just
want to get the owner. So this is too big.
Let's minimize this. Okay. And now we want to
use the get owner action. So let's type get owner. And then for the get owner,
we don't need the send event. I'm going to remove this.
And for the get owner, we want to store
the game object to the camera manager under
the global variable here. So let's just do that here. And now we need to
create a new state, and this is for
registering the camera. And we want to create a
new global event called ad and a local event
called register camera. And basically, we
want to make sure that we check this check
mark for the add event. Here, under the
registering camera, let's create a
global transition, and let's pick the ad event. Let's add a local transition
or a normal transition, and let's pick the
registered camera. And on the variables, we need to create a
couple of variables. So let's go to the
variable step here, and I'm going to create
an array variable. And this is going to
be called cameras, and this would be a
type of game object. Then we need to also create
two new game object variable, a single variable, so
as a pick game object, and this is going to
be the active camera. For the second one, we want to create a variable
called current camera. Okay. Now here back to the
registering camera state. We want to use the
array contains actions, basically, whenever we are Registering a camera, we
are going to set the camera that are registering as a
cur camera game object. And then we want to check if the cameras variable
or the cameras array, already have the current
camera as a member in it. So we need to use the
array contents here. So before adding a new cameras, we want to check if that camera is already inside
the cameras array. So here, let's just pick
the current camera, and if it's contained, we want to stay in the state, but if it's not contained, then we want to go to
the register camera, and we will need to
create a new state here. And basically on
this state here, we want to add the
camera to the array. Let's just rename
it to add camera. And we can use the
array add action. And for the array, let's just pick the cameras,
and for the value, we can just pass the current
camera game object variable. Basically here in the state, if the camera already have the current camera
that is registering, then we are going to prevent the camera to be added
to the cameras array, resulting duplicates
entry in the array. So this is to prevent
duplicate entries and The next thing
that we want to do is we want to
create a new state, and the state is for
switching the camera. So let's just call
this loop state. And how this switching
camera works is basically, we want to disable all of the camera inside
the cameras array. And when we are
finished looping all of those camera and
disabling those camera, we want to go to
the finished state and then to a new state, and we want to activate
the active camera. The only one camera that should be active when
switching the camera. So here we need to create
a new global event. Let's create one, and let's
just call this switch camera. And make this a global event. And then here on the
loop state here, we want to add a global
transition switch camera. Then we need to add
a loop transition, so let's create
local transitions, and we can use custom event, and we can search for loop. Because we have created
this event on other FSM, so we can access it via
the custom event menu. And we want to also add a
finish transition here. And basically, for looping, we are going to use the
array get next as usual. And we can just pick
the cameras here. And for the looping, let's just pick loop here for
the finish event, we can select finished. And then we can just create a new state from loop here
and back to the loop state, we want to save the Caron camera into a
game object variable, so we can use the
current camera again. And here, basically, we want to deactivate the current camera. Here, let's just create a check first if the
game object isle, so we can use the
game object is null, and we want to check if the
cin camera is null or not. And we want to add a
finished transition here. And basically, we want to intercept if the
current camera is, then we want to fire
the finish event right away without going
to the neck action here. And then the next thing that we want to do is we want to use the activate game object action. And here, we want to
specify game object, then we want to pick
the cin camera, and we want to deactivate it, and we want to disable the recursive, because
we don't need this. And basically, this
will automatically disable the current cameras or the camera selected in this loop iterations in the
current loop iteration. And then we want to make
sure that this activate game object is below the
game object is no action. So let's just put this here, and let's minimize
both of this action. And now let's fire the finish
back to the loop state. So let's just rename this
the activate camera. And then upon
finishing the loop, then we want to go
to a new state, and then we want to
activate selected camera. Here, basically, we just want to use the game object
action again. But this time we want to
pick the active camera. And then we want to activate it. So let's just disable recursive and keep the activate checked. Now we have created
the camera manager. Let's create the FSM for each
of the camera in our scene. So basically on each of
the camera in our scene, we want to create an FSM that will register itself
to the camera manager. So Here under the main camera, let's create a new FSM, and inside this FSM here, we basically just want
to get the owner. Let's just use get Owner, and then we want to
store to a new variable. Let's just call this camera. And then we want to set
an FSM game object. In this case, we want
to set the camera FSM game object variable
called current camera. So let's just use the
set FSM game object. And then we want to pick the camera manager game object
from the global variable. And for the variable name, we know that it is cur camera. And we need to make sure that the writing is correct down
to the capitalization. And then we want
to set this value to the variable that
we've grabbed before. And once we send the value here to this current
camera variable, we want to send an event. We're just going to
be the Ad event. Let's just use this SN event. And let's make sure that
this sN event is below the set FSM game
object action and pick game object FSM as the target
and specify game object, and now we can select
the camera manager. And here we want to send
the global event called Ad. Now basically we are done with the camera FSM for the camera to register itself
to the camera manager. Now we can save
this as a template, so let's just save
template here. Let's just call this
template register camera, and we can use it here. Now to set up this, let's create another camera from this position, for example. I'm going to create
a new camera here, create a new camera, and I'm going to set the future this position
here by selecting this camera and then
hold Control Shift F. This will move this camera to this
position, as you can see. And now we have two
camera in our scene. The first one is this one, and the second one is this one. Okay Let's just adjust
the position slightly, much more closer to where
our characters are, and let's rotate this a bit. Basically, this is
the main camera, and let's set the tag
to main camera also. Now we want to put the camera
near each other or better, yet we can just
group them later. Now for the second camera, we want to create a new FSM, but we want to use the
FSM template that we have just created which the
template register camera. Now this should work
with the camera manager, and the next thing
that we want to create is we want to
create the trigger area. Let's just move the player out of this area here and put it here as the
starting position. Then we want to create a new empty game object
as the trigger area. Let's just create an
empty here and I'm going to add a box collideer. For this box collider, let's make the size to three on the x and three on the z and
three on the y, for example. I think this is still too small, so let's make it even bigger five by five on the
x and the z xs, and I'm going to keep the y23, and I'm going to
reset its position. And here, let's
move this and put it around this area here
near this police officer, for example, and let's
enable the trigger option. Basically to make the collider
works with the player, one of them needs to
have a rigid body. So in order to do that, instead of adding rigid body
to each of the trigger area, I'm going to add a rigid
body to the player. But I'm going to make sure that the rigid body is
set to is kinematic. Let's just check this
is kinematic here. And we can just disable
the use gravity, and this will make sure that this rigid body is
not going to be included in the physics or dynamic object calculations
in the scene here. So it will act like
just a static or an animated or pre
animated object instead of getting the motions or the animations from the
dynamic simulation. Now we can just
minimize this here. Let's save the scene again, and now go back to
the trigger area, and let's just call this camera trigger
zone, for example. And for this camera
trigger zone, we want to create a new FSM. Let's just right click here
and add a new FSM here. And for this FSM, basically, we want to
create two states. But let's just focus on
creating the first state here. And basically, we want to use
the trigger event action, and let's just search for
the trigger event actions. And here, basically, when we want to use the trigger enter
as the trigger mode here, and for the collider tag, we can just pick the player, and we want to send an event, a custom event that we
need to create first, so let's just go to the event, and let's just
create enter event. And then we want to create
the exit event here. And basically, we want
to add enter transition, and we want to use that. And basically, on this
first state here, we want to set FSM game
object to the camera manager. So let's just use
set FSM game object. And we want to send
a enter camera. So for the camera
when the player is entering and to do this, let's go to the variable, and I'm going to create two new game object variable and let's just call the
first one camera on enter, and let's enable
the input so we can access this easily
via the inspector. And then let's create
another game object, and let's call this
one camera on Exit. And we want to also enable
the input checked here. And going back to
the state here. Let's use the variable. Let's use the variable
as a set value here. And this is for the camera on exit because basically
when we enter the state, we are going to enter the state from a state where we
are exiting the trigger. So here for the variable name, we should type active camera, and this is the variable that we have defined in the
camera manager. And now we want to specify game object here and then pick
the global camera manager. And then we want
to send an event. And for the send event, we want to specify game object
FSM has the event target, specify game object
and then pick the globals camera manager, and we want to send the
switch event switch camera event and make sure that the send event is executed
after the set FSM. Now we have set this up. Let's just duplicate
this state here, and then we change
the transition target to the transition
event to exit here. And then for the trigger event, we want to change the
trigger to trigger exit and send the event
to the exit state here. And basically on the set
FSM game object here, we want to set the value
for on camera enter, and why we are choosing
the camera enter. Because whenever
we are triggering the trigger method here, whenever the player
enters the trigger, we are sending the enter event, and when we are going
to the next state, we want to activate the camera on game object or
the camera that we have set up as the camera
when entering the triggers. We have set this
camera on enter. Let's check the send event here. Yeah. We don't need to
change anything here. And basically, now we need
to connect this state here. Let's just connect the enter to the second state and
exit to the first state. Now we have set up this
trigger zone here. I'm going to save
this as a template, so we can easily use this
template for other game object, and let's just call
this camera switcher, and let's just use
the save template. And basically here,
let's save the scene. On this camera trigger zone. On the variable, we
want to set the camera on to be the second camera here. Let's just direct
the second camera. And when we are
exiting the trigger, we want to go back to the
first main camera here. And now let's save this, and let's give this a try. So sorry, there is one thing
that we need to do here. Basically, we need to disable the second camera on the scene, so let's just disable this. And this we'll make sure
that the scene will start with the default
the first camera. So after disableling
the second camera, there is also one thing that
we need to change here. Basically, this is for delaying the registrations by one frame here in the template
register camera. So if we open the
template register camera, we can add a next frame event. And basically, this
will make sure that this initialization of
registering the camera will happens on the next frame once the camera manager is ready or has been initialized by
the camera manager here. Otherwise, there might be
a race conditions where the registered camera
tries to run when the camera manager is not yet ready or is
not available yet. But this is just a
temporary solution. And later, once we implement the additive scene loading
and stuff to load the levels, we won't be needing
this next frame event. So yeah, let's just add this for now to the template register
camera, put it on top, and then make sure on
the state settings here, on the gearbox button here
enable the action sequence. So this will make sure that the stack will run in sequence. Okay. So the other
thing that we need to do is that we need
to select the player, and we need to make sure
that the player has the tag of player because right now the camera trigger zone
relies on the player tag. So let's make sure that the
player is tagged correctly, and now let's save the scene. And let's select the camera manager,
just to the buck here. I'm going to open the variables
window and select the camera array game object
variable, and let's play this. And here, on start,
as you can see, the main camera gets
registered and it become one of the entry of the camera's
array on the camera manager. And the other camera
is not yet registered because it's still
deactivated as of now. So let's just give this try. And let's go to this area here. And now as you can see the camera switch to the second one. And once the second
camera gets activated, it gets registered to the
camera manager right now. Now the camera has two
camera member in it, and if we exit the area, we'll go back to
the main camera, and this will make
it easier to set up a different camera
view on a different area.
28. 27 Switch Scene FSM: In this video, we
are going to create a custom template
to switch a scene, and we are going to use
an additive mode of loading a scene so we can load a scene on top
of a previous scene. So for example, sample
scene is going to be the main scene where
we have the player, the lighting, the managers, and other stuff that needs to stay all the
time in the game. It's going to be inside
this sample scene, and probably we are going to rename this two
main scene later. And then the scene, the places are going to
be on a separate scene, like the CD, the club Holloway, the office, the park
and everything. Before we start, let's create those new
scene or sub scene. I'm going to go to the scenes folder and I'm going to
create a subfolder here. And let's just call
this sub scenes. Inside this folder, let's
create two new scenes. First one will be the CD scene, and let's create another scene, which is going to be
the club hallway scene. Here, let's open the
City scene here. And I'm going to check to open the Club Hallway because I
was having issues when I saved a scene with
Club Hallway as a name for unknown reasons,
so I'm going to check. It seems just to
work fine because I can see the main camera in
directional light here. So I'm going to go back to
open the CD scene here. And if we have already
imported all of the assets in the setup lessons or the
introductions video, we should have this
point and click folder, and then we should have
the prefex folder. And inside the prefex, we should have all of the scene
needed in this game here. So for the CD scene, I'm going to drag the
CD game object here. And basically, I'm going to remove the
directional light here. And I'm going to reposition the camera to be around
this position here. Okay. And then I'm going to add a knife mesh in this scene here because if we open the
navigation window here, as you can see
here, we don't have the navigation mash
baked yet here. So let's just bake before that. Let's check our CD game object. And basically, the prefabs
when I've set up this, it sh already have the
static checkmark checked. And the same goes with
the child object here. And here we already have the box collider for
the clicking part. Let's make sure that this
layer is set up to ground, so we can click on it
and the player can move around when we are
clicking the ground collider. Okay, now let's go back to
the navigation tab here, and under the Bak tab, let's press the bake button, and this will pick a new
navigation mesh here. Okay, now we have
set up the CDC. Let's save this, and now
let's open the other scene, which is the club hallway scene. So I'm going to open the
cub hallway here and go back to the Point click
folder, prefab folder. Let's drag the club hallway, and let's delete the
directional light game object. And now let's adjust
the camera position. So I'm going to get the view that I want in
the scene view here. And once we have the angle, the position and the angle of the camera that we want,
the view that we want, we can select the main
camera game object and then hold control shift F, and this will automatically snap the camera to the same
position as our view, as you can see in
our game view here. And now in this prefabs, I haven't set up the
ground collider, so let's just create a
new empty game object, and let's just rename
this two ground collider. And let's add a box collider
that we can click later and here from the top view and then autographic view by
pressing the middle cube here. I'm going to adjust
the collide size by pressing this edit
collider button, and then let's just direct
the points here so we can adjust the collider to fit
the size of the ground. Okay. So I think this is enough, and let's make the y size 20.05. So it's very small. And if we go to the
side view here, let's align the collider, so it aligns nicely
with the ground here. Okay. So we have set up
the ground collider. Let's change its
layer to ground. And now the same
goes with the city. The club hallway pre static
options have been checked so we can go to the
navigation tab directly, and then under the big tab, we can press the big button. This will bake a navigation
mesh for this scene here. And let's save the club hallway. Okay. Now we have
set up club away and CD just to test this
scene switching template. Let's open the CD scene. But before that, if
you are wondering where we can open
this navigation tab, if you don't have
it on your editor, you can go to the window AI and then pick this navigation. This will open this
navigation tab. If it's floating, you can
direct the name and you can dock it into a
panel of your choosing. Okay. Now let's go back to
the main sample scene here. Here in the sample scene, we want to hide a
couple of things. Basically, we want to
hide the environment, the dialogue, the NPC, all of the NPC here, and let's
just hide the camera here, and then let's hide the
camera trigger zone also. We don't want this trigger to
trigger camera changes for now because we want to test
this switch scene action. Let's just hide
all of this here. We can save the scene. Now let's set up
the CD scene here, but we can just load the CD additively on top of
the sample scene. If we go to the subcene here, we can just drag our
scene and put it here, and this will load the scene on top of our previous scene, and we can still modify
all of the object on the sub scene or the
additive loaded scene and the base scene here, and we can save each of
the scene separately. Here, for example, I can create a new empty game object by clicking on the scene
name and then right click and then go to the game
object menu here and I can create an empty and this will create a game object
inside the scene here. And I'm going to rename
these two interactables. This is going to be the
group of interactables, in this city scene here, and now I'm going to create
another anti game object, and this will be the
side door interaction. Now let's reposition this
side door interactions, and I'm going to make sure that this object is on
this door here. And another thing that I
want to make sure that the Pipot sets to
local or the transform set to local and rotate
this on the green axis or the y axis so that the z axis is pointing
outwards that way. And this will be the
stopping direction and distance when the player
interact with the door. The next thing that
we want to add is we want to add
a box collider. And let's set the
layer to interactable, and let's adjust its size. So I'm going to use the
edit collider button again and probably make it thinner
and increase the size, so it covers the
size of the box, and I'm going to
make it a bit wider. Okay. I'm going to move this
slightly forward here and push the back side two forward, so we have a thinner door there. And yeah, I think
they should do. The next thing that we want to do is we want to add an FSM. So let's just type FSM, and we want to add the
playmaker FSM here. And here we can
pick the template, which is the interactable
template here, and let's increase the
size 21 because we want to assign the neck FSM
that we are going to add. So here let's add another FSM, and this is going to be our
sin switching FSM here. So with this selected, let's go to the playmaker
editor here and By default, it's showing the top FSM. In order to edit this,
we can just press this edit button
here and it will open the second FSM here. Here in the first state, we
don't want to do anything, and we want to add a state here. This second state, we want
to add a global transition and we can pick custom
event run action. This way, this FSM can be run by the
interactable FSM here. Let's just call this switch
scene for state here, and we want to create a string variable
called target scene. This is the target scene
that are going to be load whenever the player interacts with this interactable object, and we want to also
expose this variable. So let's check the input
options so we can type it here. And then we want to create
another string variable, and this is going to
be the current scene. That is loaded, then we
can unload the scene here. And here inside the
switch scene state, we can add a action
called get scene name. And then we can save the name to the current scene variable that we've
just created. But for the scene reference, we want to get not
the active scene, but we want to get the
scene by the game object. So basically, this will get the scene where the
game objects reside. Instead of getting
the sample scene, it will get the CD scene, and it will save
the reference of the CT scene to this
current scene string. So it will get the
name of the scene. And let's save the
scene now and go back to the side door
interaction here. If we select active scene, then this will pick the
basin loaded in our scene, which is the sample scene,
and we don't want to do that. Make sure we change this
to scene by game object, use owner, and then store
it to a current scene. Then we want to use the load scene
asynchronous here, a sin. And then we want to use scene by name and then for
the scene by name here, we can use variable and then we can pick the target scene. Here, let's set the load
scene mode to additive, so it will load the scene on top of the basin or the main scene, and let's allow
scene activation. This will automatically
load the scene when the progress of the
scene loading is done. Otherwise, we can help the scene activations and
probably add an input, press space bar to start, then we activate
the scene that can be also achieved
using these options. These options is there to Change or to make
those behavior. Okay. Now we have
set this up here. There are no other things
that we need to set up, so let's just minimize this. Next, let's use the
unload sync asynchronous. And this time, let's put this unload sin below
the load scene. And here we want to use the
same name also scene by name, and then we want to
pick the current scene. And that will be all for the
unload scene asynchronous. And here, let's enable
action sequence here on the gear cog settings and
enable action sequence. So this will make sure that
the actions run in sequence. After this one is finished,
go to the next one, and then when this is finished,
we go to the next one. Now we have set this up. Let's save this as a template. And let's just call this
template, switch scene. And we can use the
safe template here. Now we need to modify
the camera manager. And basically, whenever we
are switching the scene, we want to clear all of the cameras that are registered
in the camera manager. So in order to do that, let's go to the managers here and
under the camera manager. Let's create a new state
to delete the camera. So I'm going to create
a new state here, and let's just call this
delete all cameras. And let's create a
new event to do this. So let's just call
this delete cameras. And let's make sure that this
event is a global event. So I'm going to check this here, and let's add a
global transition, and then we can use the
delete cameras event here. Basically, we want to
delete or we want to clear the array values of
the cameras array here. Here inside the delete
all cameras state, we can search for
array, remove all. And then here we can just
select the cameras array here. And now we have this setup. Let's go back to the side
door interactions here. Let's edit the template here. And basically, when we
are switching the scene, let's clear the camera also. In order to do that, we're going to use the send evan action. And let's put the send event on top of the stack
here in the state, and let's pick the
game object FSM. We can specify game object here. And let's use variable here. Then we can go to
the global variable and pick camera manager. And then we want to send the global event
called delete Cameras. And this will automatically trigger the event on
the camera manager. Okay. So now we are done with the switch scene
template set up here. The next thing that we
want to do is we want to also set up a interact, a scene switch intractable
on the club hallway. So in order to do that, let's drag our club hallway
into this sample scene here. Now we should be able to
see our club hallway, but it is positioned
incorrectly here. So in order to fix this, we need to move all of the object inside the
club hallway scene, so it's aligned with
this blue building here. In order to do that, I'm going to go to the top view here, and then I'm going to create
a new empty game object. And I'm going to put
the main camera and the club Hallway game object as a child of this ti game object. And now I can move around the ti game object to move the main camera and the
club hallway object. And basically, what I want to do is that I want to rotate
this by 60 degrees, so I'm holding control
now while rotating. And then I want to make
sure that this part here where we have the
door for the club hallway, aligned with the door
of this building. We want to add an offset, of course, so let me
just reposition this. And probably we want to make it around this position
because we want to make sure that whenever the player interact with the outdoor or
this side door interactions, when the player stops
in this position, then we load the club hallway, we want to set that the player is already
inside the building. And vice versa, when
the player exit the club hallway and then interact with this
door, for example, we want to make sure
that the player is top in this position, so it's already outside
of the building, when the player is going
to enter the CT scene. So I think this is
a good position. And now we can just drag
the main Cameron club hallway back outside from the game object that
we have just created. And now we can reuse
this game object as a interactable for the door interactables
of the club hallway. So with this one here, I'm going to reset
its rotations. I'm going to leave its position. And let's just rename
these two interactables. And basically, this will
be a group that will hold all of the objects that are interactable inside
the club hallway. And here I'm going to add
another empty game object, and I'm going to move
this empty game object. So it aligns with the door
from the club hallway. And let's rotate this on
the y axis. By 90 degrees. So we make sure that the z
direction is facing inward. And then we want to make sure that this lies on the
middle of the door here. And now let's add
a box collider. And we want to also make this object layer
as an interactable. So let's just select that layer. And now let's adjust the size
of this interactable here. I'm going to Make it wider. Let's just re edit this, and let's make the
collider slightly wider. So it fits the sides
of the door here and also make the height higher, so it fits with the door here. Basically, we can
just move this so it aligns with the front
side of this door here. And I think the should be okay. And basically, with
this interactable, we can just call this exit
interaction, for example. And here we can add
a playmaker FSM, and this is for the
interactable FSM. So let's just pick a template here and then pick the
template interactable. We can increase the action size, and we want to create
another playmaker FSM. And this one, we can just pick the newly
created template, which is the template
switch scene here. And then we can wreck this FSM as the actions
of the interactable. And for the target scene, we can just type this CD
because we want to make sure that when player is
interacting with this door, we should go to the CT scene. Okay. So now let's
save this scene here. There is also one
thing that we want to change here inside
the player FSM. If we go to the
playmaker editor here, we want to make
sure that whenever we are sending the event, we can just remove
the name here, so it will send to the FSM
that has interacted event. We don't have to type
the name correctly. Because, for example, here, in the CD scene here. If we don't rename
this two interactable, then this won't work when
we still have the FSM name. So I'm going just
to clear this out, so it won't detect the FSM name, but it will search
for an FSM that has an interacted event. Okay. So let's save
the scene here. And now we've done set
up the club hallway. Another thing that
we want to set up is that here on the side door
interactions of the City, we want to direct
the playmaker FSM, so it become the actions on the interactable
component here. And we want to also type the name of the
target scene here, which is club hallway. Let's just type clap
hallway and make sure that the capitalization is
also correct based on our scene that we have saved, and here let's just
save the scene here. I'm going to remove the
clap hallway scene, but I'm going to
keep the CD scene here just for testing right now. Before we test this,
we need to add our scene in the scene list
of our build settings. In order to do that, we can
just open the file here, go to the build settings, and let's add the scene
from our project. First, we want to add
the sample scene here, and then inside the sub scene, we want to add the CD scene and also the Clap hallway scene. And when we are
adding the scene, we want to save our project, so these settings get safe. Let's just go to the file, and then pick safe project. Okay. Now we can test this. So I'm going to
run the game here. Okay. So now let's just try to interact
with the door here. We should be able
to go there you go. Now we are inside
the club hallway, and if we interact
with this door, we should be able to
go back to the city. And as you can see here, the objects are facing or aligning nicely in the
interaction position. So for example, if I go
back to the club hallway, we will enter the club, and that is why we need to align those scene objects
in the sample scene, so everything aligns better. So pe conclude with the
scene switch lessons, and we are going to
continue in the next video.
29. 28 Door Swing and Transparent Wall: Hi, in this video,
we are going to continue working on
the club hallway, and we want to create a
swinging door so the player can go inside and outside of the
room in the club hallway, and we want to also
make sure that when the player is
inside the room, we want to render the wall
and door transparent. So we want to switch material
when the player enters, and we want to revert the material when the player
goes outside of the room. Before that, let's just
here on our sample scene. I'm going to disable
the CD scene. And here we can just pick
unload scene in the menu here, and this will hide the CD scene. And basically, I want to
delete this navigation mass. So here on my naviigation panel, I'm going to go to
the baked tab here, and I'm going to press clear. This will clear, and we can reopen or we can
reload the CD scene here. And I want to also save
the sample scene here. So now let's go to
the subscene folder, and let's open the
club hallway scene. Here in our clap hallway scene, we also need to fix
our nafigation mesh. So let's just clear this
and then rebake it, and this will create
a new naviigation mesh on our scene here. And I'm going to change
the agent radius to 0.35. So we have like a smaller
radius for our agent. Thus, this will
make the navigation mesh larger than what
we have right now. So let's just press bake again, and this will change
the navigation mess. And the next thing
that we want to do is we want to create
a swinging door. So in order to do that, We can select the door here. And basically, once
the door is selected, we can see that the objects are expanded in the hierarchy. We want to pick the pivot here, and then we can change
the view to the top view, and I have disabled
the perspective view here with the pivot selected
under the inspector, let's add a rigid body. And for the rigid body, we want to disable use gravity so the object will
stay in its place. It doesn't falls down. And we want to also
add a hinge joint. For the hin joint,
we want to change the axis to 01 and zero. So basically, we
want to only affect the y angle as the axis
for the hinge joint. So the door can swing with
the rotations in y axis. And we want to also
use the spring. For the spring, I've
tested the value. You can change this
to your liking, but this value 20
for the spring, Damper five works
well on my case. And then we want to also
set the limits here. For setting the limits, we can enable this added
angular limits button, and you can see that we
have this red gizmo, and this dictates the
rotation range of our door. Right now, the door cannot
rotate at all because it sets 20 on the minimum
and the maximum. I'm going to change this to
negative 90 for the minimum, and for the maximum, I'm going to set this 290. We will also need to
enable the use limit, so I'm going to press this. Now, you can see that
the door will be able to swing up to this line here
and also to this line here. It will be able to
swing both ways when the player enters or
going outside from the room. So that will be all for setting at the rigid body
and the hinge joint. Now let's just create a box collider for
the door game object, so the player can
collide with it. The default fitting of this
box collider is actually quite spot on because
we are creating the box collider on top
of the mesh render. So the collider can
detect the mesh object, and it will create a collider that fits the three D model. And we don't need to add rigid
body component anymore on this game object
because the rigid body is being handled on the pivot, and the parent game object will detect the collider
of the child object, and it will consider that collider as one object
with the pivot. So it will consider
that collider as its own collider for
this pivot game object. So now we have set up the door. I'm going just to copy the
hinge joint component here. And then I'm going to paste this to the same pivot game
object on the security door. So here let's just
add a rigid body. Let's disable use gravity, and then we want to right
click here on the rigid body, and we want to paste
component as new, and this will paste a
new hinge join with the same settings that we
have on our door here. Okay, so now we have this setup. Another thing that we
want to do is we want to add a box collider to
the security door here. So let's just add
that component. Box collider. And then pick that one. So now, basically, we are done with the
swinging door setup. Next, let's create
the FSMs to switch the wall and the door to a transparent material when
the player enters the room. So I'm going to save the
club llway scene first. Here from the top view, I'm going to select
the toilet wall here, and I want to create
a new box collider. And this box collider, I want to increase the size
because this is very thin. It fits to the wall. So let's just change some
value here in the inspector, like the Z value or the
x value, for example. Oh, sorry. I'm going
to change the size, the size or the X size. Yeah. And now let's make
this box coll fits the room. So let's just drag this by
enable the added collier here, and we can drag this nodes. And let's make this box
coll the size of the room. So I think this should do, and let's enable the
e trigger option. We want to also do this to the other security
room wall here. So let's just do the
same. At a box collider. I'm going to change
the excise so we can see the box collider. And let's press this
added collider button, and let's drag one
of this point here, so it fits the room. And let's just the
front facing here. And let's also enable
the trigger option. So now we have this setup here. We can apply this
setting to the prefabs. So by selecting the
root game object under the override tabs here, we can press apply all. And then let's save the
club hallway scene again, and let's select the
toilet wall again. Here, we want to
create a new FSM. So let's just add a new FSM
under the playmaker tab here. And then we want to initialize
the material first. So in order to do that, we need to create a
couple of variable. First, I'm going to
create a variable array, and this is going to
be the renderers. And for the type, let's change this
two game object. And let's enable the
input options here. And then we want to also
create a material variable. And this is going to be the transparent material
that we are going to use whenever we are changing the material of
the wall and the door. And we want to also enable
the input checked here, so it's visible
on the inspector. And the other thing
that we want to create is a array of material. So let's just create
an array variable, and this is going to be
the original materials. And for the type, I'm going
to change this to material. And we don't need to
expose this material. So now we can start
creating our FSM. Here on the first state, I'm going to rename this state to safe
original materials. And here inside this loop here, Use the array, get next action. And we want to loop through
all of the renderers array. So let's just sick
the renders variable. And then we want to add a
custom event called loop here. And we want to set that loop
event to the transition, and another transition
is going to be finished. And for the finish, we want to send this to
the finish event. And we want to catch the result or the member that we are
looping to a new variable. Let's just create a
new variable here, and let's call this
current render. This will save the game object
into this variable here. And then when looping here, we want to get the material and save it to the
original material array. Let's just call
this get material. And for this action, we want to use the
get material action. And we want to pick the
cur render game object. So let's just use variable
here and pick corn render. And for the material, we want to save this
to a new variable, and we can call
this corn material. And then we want to save that current
material to an array. So use ray add action. And basically, we want to add the material to the
original materials. I We need to add the car material to the
original materials. And this will make sure that the original materials
will have a list of material that is
the same order as our renderers array order. Now let's add a finished
transition here, and let's connect this back to the safe original materials. Once it's finished, we want
to go to a new state here, and we can just call this player outside
because by default, the player will be
outside of the room, and let's add a new transition, but we need to create
the event first. I'm going to create a new
event called player in. Y And then I'm going to add another
event called player out. And here I want to add
the player in transition. And basically, when we are in, we want to change the material to the
transparent material. So here we need to loop through the renderers array again. So let's just use
the array get next, and we want to loop through the renderer add a
loop transition, and then a finished transition and set this event accordingly. And we can call
this loop renderer. For loop, we want to assign the transparent
material to the game object. Here we need to save
the result and we can use the current
render variable here, and here we want to
set a material to the render game object. Let's just use set material. Pick specified game object, and then we can select
the cron render, and for the material, we can pick the
transparent material. And let's just add a finished transition here and look back to
the loop render. And when it's finished, we want to go to
the new state here, and we can call
this player inside. And basically, when it's inside, we want to add a
player out transition, and then we want to
go to a new state. But instead of going
to a new state, we can just duplicate
the state here. By pressing control C
and then Control V. Then we want to connect
this player out to this loop render state here. And basically, this is
all already been set up. But here, we want to
get the material from the original material
array for so let's just use the array get action. And for the array get action, we want to pick the
original materials, but we need to pass
an index here. Here in the loop render state, let's save the current
index instead. So I'm going to add
a new variable, and let's just call
this current index. And here, we can use that current index as the index for this
array get actions, and we can start the value
to the current material. And now we want to set the current render
game object material back to the current material or the material that we get from the original materials here. So let's just pick
current material here, and when it's finished here, we want to go back
to the state here. And now basically here on
this player outside state, we want to use a trigger event. And for the trigger event, we want to check for
a player tag here. And then we want to send
the event player in. So whenever the player
enters this collider, we want to send the
player in event, and it will change all of the game object material
to a transparent material. And here, we want to
also use trigger event. But instead of using
the trigger enter, we want to change this
to trigger exit and pick the player tag and
then send the player out. So this shot works. And right now, I want to
save this as a template, so I'm going to right click
here and then save template. And we can call this
template switch, transparent material. And we can use the safe
template in this FSM. So let's just press yes here. And now, basically, on
this game object here, we can set the render size and set the transparent material to a material that we
have in our project, and this is the material the
transparent material here. So let's just pick
this one here. And for the render game
object, basically, we want to hide the wall itself and the door
game object here. And this toilet door doesn't
have any measure render. It is just an anti game object
that halts the pivot here. So basically, we only need to assign the toilet
wall and the door. And the same goes to the
security room wall here. So let's just add a FSM. And here, let's just pick
the newly created template switched transparent
material and set the renderer size to chew, and we can drag the
security wall here and game object here and set the same for the
transparent material. So here, let's just
apply the prefabs again. On the overwrite tabs here. I'm going to press apply all and save the
club hallway scene. To test this, let's
open the sample scene. And let's load the CD scene as the additive scene
here just for testing. And now we can run the game. I'm going to make
this slightly bigger. Okay. So let's go
to this door here, and this will load the club hallway scene
here, as you can see. And now let's enter the room. And now when we enter the room, you can see that the wall and the door change to a
transparent material. And if we go outside, it will switch back to
the solid material there. So, yeah, we have this working very nicely
this action where we can switch the material of a wall when it
occludes the player. So this is basically how we want to set up the club hallway, and we are going to continue the lessons on the next video.
30. 29 Cursor Manager: Hey, in this video, we are going to create a cursor manager, so we can see whenever we
can interact with a person NPC or an object like a
door or anything else. First, in order to do that, let's just enable a
couple of our MPC here. As you can see here we
have the two NPC here, and first, we want to create a new manager to
handle the cursor. Here under the managers, let's create a new
empty game object, and let's call this
cursor Manager. For this cursor manager, we want to create a new FSM. Here while the cursor
manager is stft, let's right click here
and then add an FSM. Basically, in the first state, we want to make sure that we are moving the cursor
on the Canvas. In order to do that,
I'm going to create a new image on the Canvas
here under the UI image, and this is going
to be our cursor. For this cursor, by default, we want to set
this two disabled. We want to disable
the game object, and for the cursor manager, let's go to the
variable tab here, and let's first add
an array variable, and this is going to
be the cursor type. For the type, we want
to set this two. Then the next one, we want to add a game
object variable, and this will be the
cursor game object. And we want to expose both
of the variable here. Let's just enable
the input here, and for the cursor, we
want to do the same. The next thing that we want
to do is we want to make sure that the cursor type is
populated with correct cursor. Here I'm going to
set the size 23. For the first
sprite, I'm going to select the hand cursor, and for the second spr is going to be the
bubble dialog cursor, and the third one is
going to be the i cursor. And for the cursor game object, we want to drag this
disabled cursor game object under the Canvas as
the game object. Let's say the seat here. Next, we need to
create a new enum, so define the cursor
that we want to show whenever the mouse is
hovering the interractables. Here under the projects
and the scripts folder, and here inside the
scripts folder, let's create a new
C sharp script. Let's call this interact
type. Let's open the script. For the script
here, I'm going to delete this mono behavior and delete all of the content here and change the type
from class to um. Let's first type hand
with all capital. For the second um, I'm going to set this to and the third one
is going to be the i. Here we can select which
type of the cursor that we want to show whenever the mouse is hovering
the interactable. And for organizing the am, I'm going to right
click here and then select the quick
actions refractory, and I'm going to move
to namespace here. Here I'm going to pick
the point and click game. We can search for
this am easier under the point and click
namespace here, just like what we did
with the item class. Now this is done. Let's just
close isle studio here, and now we can use
that am in playmaker. The next thing that we
want to do is we want to go to the cursor manager
here under the playmaker tab. Now we want to move the cursor every frame
inside the state here. First, we need to get the
mouse position and by default, playmaker provide us with
the get mouse x and y, but there is a compact version
of it in the ecosystem. I'm going to go to the ads here under ecosystem
ser open it, and then I'm going to
search for mouse position. And should return the custom
actions that we need, and I you change the capital. Here. As you can see, the first result is
the GT Must position, so we can just get this action. With this action, we can get the vector
of the most position directly without having to build the new position
from a float. Here, let's go back to the actions browser and use
the get most position here. Let's just store
this most position to a new variable called Moz we don't want to
set this to normalize, Disable the normalize and we want to enable
this every frame. Then we want to set the position of the cursor
using the set position action. For the game object,
let's specify game object and then select
the cursor variable here. For the vector, we can
select the most position, and for the space, world
should be good here, and let's just select
every frame here. Now to test this,
we can just enable the cursor and Under game view, we should be able to
see this wide square. If we press plea, you see that the image is following the
mouse cursor, as you can see. Now we have this cursor working. We need to implement
more to show different cursor whenever it
hovers different intracts. The next thing that
we want to do, we want to disable the cursor back. Under the cursor manager, we want to add a new
state to switch cursor. Here, let's just change
this two switch cursor, and we need to create
a global event. I'm going to create a global
event called switch cursor. I'm going to enable this
broadcast event here. I'm going to create another
event called Hight cursor. And I'm going to also enable
this broadcast event. Next, I want to add a global transition stitch
cursor to this state here. I'm going to create
another state and add a global transition
height cursor on this one. Let's rename the state
to Hight cursor. Now we have created the switch cursor and
the height cursor state. On the switch cursor,
we want to get the cursor using the array gap from the cursor
types array here. For the index, we want to create a new variable called index, and this will be set by each
of the interactable later. Then we want to
store the value to a new variable
called cent cursor. And we want to add a
finish transition. If the index is out of range, we want to go to finish. I will skip this
next action below. Then here, we want to use
the UI set image sprite. For the game object, we can just pick the
cursor game object. For the sprite, we can pick
the current cursor here. This should do here and
another thing that we want to add is we want to add and
activate game object. Action here. Basically, we want to activate
the game object. Whenever we have finish getting the cursor
and sting the cursor, then we want to enable
the cursor game object. Let's just specify
game object here. Pick the cursor variable
and activate it. And we can copy
this action here. Basically on hide cursor, we just want to hide the cursor. We can just activate
this wel hide it, and we want to add a
finished transition and connect the finished transition back to
the first state. I'm going to
reorganize this here. Here this is basically what we want to do with the
cursor manager. The next thing that we
want to do is we want to modify the interactable FS. Let's just pick one
of the NPC here, and under the playmaker FSM, let's just click to
add the template here. Here, basically, we want to add two new state to switch cursor, and then to hide the cursor. Let's just rename this
two switch cursor. And this one to cursor. We can use a custom event that lemker has
provided us here. I'm going to add a
transition system event and here we have the mouse over. I'm going to use that and
go to the Switch cursor. Under the Switch cursor, I'm going to add a
transition system event, and then this is going
to be the most exit. I'm going to connect this Ms
exit to height cursor here. For the cursor, I'm going to add the most over transition back so we can go back and
switch the cursor again. Basically, this will look through the two states
whenever we are entering or exiting the interactable when the most position is entering the interactable or
exiting the interactable. Here on the first stage here, we want to add a
mouse pick event. Let's just search
for it and let's pick this mouse
pick action event. Whenever we are hovering, we want to send the mouse over, and let's add a layer mask
and for the layer mask, let's just pick interactable. And we want to make sure that this every
frame is checked, so it will check for
the mouse every frame. Now we can copy the stft
action here, minimize it. Inside the high cursor, we want to paste this back. For the switch cursor, we want to paste this and we want to set the most
over back to none, and we want to set the
most off to most exit. Now, we need to create
a new global variables to hold the cursor manager. Let's just create a new
game object variable. Let's call this cursor Manager, and I'm going to set this
category to manager. For the value, we need to set this up from
the cursor manager. Here inside the cursor Manager, I'm going to add a new state here and let's just
call this in it. Basically what we want
to do is we want to get the owner of this FSM. And safe this to a new
variable called owner, then we want to set
game object variable, which is going to be
the cursor manager. For the game object, we can
pick the owner variable. Let's move this down so
we get the owner first, then we set the cursor global
variable to be the owner. Let's just minimize
this and set this as the start state at a
finished transition, and connect this to
the first state. I'm going to save
the sample seam here and back to
the NPC dialogue, the interactable template here. Now we want to send an evN to the cursor manager whenever we are switching
the cursor here. Here, let's just
first set an FSM in. And we want to set the
index based on the type of the icon that we want to set as the interactable icon or cursor. In order to do that,
here in the variable, I'm going to create a new
variable called type. For the type here, I'm
going to change this to um. For the um type, I'm going to go to the point and click game, which is the name
space that we've created and tick interact type. By default, it will set
this value to hand. We want to expose this
variable as well, Let's just press the input here, check the input, and now we have this am in our inspector. Back to the state
here, we want to set the FSM integer
specify game object, and then we want to pick
the cursor game object. Here for the variable name, if we go to the
cursor manager here, you see whenever we are
switching the cursor, we are getting the cursor types based on the index integer here. We want to set this value. So Let's go to the
interactable template here. Here, the variable name is index that we want to change and we want to set the value to
the Nam that we have here. So here, we can select the use variable and
basically we can convert enum to a integer
automatically by using this convert menu and
then pick the type um, and this will set the integer based on the index of the enum. Basically this by default, is going to be in order
starting from zero, an is going to be zero, Tk is going to be one, and I is going to be two, and we need to make sure that this order is the same as the
order of our cursor here. As you can see here, The first cursor type
index zero is the han, and then the second
one is the talk, and the third one is the i. We need to make sure
that the order of our am and the order of
this array is the same. Go back to the NPC
dialogue here, add the interactable
template again. Now we have set up
the index variable on the cursor manager. We can just minimize this and then we can just
send in the event. And we want to target
game object FSM for the game object specify it and get the cursor manager here, and for the event, we
want to search for the global event
called switch cursor. And we can copy
this action here, and whenever we are going
to Hight the cursor, we want to basically, we want to send the
ight cursor event here. Let's change this order here. We want to boot the most event to be the bottom action here. Same with the switch cursor, we want to change this to
them of the send event. Now let's save the scene here
and let's save the project. It updates the template here. Now let's give this try. Here, if I hover
the police officer, as you can see, we can
see the hand icon, and I can see also
the hand icon. This is because that
the hand icon is the default icon or the cursor. In order to change that,
you can just easily go to the NPC here and then change the type to and the
same with the other NPC here. Under the intractable, we
can change the type to tok. Now if we test this again here, you will be able to see
that if we hover the NPC, we have the bubble dial
up on or cursor here, and we can interact
with that PC. We can talk this NPC here. Yeah, that is basically
how we create a cursor and this is
going to be useful. So the user will be able to know which object
that we can interact in our seat If we want to make this door
interactable then we can set those cursor type here
in the interactable FSM.
31. 30 City Scene Story: Hi, in this video. Let's start creating the story gameplay, and here I've already created a base story for our game here, and we are going to start
working on the scene one, which is the front club
or the City scene here. So first, let's just
disable this NPC here from our example
here and this one here. And let's open the se tab here. And first, we want to create the bouncer here to
guard this door here. So basically, we want to make
sure that we want to create a story where whenever the players try to interact
with this door here, we want the bouncer to forbid the player to enter
this door here. So in order to do that, I'm going to create a
new anti game object under the interactables
on the CD s here. And create a new T here, and I'm going to rename this
NPC underscore bouncer. And for this bouncer here, I'm going to add a
capsule collider. And I'm going to set the height
to two and the center 21, so it aligns with
our ground here. And for the layer, let's
set this two intractable, and we can add a
playmaker FSM here. Okay. And we want to add the three model that is going
to be the bouncer here. So let's just go
to the project tab here under the two
tiny people here. Go to the prefix folder, and I'm going to pick this male A and drag this as the child
of the NPC bouncer. And let's set the rotations
to zero on the y axis here. So it's facing forward. And now we want to select
the parent game object, which is the NPC
bouncer and rag this, so it stands on the
side of the door here. For this NPC bouncer, we want to add the
interactable FSM. So let's just pick here from the template and select
the interactable. And for the type, we
can set this two talk. And here, we can add
an anti game object. Let's just call
this Talk response. And I'm going to create
another anti game object. And this is going to
be the door response. And for the talk response, I'm going to add a new FSM, and I'm going to select the
template dialogue FSM here. And for the message, I'm going to set this to. What are you looking at And we don't want to set the other stuff here because we only want
you to show the message. And let's add the name
of the bouncer here. And I'm going to press enter. L et's also enter
this message here. Let's check this if this
is on a different line. So I'm going to open a node
path here and paste let's just enter this
here and copy all of the message here
and paste it here. Now we should have a new line between the name
and the message. Here on the NPC bouncer, we want to set the actions 21 on the intractable FSM and
direct the top response. And then we want to create
another empty game object, which is going to
be the front door. And for the front door, we
want to add a box collider, and we can set the size of the x to 1.7. This should be enough. For the Y, I'm going
to set this to 2.5. And for the z, I'm
going to set this to a very low value,
0.3, for example. And for the center, I'm
going to set this to be the half value
of our y size here. So it's going to
be 1.2 or 25 here. And now let's align this game object to
the front door here. So around that position. Let's perfect this
position here. Okay, this should do here. And let's change the
layer to intractable. And then we want
to add a new FSM, and let's pick the template, which is going to be
the intractable here. And for the type, we want
to keep this to hand, and we want to set the size
to one for the actions. And now we can expand
the NPC bos bouncer. And for the door response, we need to create a new FSM and select the dialog
template here. And for the message,
we can just say, like, let's just type
it here on the notepad. So we have this new line. And let's just say that
you're not allowed to enter. For example, and let's just
copy all of this text here, and then paste this
here to the message. Okay. Another thing that we
want to do is we want to play an animation whenever
this bouncer is talking. So let's just add a
new anti game object. And this is going to
be the animation, for example, and let's
add a new playmaker FSM. Let's pick the template
play animation. And we want to drag the
animator game object, which is this prefabs
game object here, the child game object that
has the treaty model on it, it should have an animator. And for the controller here, we want to select the people
here because the controller, we already have the
animator set up. Basically, we have this idle animations in the bland tree, and we have this talking, and we're talking, we can trigger this talking
using the top trigger. So if we go back to the scene here and under the
animation game object, we can type the
trigger, which is talk. And basically, whenever we are
interacting with this NPC, we want to trigger
the top response, and then we want to trigger
also the animation. And the same goes with
the front door here. First, we want to trigger
the door response FSM here, and we want to add another FSM, and then trigger the animation. Now, let's save the scene here. If we press play, we can talk with this bouncer. Oh, we need to check
those new line, but right now, let's just
keep it like this here. And if we talk or if we
interact with this door here, it will also says that
you're not allowed to enter. So basically, this bouncer
will guard the door here. The next thing that we
want to do is we want to create two different
cameras in the scene here. So basically, first,
we want to have the main camera pointing
to this angle here. So right now we can just
select the main camera here, and then hold Control Shift F to change the position of the camera to be aligned
with our view here. So now, in our game view, you see that we
have the same view as our scene view here. And for the main camera, we want to remove
the audio listener. And we want to add
a plan maker FSM. And here we want to select
the register camera template, and we don't need to set
anything else in this FSM. And I'm going to
create another camera, and I'm going to call
this side door camera. And for this side door camera, I'm going to change
our scene view to point in this
area, for example. Yeah, I think they should do. And now with the side
door camera selected, we can just hold
control shift F, and this will
change the position of the second camera here. And we want to also disable
the second camera here. But now we need to create an area to trigger
the camera zone. We already created a
similar game object here on our sample scene here, the one that has been set up, so we can just duplicate this game object and then drag this game object
to the CD scene here. And this will be the CD
game object right now. And let's just enable
this trig camera zone. And let's rename this
two side trigger. And now we want to
go to the top view here and drag this glider. And basically, we want to put this around this position here. And I'm going to extend this scider by pressing the edit glider and then
extend this scaliter, so it will cover this area here. Maybe this area as well. Okay, now that we have
the trigger zone setup, Here, we want to change
the camera on enter, and then on exit value here. Let's just track the main
camera as the camera on exit, and on enter, we want to change this to the
side door camera. Let's save the scene here. And now if we test this, if we go to this area here, we should be able to see that
the camera is switching. But if we go back
to this area here, then it will go back
to the main camera. So the next thing that
we want to do is we want to create this
side door interaction. Here we already have the
side door interactions, and basically the side
door interactions will switch the swing right now. But we want to change this. So here I'm going to add
a new anti game object. And I'm going to call
this failed response. And then I'm going to
duplicate this game object, and I'm going to call
this success response. For the success response, we want to copy this FSM here, the switch scene template here. Let's just copy this component. And then here I'm going
to paste component a new. So we have this. And on
the side door interaction, we can just delete this. And then we want to create another couple of
anti game objects. And we are going to call this password
unknown, for example. Put it on top here.
And here, basically, we want to show a dialog
and a response here. So basically, we want to
add a playmaker FSM here, add a dialog template, not the action, but
the template FSM here. And let's just set
the message to do. And then ask the player, what is the password? And then we want
to enable to ask questions here for the yes. We want to set this to
chicken, for example, with question mark, and for no, we can just type this no idea. For the sender FSM, we can just drag this
FSM to the slot here. And we can add a no
action and yes action. And both of these
no and yes actions, we want to direct
the failed response. Oh, we need to add FSM first, so let's just add
a new FSM here, and this is going to be another
dialogue template here, but without any question. And for the message,
I'm going to type. Nice try. For example. And now if we go back to the
password known game object, we can drag this failed
response to the slot here and failed response
to the other slot here. And basically, we want to trigger this password ag node whenever we are
interacting with the door, but we want to increase
the size here, and then we want to add the password known
game object here. So this is when we are already interacted
with the password non or with the password intractable that we are
going to create after this. So for the password
known FSM here, we want to set the
success action or the yes actions to the
success response here. And for the yes
answer label here, we want to set the two
help with capital eight. A capital letter with ds in between. This
can be anything. It's just that this
is the one that I've decided for this game here. And basically, we want
to disable this FSM. And here on the side
door interactions, we want to direct
the password known. Basically, this will triggers if the password known
FSM is enabled, and right now it's
disabled by default, so this won't get triggered
by this interaction. And now we have set up the
side door interactions. We need to create
another thing here, another anti game object, and this is going to be
the password, for example. So let's just add a box
collider, not the two d one. It should be the three D one here and set the layer
to interactable. And here we want to add a FSM. And then for the template, we can pick the
interactable template here. And we can create another
anti game object. And let's just
call this activate known password, for example. And here we want to add FSM. Then we want to add the
template activate multiple FSM. So here we want to disable the password unknown and
activate the password FSM. Let's expand the side
door interaction and direct the unknown to
the activate one here, and then direct the password known to the activate FSM here. Okay. So this should do here. And on the password here, we can add another FSM, and we can add a
dialogue FSM here. So basically, we want just says that there is a
writing in the wall, and let's just type
the password is E P, like so. So now we can
trigger whenever we are interacting with
this password here. Let's just drag this FSM as the first FSM on the
interactable here. And then for the size,
increase the size, and we want to d the activate known password game FSM here. For the type, we can
just change this two I, and let's save the CD s here. And now this is the
password game object. So I'm going to make
this a bit smaller. And I'm going to align
this to the texture here. So here on the side door, you see that we have the
texture, scribble texture here. So I'm going to align this
game object to that position. Okay, yeah. Let's save this, and now let's give this a try. So if we interact with this NPC, we won't be able to enter. Let's go to this area here. If we talk to this door here, for example, we don't
have the answer. So if we answer anything, we won't be able actually
to enter the door. But if we interact with
this password here, T. See that now the password
unknown is disabled, and the password
known is enabled. So we now will be able to see the changes in the
behavior of the door here. Now we have the correct answer. And if we respond with no idea, we cannot enter anyway. So we need to answer
the correct password. Now if we press help,
as you can see, now we are entering
the club hallway. So that is basically
what we want to set up with the gameplay story
of the CD scene here, and we are going to continue
this on the next video. A.
32. 31 Club Hallway Story: Hi. In this video, we
are going to continue to create our gameplay
story for another scene. Last time we already create
the story for the city here. The next thing that we want to create is the club hallway. Here I have the base story. We already implement
the first scene, which is the front club here, and now we want to implement
the club rear hallway. Basically in the
hallway, there will be a toilet room, a security room. And then the story is that well, the protagonist the player, need to ask the security regarding a regular
visitor of the club. And show the pictures. And the security will tell him that he haven't
seen the person. But there is another
person in the toilet, which overheard
the conversations, and then we can talk to that
person and that person will give us a hint on where
we can find that person. If we haven't talked to the
security at that moment, trying to talk to the
guy in the toilet will give us just
a vague response. So we need to talk
to the security first and then talk to
the guy in the toilet. And this is part of the puzzle. Let's just do that. Here, first, I'm going to basically remove
the CT scene here, and I'm going to direct the club hallway so
we can edit this. And here in the club hallway, we already have the
interactable game object. This is basically an
ant game object that holds all of the
interactable objects. And right now, we only have this exit interactions so the player can go outside and
back to the CD scene here. First, we need to
create two NPC here. I'm going to create an
mt game object here, and this is going to
be the security guy. So I'm going to call
this security guy. And for this security guy, let's add a capsule collider
and set the height to two, and I'm going to set
the center to one. So it aligns with
the ground there. And perhaps I'm going
to add a y position. So it aligns very
well to the ground. Here, I'm going to set
this value to 0.2 K. Yeah, that should
do. The other thing that I want to do is I want to change the layer to
intractable and add a FSM. And this is going to
be an intractable FSM. Let's just pick the
intractable template here. Now we can add the
model by going to the Toni tiny P, TT here, and then under the
prefabs folder, I'm going to direct
the pols and make this pols as the child
of this security guy. I'm going to reset the position to zero and set the
rotations to zero as well. And I'm going to change the controller to use the default people
that we have created. So it will play the
idle animation. Okay. Now on the top view, I'm going to direct
this security guy. It stands inside this room
here and I'm going to rotate. And I'm going to
probably hide the gun here because it doesn't make sense that he is holding
his gun in the room there, so let's just set the handgun
and then we can hide it. And basically for
this police officer here or the security guy here, we want to create
a response here. So first, I'm going to create
another anti game object. And this is going to be
the normal response. Or we can just call
it this response because this person will
only have one response. Okay. Now we want
to add a FSM here. And basically, for this FSM, we want to use the
dialog template, and we want to create
a couple of message. So first, let's just type will, and we want to say that E me. Have you seen this guy around showing picture to
the security. Okay. There. And for the
second message. I'm going to type
security guy here. And probably let's
just say I'm sorry, but I haven't seen
him for a while. Okay. So this is the response, and we don't want to
set questions here. It's just going to be
a normal response. And then we want to also
create another FSM here, another anti game object. And let's just call this
modified toilet guy. And here we want to add an FSM, and for the template, we want to pick the
activate multiple FSM. And this will modify the
toilet guy FSM here. Since we haven't created it yet, so we need to create one. Here I'm going just
to wait a second. We we move the model
of the security guy, so I'm going to copy
the transform here. And then I'm going to paste
the component values here. And then let's just reset this transform of the
security guy here. So it sits back on exactly
on the parent game object. So now this so be correct. Previously, it was wrong. And for the type of the
interaction here, we want to set. And for the actions, we can just add one for now and then direct
the response here. L et's save the scene here. And now let's create
another anti give object. And this time, this
is going to be the NPC toilet guy, for example. Let's set the y value 20.2, and let's add a capsule glider and this should have the same
value as the security guy. I'm going just to set this. And we want to add
also an FSM here, and this is going
to be the same. It should be the interactable. We want to also change the
layer to interactable. Let's set the type as well
to top on the interactable. And now we have this folder
open, the model open. We want to drag the male A as the child of this toilet guy. But we want to hide
the baseball bet here. Let's just select this and check the active,
so it's hidden. And now we can just also reset
the rotation choose zero, and we can reposition
the parent game object, which is the NPC toilet guide. And I'm going to put him in the toilet around this
position, for example. I'm going to rotate
him a bit. Okay. So now we need to set up a couple of FSM on this
toilet guide here. Here, first, I'm going to
add a normal response. And this is going to have an FSM with a dialogue
template here. And I'm going to say going to type here that I'm
out of stock now. Like he's selling something, for example, He's
selling something, but he is out of stock. And then we can add
another Anti object. Let's just call this
Eaverop response. This is the response when he
eave drops our conversation. And let's add a dialog
template FSM here. And then we can just say that. I've overheard
your conversation. And for the second message. And I believe you will find
the person on this address. We did more string here. Then he gives you a name card with an address
on it, for example. So this is like an explanation that he is giving
us a name card. And this is also not a dialogue, but we want to check
this playmaker FSM here. We need to create another
anti game object. This should be give name card. And let's add an FSM here, and then we want to
use the give item FSM. Basically, this NPC will
give us an item and we will have this item given to
us to our inventory here. But before that, we need to create the definition
of the item. So I'm going to
create a new item inside the data folder items. R, create and then
item definitions, and I'm going to just call
this name card, for example. For the git here, I can just right click on the script here and
we can copy the git And then paste it here. We have a good number, and let's just call this
name card a name card with an address on
it, for example. Then for the image, we can pick one of the item
image that we have prepared. I'm going to pick this item six. So now we have name card. And the next thing that we
want to do is we want to add this name card definition
into our inventory database. So let's just
increase the size of our array inventory
database here and direct the name card as
the third item here. So now we can save
the scene here, and now on the NPC toilet guide, we can add the name card item
as the item to give here, then we want to add
a chain actions. For these actions, basically, we want to create another FSM. We can call this revert FSM, for example, and here, we can add a FSM, then we want to add the
template activate multiple FSM. Basically, this
should be disabled. Give name card should
also be disabled, and we want to put all of this three FSM onto
the intractable here. Let's just set this 23 and then direct the
normal response. IFS drops response, and
then the gif Name card, sorry, the gift
name card response. We should have this three FSM, but it will only execute
the one that is active. The disabled one
won't be executed. And this revert FSM. Basically, we want to revert the FSM back to
the normal response. Once the NPC gave us the item that we want to revert the dialogue back to
the normal response. So we want to disable two FSM
and activate one FSM here. Basically, we want to
activate the normal response. At the same time,
we want to disable the eaves drop and
the gf name card. Response. But whenever we successfully
receive the name card, we want to also disable one of the FSM on
the security guy. So we can add this
the activate here, and we can disable the
modified toilet guy here. So basically, once we talk
with this security guy, it will modify the toilet guy, and then it will
change the order or the FSM that is activate
and deactivated. Here we can just do that now. Basically, we want to activate two FSM and deactivate
one FSM here. And here we want you to
activate the normal response. And then we want to
enable the Ifrops as well the give name card FSM. So once we talk with
the security guy, we should be able to get the name card from the toilet guy. But then when we revert the FSM, we want to revert back to the normal response and disabled
all of these three FSM. So the next time we
try or the player try to talk to the
security guy again. It will only run the response, but it will skip
this second FSM, which is activating because this can reactivate the
gift name card FSM, which will allow
the player to talk to this person again and then
receive another name card. So it will cause
a bug that where the player can receive
multiple name card item. Here on the security guy, we want to increase the action. Do, and then we want to direct the modified
toilet guy FSM here. And then let's save this
and now give this a try. As you can see here, the
player is outside of the area, but if I run this, it will snap the player
inside the Nai mesh. Okay. Now let's give it a try. Basically, I think we need to change the
camera angle here, but y, we can talk to
the security guy here. Oh, let's top this. Let's
try the whole thing first. Let's try to talk with
the toilet guy first. Okay. We only get that response. Now let's try to talk
with the security guy. Okay. Now if we go out and then we talk with the
toilet guy again, it should have
different response. There you go. I've overheard
your conversation, and now in our inventory,
we have name card. Previously, we don't have it. And I believe you will find
a person on this address. Then he gives your name
card with an address. Now if we open our inventory
here, we have the name card. There you go. And I can confirm
this that because if we stop this and then
if we press play again, you see that on our global
variable inventory, we only have the lighter, and if we open the inventory here, we only have the lighter. So with this system, it works, actually, and
we can try it again here. Let's just try to talk
with him again and then try to talk to the
person in the toilet here. We should receive the name card. And now let's talk with
this police officer again. And if we talk with
this guy here, it will, yeah, we
need to fix this. So it's still giving us
another name card here. So basically, we need
to disable this FSM. Here, let's check
give name card. Oh. Yeah. This is where I forgot. Basically, we have
this revert FSM, but this is not being
called anywhere. Basically, after we
give the name card, we have the chained
actions where we can run another FSM whenever
this action is executed, so we need to direct
the revert FSM here. This is basically will prevent the modified toilet g FSMs to be ever executed again here. Now we can try this one more time and
hopefully this works. Let's just talk to the
officers right away. And then talk to the
toilet guy here. And now we should
have the name card. Yeah, we have the name card, and let's talk with
the officer again. Now if we talk with
the there you go. It keeps saying the
normal response here because talking to
the police officer again, won't change the FSM active
status on the toilet guy. Now we have implement the story for this
club hallway scene, and we are going to continue
this on the next video.
33. 32 Keep States Between Scenes: Hi. Now, in this video, we are going to
continue to work on our point and click
playmaker project. Last time we've created the Club Hallway story
implementation where we can interact with the Security guy as well with the toilet guy. But there is one issue
here that we have now. So I'm going to show you here. Let me just remove
the scene here. And let's track the City scene, so it starts from
the City scene. Right now, we have no way to
keep track the changes or stated changes on
a certain object or NPC whenever we switch scene. So for example here,
with our password here, basically, if I interact
with this password, and then I interact
with the door, I can enter the club
hallway And if I go back outside to the CD scene here and then try to interact
with the door again, you see that it resets itself. We don't see the
password anymore, so we need to interact
with the password again. And this is not ideal. We want to make sure
that object states are safe between scenes. Right now, the states are only safe if we press safe
and then if we load. Now we want to make sure that every object that
has different state or a possibility of different states get safe whenever those
states are changed. So in order to do that, we need to create a couple
of things first. First, we need to
modify the password. Basically here, this is where the cyt
interactions change. For the door here, it's being modified
by the password. So we need to insert some
FSM that trigger the safe whenever we change the order of the active FSMs on
the cital interaction. Here I'm going to create
another anti game object. And this is going to be
called the Safe state, for example, and let's
add a Plamcer FSM. Here, I want to add the template record states
as well the load states. So I'm going to add another FSM. And the load states. By default, this record states
and load states will work automatically or register
itself automatically to the entity safer FSM array
on the global variable, as well the entity loader
FSM for the load states. This is fine and all,
but we need to create some modifications on
this template here. First, I'm going to edit
the record states here. And I'm going to
add a new variable, a type of game object, and I'm going to call
this interactable FSM. And basically, we need
to expose this variable. And now we need to define the
intractable FSMs in order to get all of the
action array list. And now since we are
putting the safe state or the record state and load sits on a different game object, this won't find the
correct variable. So we need to target this
to the correct game object. And this is why we need
the intractable FSM. Now we can just direct the side door Itraction
parent game object here, and this should have
the intractable FSM. This is to make the template
more modular where we can put this template on
different game object and still target the correct
intractable FSM. The same goes with
the loader state here or a load state template. We want to also create
another game object. Let's just call this
intractable FSM as well, and then enable the input. And on the first state, whenever we are
getting the actions, we want to target
the intractable. But in the load states here, we want to add a
finish transition, and then we want to connect
the finish to the load. So we want to load the data, if there are any data
on the scene start. So whenever the scene is loaded, then we want to try to load
the states if there are any states that are safe or
loaded in the safe manager. And if there are no states
with the correct identifier, then this won't trigger
anything at all. So it shod behave as we want to. So now we have this, and we need to drag the
side door interactions. So let's just call this password safe and copy the name
and paste it here. And then we want to also save
this to be password load, for example, and
then save it here. And now here, we want to trigger the record FSM or the record states here whenever the password
is called here. So here we can just add an FSM to the actions of
the intractable and then drag the safe state. And this will get the first
state in the component here. So this will get the
password safe FSM. It will not get
the password load. So whenever we are interacting
with the password, we want to save the state
changes on our side door here. But there is one
thing that we want to do as well with
the safe manager. Right now, the record state is basically trying to run the
template using the run FSM. This will run the safe manager, and it will run the record
position or the record states. But right now whenever we are finished recording the
states or the position, it will go to the
loop all entity, and we don't want to
do this if we only want to save a certain
state of an object. We only want to loop whenever
we run the safe event, then we want to look through
all of the entity FSM. We need to create a bulion here to prevent those
from happening. Basically, we want to create a bullion variable
in the safe manager, and let's just call this loop. Then whenever we are saving, we want to set that b to true. Let's just set bull value here, select the loop and then
check the bull value, and this will set the
Bulen value to true, and we want to copy this action, and whenever we are going
back to the first state, then we want to set
this back to falls. The logic is that
whenever we are running the safe event here, and we want to do all
of this FSM here. We want to enable the loop. So whenever we are iterating through all of the
FSM or the saver FSM, this will direct or
the flow of the states will go to the correct
state here for looping. But we need to create a new
state to decide whenever we want to either to loop the FSM or go back to
the initialized here. So let's just select
all of this here, and let's just move this, and I'm going to create
a new state here. And I'm going to call this
check for loop, for example. Then we want to add
a loop transition as well a finish transition. For the finish, we
want to connect this back to this initialize. And for the loop,
we want to connect this to the loop all entity FSM. Basically, we just want
to do a bull test here. And we want to check if
the loop value is true, then we want to lo,
but if it's false, then we want to go to
the finished transition. And now we want to
redirect all of the finished transition on all of the state here to
this check for loop. Let's just change
this, direct this, this one as well, this
one, and this one. Basically, this is
what we want to do or what we want to change
with the safe manager, and there is nothing we need to change on the
load side of it. Let's save the scene here. And now we have this setup, and we also trigger
the safe state. Whenever we are interacting
with the password. Now we can give this a try
and see if this works. Okay. Now I'm going to
go to this area here, and let's talk or
interact with this door, and we don't have the
correct answer now. Let's interact with
this password. So now we have the
correct answer. We should be able to
enter the club hallway, and now let's try to
go outside again. And once we are outside, let's interact with
this door again. And as you can see here, now we have the correct
answer without having to re interact with
the password again. So now all of this state are preserved whenever we
are changing those states. But we need to always remember
to run the record states, whenever the states change here. So here on the password, we trigger this
record state action whenever player interact
with this password. Because we know
that before we are triggering this record states, the order of the active FSM
is changed by the second FSM, the activate known
password here. Okay. We are done
with the states, but right now we
need to also create changes or make changes
with the NPC move. So for example here, we have this disabled MPC here, and this NPC have a move action. Whenever we interact with
this NPC, it will move. We want to also save the transform whenever the NPC or the object is
finished moving. So let's drag this to our city scene and put this
under the intractable, and let's enable
the NPC move here. I'm going to move its position, so it doesn't collide
with the bouncer there, and I'm going to also change the target position to be
around in this position here. Okay. So now let's
save the city scene, and I'm going to show the problem that we are having right now with
the NPC move here. So if we interact with
this police officer, and then let's say we go to the other scene to the
club hallway here. And then we go back outside. If we walk here, you see that the police officer goes back to its
initial position. And if we want to
preserve the state, then we need to trigger the record transform whenever
it's finished moving. So it's quite easy to do this. We just need to make sure that whenever the
move is finished, then we trigger the record
entity transform and the entity transform so handle the transform whenever
we are switching scene. Here I'm going to add an
action and then direct this record entity transform
FSM to the state here. Let's check the load
entity transform here. For the load transform
and the record transform, we don't need to add the
intractable FSM because we don't want to save the action
state or the FSM state, but we only want to save the transform, so we
don't need to do that. And here, we need to do the same with the load
state template, which is we need to add the finish transition
on the first state and then connect the finish
to the run action. And basically, we want to
try to load if there are any data for this
specific entity, and if there are any data are
safe and then it's loaded, then we want to try to get
those data and then apply those data to this transform
or to this object. Okay. So remember,
we need to put the record transform to the
chain action of the move FSM, and we need to modify the
load entity transform. So it try to run the
actions on start. So let's save the
City scene here. Okay. So now let's
test this again. Okay. So I'm going to talk to the police officer
here, and he moved. And let's go to another scene by checking the password here and then interact
with the door. Okay. And now if we go back
to this area here, you see that the police officer is in the correct position. We can always make sure that the NPC reset its
previous position. And if we want to do that, we can just make sure that the entity transform
FSM doesn't get called here. So you have options
to keep the position persist between
scene or reset it position between scene for any objects or NPC or intractables that we
want to keep track of. And here we can also save here, but we will have an issue
here because as you can see, when I leave the scene here, we created an empty member
on the entity safer here. So here the element one and element two
has no object in it. And this will cause issue
in the safe manager. If we go to the
safe manager here, and then you see that here under the L all entity FSM here, when we invoke this,
this will stop, and it will stop the iterations
of loading the data, and we cannot finish loading, and it will cause a buck here. So we need to fix this. So let's just stop here. And to fix this, basically, we need to check if the
current FSM is null or not. And in order to do that, we don't have an
action to do this, but we have a
conditional expression. So here, if we go to
the action browser, and then under the logic here, we have this
conditional expression. And we can use this to evaluate a certain variable with a certain value in
this expression. So I'm going to show you here. Basically, to check for
a certain variable. First, we need to add $1 sign, and then we need to
type the variable name. And the variable name is
current FSM with a space on it. If there are no space, you can just type it
right away like so. But since we have a space between the current
and the FSM word, we need to add a parent C to close the text here
and then add space here. As you can see
here, it says that this variable was
not found here. But if I add space, then it says that it's false
because this is null here. But if we add if this is null, then it says it's true here. So we want to check if the
current FSM is null or not. And basically, we want
to add a new event here. So let's just add skip, for example, and then add
that transition skip. And basically,
whenever this is true, if the current FSM is null, then we won't to
send to skip here. And basically, this will
skip this call method, and it will go to the next entity saver
that is available. But if it's false, then we
can just leave this empty, then it will execute
the call method here. And now we can connect the skip to this loophole entity FSM. And the same with the
loader here because we will have empty entries
here, for example, let's just save the scene here, and let's give this
another try to check if we don't need to interact with the
police officer here. We just need to make sure that
we see the password here, check the password, and
then go to the other room. And as you can see, we
have empty member there. And if we go back to
the CD scene here, we will have new member, and this will gets added, and we will keep the
empty member here. So we need to also fix
the load part of it. So we already fix the safe part, and for the load
here, Basically, here, we want to check if the
carbon FSM is null or not, and we want to skip
the call method here. So I think we can just copy this conditional
expression here, and then paste it in this
state here and put it above. And we can just make sure that
if the carron FSM is null, then we want to execute
the finish right away, and this will skip
the call method. So this is for a safeguard,
if for some reason, the entity loader or the
entity safer has an empty or a object that is
none in its member. So now let's save this, and
let's give this another try. Now we should be able
to save the game. So the police officer is moving there and
let's interact here. Here and then we can go
back to the CDC in here, and now let's save this. I'm going to highlight
the safe manager and let's see if this gets
safe. It's get safe there. Now if we stop here, we can try to play it again. And if we load this, it
should load the game. And if we talk to
this door here, you see that we have
the state saved. And if we go to this area here, we can see that the police officer is in
the correct position. So yeah, that is basically how we persist on NPC or
interactables between scene. And we will also want to keep track the scene whenever
we are saving the game. So we need to add that to keep track which scene when
we are saving last time. And we are going to do
that in the next video.
34. 33 Park Scene Story Part 1: Now, in this video, we are going to work on the park scene, the last scene of our game. In order to do that, let's create a new scene here inside
the subs scenes folder. I'm going to create a new
scene here from the menu, and let's just call this part. And let's open the scene here. Now we want to set up
the environment first. First thing that we want
to do is we want to go to the point click folder here
and under the prefabs, we should have the Par prefe. We can use this
directly to the scene, and now we have this there. I think we can just delete
the directional light, the default directional light. Now we want to prepare a
couple of things here. I'm going to create
an anti gable check and then reset the transform. Let's just rename
this two environment. And I'm going to drag the park prefs to be the child
of this environment here. For the main camera, I'm going to select
the main camera here, and I'm going to reposition to be around this position here. For example, maybe
something like this. In order to reposition
the camera, to follow the view that we
have on our scene here, we can just select
the main camera and then hold control, shift, and then at, and this will align the camera
with our view here. Now if we go to our game view, you see that we have the view or the same angle with what
we have in our scene here. T. Okay. Now we can save the scene
and the next thing that we want to do is we want to create
another anti game object. So I'm going to create
an anti game object, and I'm going to call
this one interactable. And this is for grouping the different types of object that we have in our scene here. And this will holds everything
that we can interact with. So here, I'm going to add a new anti game object as a child of this interactable, and I'm going to call
this NPC police officer. And here, let's just go to the two
tiny people folder here. C mo, and under the prefs. Let's just direct the
police prefabs here to be the child of this
NPC police officer. Now let's reset all of this position here
and also the rotation. And now we can select
the parent game object, and we can move this and I'm going to position
this police officer around this position here, and I'm going to rotate this so it's facing to this side here. Now if we go to our game view, we can see the police officer. Maybe we can move this a
bit back on the Z axis. Maybe around this position
and see in our game view. As long we can see it
in our game view and be sure that the player can interact with this
police officer. This is a good position. For the police officer, there will be a couple
of states that we need to create as a child here, an empty game object that will hold different states
of interactions. The next thing that we
want to create here, I want to create another
empty game object to be the child of interactable. I'm going to call this
game object blocker. And then I'm going to
add a box collider. And then let's move
this blocker so it blocks the area
here, the park area. I'm going to put around in this position in
front of this barrel. And I'm going to disable
the perspective mode. Here, for the sizing, I'm going to set the z size
to a very small one like 0.2. I's thin and I'm going
to create a wall. I'm going to increase
the size to 0.4. For the x value, I'm going to set this to 20. It covers most of the view here. I'm going to make
this even bigger, for example, and move
this to the site a bit. For the y size, I'm going to set this to two, it's around two
units or 2 meters. And move this slightly up. One on the y position
here. That should be good. Now we have this blocker, and I'm going to this
slightly down on the y axis, so it conforms to the surface
to the ground surface. Let's increase the y
size here to three, for example, and adjust
the base position. It sits on top of the
ground surface of the park. Now we have this blocker here, The blocker should
cover everything. The purpose of this blocker
that we don't want to allow the player to interact with the dead bodies that we are
going to put next here. Here, let's create
another anti game object under the interactable
game object, and let's just call
this NPC dead body. For this NPC dead body, I'm going to add the male
A again as the child. I'm going to move the NPC here. I'm going to rotate
this 90 degrees on the y axis and also 90
degrees on the x axis. So I facing down to
the ground here, and we can adjust the
position of the bones. We can post this. Here, let's
just unpack this prefabs, and I'm going to delete the
animator component here. Now I'm going to open
the child object, expand the BiP object here, and this is basically the bones. If I hold out and then click
on this expand button, you can see that we have a
lot of child game objects. First, I'm going to select the baseball bat that we have here and I'm
going to hide it. Then for the head, I'm going to rotate
the head bone, so it's facing this way, or maybe we can just rotate it to so it's
facing the other way. Then we can adjust the hand clavicle here to make
it more spread like this, and the same goes with
the other clavicle. And we can rotate this
a bit here like this. For the leg, I think, we can adjust the i if we want, make it something like this. Then once we set
up the pose here, I'm going to readjust the position of the
parent game object, which is the NPC that body, and I'm going to
push this on the or local of this
game object here. I s move b slightly below, so it conforms to the ground. And here we want to add
a capsule collider, so we can interact
with this NPC later, and I'm going to set the
y value the height two, maybe around two units or 1.7 units and move the center
to be around maybe 0.85. And now we have this here, we should be able to interact once we've disabled
the blocker later, and I'm going to enable
the s trigger options. For the layer, I'm
going to make sure that this is going to be
the interactable layer, and I don't want to
change the child object, so we can just change
only this object here. For the blocker, we
want to do the same. We want to change this to
an interactable layer. The same goes with the
police officer here, we want to set this to
interactable layer. And make sure that we don't
change the children as well. Now we have set up
that body here. Let's add a capsule glider for this police officer as well, and I'm going to
set the same value, 1.7 on the height, and for the center, shift the Y axis to 0.85. And here I'm going to
add a playmaker FSM, and I'm going to use a template, which is the intractable
K. Then for the actions, we are going to
set this up here. Basically, there
will be a couple of states that we want to set
up for the police officer. We want to have
the base dialogue, so I'm going to create an empty and this is going to
be the base dialogue. Let's add a playmaker FSM
and form the template. We can pick the template
dialog FSM here. Then here we want to trigger the base dialogue
whenever we are interacting with
this police officer. Let's just drat the
base dialogue here. And we want to create
another anti game object, and this is going to be
called after bribing. We are going to bribe this police officer to
remove the blocker. For this after bribing, we can just add a Plamer FSM, and this is going to
be also a dialog FSM, and we are going to
set up this later. But for now here on
the intractable, we want to expand the action, and we want to trigger also
the after bribing here. But we are going to
disable the FSM. By default, this bribing
FSM won't be called whenever we are interacting
with the police officer. I will only be executed once
we have activated this FSM. For the base dialog, let's just create a
couple message here. And then for the message, can we can just say
that police officer, you are not you are not
allowed to enter, for example, and then for the second line, we can just say that unless and then with a grin, for example. So we want to give a hint to the player that
we can interact with this police officer and we
can offer some money to it. Here, we can just enable
the ask questions, and just for the, we can just ignore him, and for the yes string, we can just say this give money. For the center FSM, we can just drag this FSM
itself to the slot here, and the s actions, and for the yes actions, we want to create
another child object that will trigger a
couple of actions. Let's create an empty
game object here. Let's just call this yes action. For the s actions, we want to add a clacer FSM, and then we want to
use the template take item item FSM here, and we want to
create a new item. I'm just going to
be the money here. Here on the Neta folder
and items folder here, let's create a new
item definition here. Let's just call this money. I'm going just to copy
here from the lighter, for example, I'm going to change a couple
of character here. Change the number here. Yeah, we should have a unique get here. For the name, I'm going to call this money for the description. Let's just type this
a couple of bugs. For the image, we want to use the money icon here,
this one here. The next thing that
we want to do here, here under the
inventory database. We want to add the money here. Let's just increase the size
and for the fourth member, we want to add the money here. And we want to put this money as the default item in
our inventory here. Here in the inventory, I'm going to increase
the size and then drag the money as the second
element of our inventory here. Let's save the seat here and I'm going to
save the project, so it will save all of
the changes that we have created here in the items folder as well the global variable. Let's go back to the yes
actions of the police officer. For the items you take here, we want to drag the money. For failed actions,
we want to say or we want to show a dialogue that saying that we don't
have this item. For the success item, we want to trigger a
couple of things. I'm going to set the
sides to two here. For the failed actions, I'm going to create another
child game object here, and let's just call
this failed action. And add a playmaker FSM, and here we want to run
the dialog template, and this is not going to be
an option or a question, so it's going to be a message. Let's just type don't
have any money. For the s action here, let's just direct
the failed actions to the failed actions, and we want to create
another anti give object for the succeeded action. Let's just create
another anti gm object, and I'm going to
call the succeed one Add the playmaker FSM here, and we want to deactivate
a game object, which is the blocker
game object here. For this FSM, we need to
create a new template here. Here, under the playmaker, let's create a new FSM here. I'm going to add
a new state here, and I'm going to add the
global transition run action. Basically, we want to enable or disable certain
game object here. Here I'm going to create
two new array variable, and let's just call
this two disable. For the type, I'm going to
change the two game object, and let's expose
this in the input, and let's create
another array variable. Let's call this two
enable and change the array type also to game object and then
enable the input checkbox, so we can set up this value
here in the inspector. Basically, we just want
to look through all of those. Object here. Here, let's just use
the array get next, and then let's just pick the
two disable game object. For the result, we want to cache the array that we are
iterating to a U variable. Let's call this
current game object. We don't need an index for this, let's just add a transition a loop transition and
a finished transition. For loop here, basically, we want to create a U state, and then we want to
disable or deactivate. Let's just use the activate
game object action, and then we want to
specify game object, and we want to pick the current game object
that we are iterating, and then we want to
disable this game object. We want to uncheck the
activate options here, and then we can just add
a finished transition, and let's just go back
to the state here. Let's just rename the
loop all two disable, for example, let's just call
this disable current O. When we are finished, we want to go to a new state and this one is going to
be loop two enable. And here we want to use
the array get next again. This time we want to look through the two
enable go the array, and then add a transition loop, and then we can just
create a new state here. And we can use the activate
game object action, and then specify game object, pick the current
game object that we are iterating and we
want to activate this. Upon finish, this
transition or the state, we want to go back to
this loop state here, and for the loop event, set this two loop so we can just look through
the game object, and we need to store the result to the current
game object variable. When finish from the state here, let's just go back to
the first state here. Here on the second loop, we want to set the loop
event to loop and the finished event to
finish transition. The same goes with
this first state here, we want to send the loop to loop event and the
finish to finish event. Now, basically, whenever we
are running these actions, we are going to look through
all of the disable array or the game object that we want to disable in this
array inspector, and then it will disable it. Then once we finish this is going to look through all
of the two enable array, and in this one, we are going to enable we want to activate
the game object instead of disableling it. Let's just rename the state to enable current game object. Now we have this state setup. I'm going to save this
as a template and here, I'm going to call this template activate multiple game
object instead of FSM here, we can just use the safe
template in this FSM here. Now we have used
this template now. Basically, we just want to
disable the blocker here. Here I'm going to add a disable game object here and then drag this
blocker game object. In this yes actions, for the first one, we want
to drag the succeed action. Whenever we are giving the
money to the police officer, we want to disable the
blocker game object. Here, we want to add
another anti game object, and this is going to be the succeed two,
for example, here. Let's just in sued the second
succeed child game object. We want to use the template
activate multiple FSM. And then we want to enable and deactivate one of
our previous FSM that we have set up here. Basically, we want to
disable the base dialogue. We want to deactivate this, and we want to activate
the after bribing FSM. This is going to make sure that whenever we bribe
this police officer, the next response is going to be different than
the base dialogue, which is the after bribing. I'm going to add another
child game object, which is going to be the
succeed third action. Here is going to be just a simple dialogue and it's going to be a message
only without a questions. Let's just say thanks for
the police officer here. Here in the yes actions, we want to make sure that
we are running all of the succeed actions whenever we are successfully giving the
money to the police officer. Let's just add the
success action again and then drag
the third one here. Now, make sure that first the after bribing
FSM is disabled, and here I'm going to add a dialogue here, like singing. Something like that.
This is the last thing that we want to
create is we want to create another dialogue whenever we are interacting with the
blocker game object here. I'm going to add an
empty child object, and I'm going to call
this blocker dialogue, and here I'm going
to add another FSM, and then use the
template dialogue here. For the message,
I'm going to say this let's just say what
something like this. This should prevent us
and giving the player hint that the player cannot
go to the dead bodies. It needs to do something before we can interact with
the dead bodies. Another thing that we want
to create is the animator. We want to trigger an
animation whenever we are interacting with the
police officer here. Let's just add FSM here, and we shod have the template. I think we have this one
here. The play animation. For the animator game object, we can just direct
this mash game object that has an animator. Then here, we can just use
the default people, I think. Let's take a look in
the animator here. Yeah. We have this talk trigger and we have this talking
animation state. We can use this actually. Here in the trigger animations, I'm going just to trigger
this talk parameter. Here in the trigger animations, we can just type talk
here as the trigger. Then the other thing that
we want to add is we want to create a trigger audio. Here let's add another
playmaker FSM. Let's just pick the play audio here and let's just pick
one of the dialogue here, like Mel C Dog for example. Now we need to always play this trigger animation and trigger audio in our
base interaction. Here I'm going to increase the size of our actions
in the template in FSM here and drag this trigger
animations and audio here. The next thing that we want
to do here is in the blocker. We want to add a playmaker FSM, and then we want to pick
the template intractable. For the actions, we
want to set this 23, and we can just drag the
blocker dialogue here, the trigger animation, and
the trigger audio here. Now let's give this try. Oh, we cannot try it this way, so we need to open
our base scene. Let's just go to
the scenes folder here under the
sample scene here. Let's just go to the subscene, and then direct the park
scene to the scene here. Let's test this out, and I think we need to
move the player. Let's just move the player a bit here around this position here. The other thing that I think
we need to do is we need to bake the navigation mesh because we haven't
done that yet. Here under the park, I think I've already marked this prefab static s. I'm going
just to open the park scene. Remove the park scene here under the subse. Let's open the park. We can just save the
sample scene here, and then here inside
the park scene, then we want to do the bake. Now we have bake the scene here, that save the park scene. And once we successfully
bake the navigation mesh, we should be seeing a folder called park
inside the sub scene. Now we can go back to
the main scene here and then drag the park
scene from the sub scene. Now let's run this
and give this a try. Another thing that I forgot is that we need to create a glider. I'm going to create an
mt game object here, and for this anti game object. I'm going to add a box coli. I'm going to set
the y size to 0.2, and I'm going to
increase the x size to let's say 30 by
30, for example. We have something that
is covering our scene, from the side view, I'm going
to move this ground colier. I lies on the tre surface, let's change the layer to ground here and I'm going to
enable a trigger here, let's just call
this ground glider. Now we can save the park seal
here and test this again. Here we should be
able to walk around and I'm going to
mute the audio here, and basically if we
interact with this blocker. Na sgment. The police officer is basically saying,
what are you doing? Na named the sage mail. We cannot interact and let's try to interact
with this police officer. Let's just ignore him for now. When we are ignoring him, we want to make the
police officer say. We are going to do that. Next thing here.
Let's just stop this. Here under the interactable I think on the base
dialogue here, we should have the no action. Let's just increase no actions, and let's create another
anti gave object. Let's just call this no action. Then here we want to
add a claim maker FSM and pick the di time plate here, and let's just type police
officer suit yourself. And here, I'm going to put this below the yes action here. For the base dialogue, I'm going to direct the
newly created no actions as then actions in our FSM here. And we can save the
park scene again. Now let's try this again. Okay. And we can
try this here if we remove the money
from our inventory here and then try to interact
with this police officer. And we want let's say
we try to bribe him. We we should not be able to You should get
a response here. Let's just check
because there are no response failed actions. Here, the issue was
very simple, actually. I forgot to put the s actions
in the base dialogue here. Basically here as you can see the yes action is
till set two none, so I need to drag this yes
action to the slot here, and that sho fix this. Here, let's try this again. Let's try to interact with
the police officer here and then I'm going to remove the money from
our inventory here. Let's just try to give him money and it
says that you don't have money because it failed to give the money here and it
triggers the failed action. It triggers this dialogue here. Now I'm going to
stop this again and then try this again
and this time we want to give the money
from our inventory here. Let's just give him this money
here and it says, thanks. Now when we are interacting with this police officer, again, it will just sing and it will not show the base
dialogue anymore. Here, if we see that we can see that our blocker
is now disabled, we should be able to walk
around and we should be able to try to interact with
this dead body here. We are going to continue
this in the next video.
35. 34 Park Scene Story Part 2: In this VO, we are going to continue working
on the park scene, and we are going to create the ending cut scenes
for this scene here. So let's jump into it. First, we need to create
a new anti game object that will hold the
cut scenes data. So I'm going to create
a new game object here, and it will create by
default in the sample scene. So I'm going just to click and then direct this
game object to the park. And we can discard the changes
on the sample scene here. And here in the park scene, I'm going to rename this
game object en cut scene. Let's just reset
the transform here. Then we want to add a couple of child object in this
cut game object. The first one, we want
to add the female model. I'm going to go to this
folder here, Titmo, and under the prefet I'm going
to direct the demo female. Now we have the female
game object here. The next thing that we want
to do is we want to add a new camera as the
child object here, and then we want to create
another anti game object that will hold the dialog signal
that we want to trigger. Basically, this will hold all of the game object that we'll
have like a dial of FSM, and we can trigger each of those dialogues via the
cut sins or the timeline. I will show you this later. Here I'm going just to
call this dialog group, or we can just call
this dial receiver. And I'm going to create
one empty game object, and let's call this dial one. And for this game object, let's just add a Pla Maker FSM, and then we can add a
template dial of FSM here. Let's just leave the
settings as it is right now. Here for the dial up receiver, we want to add the
signal receiver. We are going to setting
this in a bit later. Now, first, we need to add a new timeline to this cut
scene game object here. Here I can just open a timeline window and if
you then have this opened, you can go to the window menu and then sequencing and
then pick timeline. And then we'll show
you this window here. Okay. So now we can just create a new timeline, and
we can save this. So I'm going to go to the
SS folder animations, and I'm going to
create a new folder called sequence inside
the animations folder. And then here, we can just save this timeline
playable format. Now once we save
this, we should have this interface where
we can add tracks, we can direct the timeline here. So first, we want to animate
this female game object. So let's create a track group, and I'm going to call this
female gao, for example. And the neat thing with
the group is that we can create a couple of
tracks inside this group, so we can order or
organize our timeline nicely and less cluttered
than without any track group. Here I'm going to
create two animation t, two different animation track. Then the last one, I want to
add the activation track. Yeah. Here we can just drag the demo female model here to this animator slot
and then the second one. For the third one, we want to also direct this game object and we want to activate for the length of
the cut scene here. The next thing that
we want to do is we want to adjust the
camera view first. I'm going to select the
camera game object here, and I'm going to change, for example, I'm going to change the view to be around this. Or maybe make it like
this, for example. And the reason is
that we want to make sure that we will able
to put the female outside the camera
frame and then start running going inside
the camera frame. So here with this
camera set that, we can just hold control
shift F and this will align the camera there. And the next thing that
we want to do is we want to pick the sens again, and now we want to animate
the female model here. Here, for the second
animator track here, I'm going to press this
recording button here, and then we can just select the female model here and I'm
going to direct position. And this will create keys
there, as you can see here. In the first frame,
we have a new key. If we go to the camera view, we want to make sure
that this female is from this position here. Let's just put this way
out of camera here. And I'm going to change the y
axis as well, the position. It sits above the road
or the three D mesh. And here maybe we want to I think we want to create a
key frames around frame 90, so we want to make sure
that the female starts running from this frame
or around frame 100. I'm going to add a key
all animated here. It will create key frames there, and then I want to
go to frame 150, for example, or 160. I'm going just to type it here. With the female module selected, I'm going to move this female, so it stops around
this position here. In front of his husband, for example, and rotates a bit. Here we be able to see
the animations there. And here I'm going to
create rotation animations. It's running straight first, and then it rotates. We can addit these
animations later. I mean, the timing, we can
change the key frames. But for now, I think
they should be enough. The next thing that we
want to do is we want to disable the animations
button here, so it doesn't animate anymore. And for the first
animation track, we can add a clip. So here I want to
add a running clip, starting from Frame 100. So let's just right click here, add from animation clip, and then we can pick
the female run and make sure that we pick
the run only without the RM suffix because this is the root motions where the animation has the
translations information. So we want to use the animation
that is running in place. Now, as you can
see if I run this, we can see the run
animations there. We need to make this keyframe longer so we can
just drop a click on this track here and it will open the clip in the
animations window. And basically, we want to make
sure that this part here, we want to scale the animation. In order to scale
this, we can just drag this blue lines here
near the key frames, and this will stretch the keys. I'm going to make
sure that maybe it stops around this point here. Now if we go back
to the timeline, we should be able to
see that our animations now ends in the
different frames. Here, if I scrub this again, you can see the animations. I think this runs much better. And we can loop the run
animations by dragging this clip here, and
this will loop. And around this
position, I want to stop the animations. There, it stops. And then we can add new clip female idol,
for example here. Let's just make this
very short idol, and we can drag this
idol and make sure that this idol is overlap
with the run animation, so it will create transition. We can just drag this and
make it overlap like this, and this will be the
transition value here. Here if I scrub this, you see that at the
end of the point, it transition to the idol there. Here I'm going to add a new animation clip and this one is going
to be the female death. This is not for the death
animations actually. I just want to make a
fainting animation, so we can just use
this animation. Just move this. We don't need to change the timing and make sure that this death
animations overlaps a bit with the idol. There you go. Now we should be able
to see that it will stop the animation and
here it will faint. And here we need to make sure
that the active track here, we want to extend this, so it doesn't make the female game object
disappear like so. So here let's just set the end time around this
position, for example. I'm going to just to type
it to make it round, 260 and then direct this. So we should be able to see the female game object all
the way through the p. Okay. So the next thing that
we want to do is we want to also add a new
active ation track, and this is going
to be outside of the female game
object because this is going to be the active
track for the camera. So we want to enable
the camera during the cut scenes here and make
sure that the length is the same as the previous
timeline or here a frame 316. We want to make sure
that the track is the same length as the one
that we have above here. Okay. The next thing that we want
to do is we want to add a track or senal track here, and this needs a senal receiver. For this, we can just
drag this dialog receiver here and we can trigger
different signals, and I'm going to show
you this inhibit. Okay. Next thing that we want to do is we can just
save the scene, make sure that we have saved all of the changes
that we've created. Here, for the female
game object here, I'm going to disable
the preview. And for the female
game object here, I'm going to select the knife
model here and I'm going to make sure that
the knife model is selected and hide this because we don't need
this to be shown. Then we want to also disable
the female model by default. It's not feasible
during the gameplay, and we want to also
disable the camera here. It's not activated
during the gameplay. Let's save the park scene again. The next thing that we want
to do is we want to create a new signals for the
animations dialogue here. Here in take the
animation sequence. We'll create a new signal, and then let's just
call this dialogue one, and we can uplicate the signal. And this is going to
be the end dialog to. Here inside the dialog receiver, we can add reactions. I'm going to add two reactions. For the first reactions, I can just pick the first
end dialog signal here. For the second, we can just
pick the second dialog. Here we can trigger
the dialogue here. Here on the first dialog, I'm
going to add a new message, and I'm going to type wheel and he will
mention something like, this is not good, for example. And out of the worry of the wife that's going to be
said when she sees the scene. We'll mention about this. And then we can just
duplicate the dialogue here. I'm going to change the name
the game object name here and for the second dialogue, I'm going to type this wife. And then that's just
like screaming like so. Then here in the
dialog receiver, we can add a new reaction event, and we can direct
the first dialog to the first slot here, and then we can go to
the playmaker FSM, and this, basically,
we want to force the run a global transition. In order to do that, we can use the send event
method here and then type the global
transitions name. It's going to be run action with all CAPs the same goes with
the second reaction here. I'm going to direct
the second dialog. Here, we can just pick the
playmaker component FSM, and then we can just use the
set event methods as well. Then we can just type
run action here. Now we have set up the receiver. In the timeline here when
we select the can s, we can trigger those receiver. Here, maybe around frame 20, I'm going to add a
new senior emitter, and we can pick the
first dialog here. And when the wife came
running and arrived. Maybe around this frame here, we can just start emitting the second dialog
signal, like so. Here, this should
play the animations. And now we need to trigger
this cut sins from playing when the player interacts
with this dead body PC here. Here in the end cut
scenes game object, first, we want to disable
the play on awake. We want to make sure
that this cut sins doesn't get played automatically
when the scenes start. And then here, we can just expand the
interactable group here and then select the NPC dead body and make sure that it
has a capsule glider. We already done that.
In the last video, we also set the layer
to interactable. And now we can just
add a playmaker FSM, and we can pick the
interactable template. Then here, we can add
a new child object, and this is going to be
the trigger cut sin FSM. In order to do this, we
need to create a new FSM, and we need to create a new template FSM here.
Here I'm going to add With this selected here,
let's just press edit here. We should be able to
edit the FSM now, and I'm going to add
a new state here and I'm going to add a global
transition custom event, and then pick run actions. And here, basically, we want
to trigger the timeline. In order to do that, we
need to know the type of the timeline component or
this playable director. So in order to do that, we can just select the
FSM here and then drag the cuts in game object that has the playable director
component attached to it. And then here we can just
use like score method here, and now we have a
method that can trigger a method from
this component here. Now in order to
make this easier, we know that the Unit engine
playable playable director. So here we can create
a new object variable. And let's call this timeline. For the type of the object, we can change this
to Unity engine and then go down here
under the letter P. We should have a sub
menu called playables, and here we can pick
the playable director. We can also expose
this as an input in the inspector And the next thing that we want to do
is we want to make sure that this is on
the second state. I'm going to copy the selected actions
and then paste this on the second state and delete the one from
the first state. And for the second state, we can just pick a
variable timeline, and for the method, we can just trigger the play method here. Now we have a FSM that can
trigger the cut ins to play. Here I'm going to save
this as a template. And I'm going to call this
template trigger timeline. Can just use the
safe template here. Now we can trigger the
playable director, so we can just drag
this cut scenes here. Then in the main NPC
that body game object, we can trigger this cut sins by increasing the action
size and then drag the trigger cut sins game
object into the slot here. The next thing
that we want to do is we want to make sure that the z directions of this game object is
facing this way here. We need to change
that. I'm going to recept the rotations
of this game object, and I'm going to rotate
the male model instead. I'm going to rotate
90 degrees on the y axis and also 90
degrees on the x axis here. Now we need to change the orientations of the
capsule collider here. Here we can just change
it to the x axis. Now we have the
orientations correct, but we need to make sure that
we reset this value here, and then we can add
0.85 on the x axis. It fits to the mesh
here, as you can see. Now if we select this and
select the Move tool, the Move gizmo, as
you can see here, we have this z axis correct. I'm going to move this
collide a bit to the center, for example, set it 20 here, and then change the
mesh instead to be like maybe negative
0.85 on the sorry. Not this here. I think she. This should be
negative 0.85 there, and now it should
be on the middle. The z axis here,
and now we can just move this body back
to its position. Now this will date the stopping position of the
player when interacting. Now let's save the scene here
and let's give this a try. So here we need
to interact with. Okay. One thing
that we need to fix is the police officer
position here. So let's just do that
before we continue further. I'm going to
reposition the y axis, so it stays above the
ground. Maybe like so. Yeah. Let's save the scene
again and test this now. Let's just interact with
the police officer here, and then let's just
give him money, and now we should
be able to walk around and we can interact
with this dead body. Now as you can see here, when we are interacting, we can see the
timeline here playing, and we need to fix the
timing of dialogue, but that is an easy fix. Now, let's wrap up
this cuts ins here. One thing that we need to fix is the timing of the dialogue here. So in order to fix that, I've already adjusted the First dialog signal here, I put it on the very
start of the cut scenes. And the second one, I
put it around frame 190. So you should have enough space between
dialogues to finish, but user can also
click it to finish up the text from writing. The last thing that I
want to do is I want to transition the scene here to a menu scene that
we haven't created. So for now, we can just
create a more scene here. I'm going to create a new scene here inside the scenes here. I'm going to create a new scene and let's just call this menu, and I'm going to
open the scene here. Basically, I just want to put a text object in
the Canvas space. Let's just zoom out here and I'm going to set
up this very quickly, change the UI scale mode
and then set the match 0.5, so it match the
width and height. And now we can center
the text here by selecting the text object and
under the direct transform, we can use the anchor
presets here and then hold all and then
press the middle one. This will center the object, and I'm going to
center the alignment as well and change
the text menu. And then for the main camera, I'm going to change the
background or clear flags to solid color and then change
this to color of black. So here we have this menu on
top of a black background. Let's just save the scene here. And the next thing that
we want to do is we want to put this menu in
the build setting. So here, let's put the
menu to the Bild settings, and we also need to put the park scenes to
the build menu here. I'm going to reorder
this so it's organized nicely and put the
menu as the first scene. So now I have set up the
scene in the build settings. I'm going to save the project. And now we need to go back to the main scene or the
sample scene here, and I'm going to drag the park scene to the
scene here again. Okay. Now let's create
the transition. First, I'm going to create a new Canvas to be the
child of this cut scene, so I'm going to go
to the menufolder, and then pick Canvas. And for the Canvas, we can
just set this to anything. I'm going to set this to
scale with screen size. We can set this 0.5.
For the match value. And then we can add a image
hot on the Canvas here, and I'm going to stretch
this to full screen. So I'm going to click this on the anchor preset
and then hold out, and then I'm going to pick the
most bottom right presets. And this will stretch the image to cover all of the screen here. So here for the image, I'm going to change
this name to failer, and we can just set
the color to black and set the transparent
or the Alpha Vu 20, and we can just disable
the recast target, so it doesn't interfere
with the cast, the clicking, the UI
and the scene casting. Here, under the Canvas, since we don't need any
interactions with the Canvas, I will just delete this
graphic recster here. Okay. Now we have this fader and let's go back to
the cuts in here. And basically, we want
to animate the fader, so it start fading from this
frame here, for example. So here, I'm going to create
a new animation track, and I'm going to drag
the fader game object. And this will ask to
create an animator, so we can just create
animator on fader. And basically here,
we can just enable the recording button and
we can set up the fader. I'm going to change the value. Alpha value, and then
put back to zero, so it gets recorded
and basically, I just want to create
a new key frame with an alpha value of zero
in this frame here, and nearing the end, maybe ten frames before
the end in frame 350, I'm going to change
the color to full black or opaque set
transparency to 100. Now we have this here. I'm going to disable
this recording mode and here back in the
project in the data folder, sorry in the sequence
animation sequence folder, I'm going to duplicate
the signal emitter here. And then I'm going to
rename this to go to menu. I'm going to add a new reactions in the
signal receiver here. I'm going to add new reactions and I'm going to
pick the go to menu. And then we can add
a reactions in it. I'm going to create a
new empty game object. And I'm going to call
this go to menu. Let's add a playmaker FSM. Here, basically, we just want to create a state where we are transitioning to the menu scene. Let's just add a
global transition. We can just use the run
actions and we can trigger this transition
from the set event later in the signal receiver. Here on the state. Let's just we can use the load
scene asynchronous. And we can just use the by name and we can use
a new variable. Let's just create
a new variable. Let's just call
this target scene, and we want to activate
the allow sine activation. Basically, this will open
the scene once it's fully loaded because we can delay the scene loading
by pressing a button, and if we want to do that, we can just disable the
all sine activation. Okay. Now we have
this target scene. I'm going to expose this,
and I'm going to type menu. And this is the mockup
scene that we've created previously
here in the scene. And now that we have this FSM. We have this state load scene asynchronous in the second state with the run actions
global transition. We can go to the
signal receiver and then directly go to menu here. And then we can pick
the playmaker FSM, and then we can
just send an event, and we can just use
the run action. Here. Okay. So now
that we have created this signal and the reactions back to the timeline,
the end cuts in here. We can go to this
frame, frame 350. And then on on the signal track, we can just right click here, and then add signal emitter, and then we can pick
the G two menu here. And this will trigger this sent event to the
good two menu FSM here. Okay. So let's save the park scene and now
let's give this a try. Okay. So let's talk to
the police officer. Okay. So let's give him money, and then let's interact
with the dead body here. Now we have this.
Once it's finished, it's fade out and then
it opens the menu sine, and later we can continue working in the menu sine
to create interactions.
36. 35 Connecting City to Park Scene: Hi, in this video,
we are going to tie up our gameplay, and basically, we need to create a way to transition from the CT
scene to the park scene, and we haven't set up that yet. So here, I have the sample
scene and the CT scene opened. I'm going to add a new game
object as the interactable, so expand the
interactable game object. And then we can add
an empty game object, and I'm going to call this taxi. For this taxi here, we can go to the project folder. Under the point and
click folder here, we have the models folder
inside the models folder, we should have the
taxi three model. Let's strike this taxi and make this object as a child of
this taxi game object here. And now we can move the taxi game object
here and I'm going to move it to be around
this position here. I'm going to move the
child game object, so it's centered,
for example here. Then we can just move the
taxi game object here. Move it to this
position, for example. For the taxi game object, I'm going to change the
layer to intractable, and we can just select
know this object only, so it doesn't change
the child object. And I'm going to
add a box coller. For the box cooler,
I'm going to set the size 24 on the x axis, and then I'm going to set the y axis to two
for the z axis, I'm going to set
this also to two. For the center, I'm going
to change the y value 21. It's offset and it aligns correctly with our taxi
model, so we can click on it. Here I'm going to add
a new playmaker FSM. And for this pimter FSM, we are going to use the
template intractable. And for the type, I'm going to change this to the top icon, and I'm going to increase
the action size to one here, and I'm going to
change the z direction of the parent game object. As you can see now, the
z is pointing that way, so I need to make
sure that the z is pointing to the opposite
direction here. So here we can just rotate
the parent game object, 180 degrees on the y axis, and then select the
child game object and then rotate this back to 180 180 degrees
in the Y axis here. And we can just remove the negative sign
on the position here. So it's inverted,
and now we have the car or the taxi model
back to its position, and it fits with the
collider as well. So now we have this setup. I'm going to set the stopping
list maybe to around 1.7. And the next thing that we
want to do is we want to add a couple of anti game object as a child of this
taxi game object. So the first one, we want
to check for name card. So we can just call this
check for name card. And for checking the name card, we want to add a playmaker FSM, and we can use the
template take item FSM. And here, basically,
we want to add a functionality where this FSM can also only check the item instead of taking
the item from the player. So here, let's just press
the edit button here, and here we want to add
a new, a bleen variable. And I'm going to call
this check only, and I'm going to expose this bulion so we
can change it here. And here, basically, whenever we are successfully
checking the item, we want to go to a new state, and we can call this state check gole option, for example. Basically, we want to
add a finish transition, as well a skip transition
that we have defined before, and it should be available
in the custom event here. So here I'm going to
use the skip one here. Basically inside the state, we only want to
check for a bullion, so we can use the
bull test action. Let's check for the check only variable, and if it's true, then we want to skip
and if it's false, then we want to go to finish. Here basically for the finish, we want to go to the gift state, and here for the
skip transition, we want to go to
the first state. So now we have this here. And basically, we need
to make sure that we run the success or yeah, the success actions every
time we have the item. So instead of doing it here, we can just cut this action
here and we want to do it now in this check
bull option state, and put this above
the bull test here. And one thing that we
need to make sure here, we need to make sure we
disable the finish event. Otherwise, the bull
test will get skip. So I'm going to
set this to none, and I'm going to
let the bull test to handle the transition
of the states. We want to only trigger
the success action here. So now we are done with the modifications of the
template take item FSM. If we go back to the
check for name card here, we should have this option here. And for this check
for name card, I want to enable this option, so we don't lose the
name card that we are going to show
to the taxi driver. So here for the item to take, we can just select
the name card. And we need to add the
fail actions sides 21, and for the success
action same 21 here. Okay. So I'm going to add another a couple of another
child game object here. And this one, I'm going to
call this no name card. And for the no name card, I'm going to use a simple
template dialog FSM here. And for the message,
I'm going to set this to taxi driver, and I'm going to say
going somewhere, Mr.. And this is going to
be a simple dialogue. And for the other
hid gate object, I'm going to call
this H name card. And for this H Name card, I'm going to also use the
template dialog FSM here. And for the message, I'm
going to type taxi driver. Do you want to go
do you want to go to the address on the name card, for example, we can set this
as a questions for yes. We can just set this to yes. For no, we can just
set this to no, and then we want to
set the sender FSM. So as directly has a And
for the yes actions, we want to enable
one FSM here and we need to create another
anti game object, and I'm going to call
this switch scene. And here we want to
add the playmaker FSM. We want to use the
template switch scene. And for the target set, it's
going to be the park seat, so we can just t park here. And now inside the
H Name card FSM, we want to direct the
switch Scene game object to this yes action here. Okay. So now we have
set this up here. Let's check one more time. Okay? Now we need to add
this failed actions and the success actions to the check for name card game object. So for the no name card, we want to go to
the failed action. And for the H Name card, we want to set this to
the success actions. So we can save the scene here. And then on the root
taxi game object, we want to check for name card game object to be the element or the FSM
that we want to trigger. We can save the scene here, and now we can test this. So Right now, if I talk
to this taxi driver, we can't do anything with
the taxi driver here. So we need to get
the name card first. Let's go to the club hallway. And here let's talk to
the police officer. And now we can talk to
the guy in the toilet, and we should get the name card. So here now, in our inventory, we should have the
name card in it. So let's go to the
City scene again. And now let's try to interact
with the taxi driver. And first, I want to
try to say no and see if we still have the
name card. There you go. I select no, and we still
have the name card, and in inventory, we can still
see the name card in it. But if we interact again
and then we pick yes, we should be going to we
arrive in the park scene here. And there is an issue here
because, for example, if we transition
to the park scene, we started inside part
of the crime scene here, so we want to prevent that. So we need to modify
the park scene. In order to do
that, I'm going to drag the park scene
to our scene here. So let's go to the scenes
folder, sub scene, and I'm going to
drag the park scene, and now we should be able
to see the park scene. So for the park se,
let's just adjust all of the park scene
game object here. Basically, we want to select all of the park
game object here. And then we want to
move them all together, and let's move the park scene so we set it like around
this position here. So the starting position, we will be around in
this position here, the player near the taxi, and then when we transition
to the park scene. We should be in the area where we cannot
enter the crime scene yet. So we want to make
sure that position. So let's just save
the park scene, and let's remove the
park scene here. Okay. Now let's test this
again for testing this. Let's just increase the size of the inventory and
then add the name card. And let's interact with the
taxi here. And press yes. And now, as you can see here, we are starting
in this position, and we won't be able to go to the crime scene unless we
talk to the police officer. And I want to check
for one thing here. I want to make sure
that our cut scenes is working as expected. So here, let's just give
money to the police officer, and then let's interact
with the dead body here. Yeah. We still have the cut
scenes working correctly. Okay. So yeah, that
is how we want to tie our city scene
to the park scene. And in the next video, we are going to
implement how to save the current loaded scene into our safe file because right now we don't have that
implemented yet.
37. 36 Saving Loaded Scene: Hi, in this video, we are
going to continue to work on our playmaker
point and click game. And in this lessons, we are going to implement to save the current loaded
scene into the safe file. In order to do that, first, we need to expand
our sample scenes, expand the managers,
and then we need to create a new object here. And then I'm going
to call this SN I. And for the scene in it, I'm
going to add a new FSM here. Basically, I just want to load the scene the default
scene that we want to load or the child scene that we want to load
by default here. Here I'm going to
add a new variables. I'm going to set
the type to string, and I'm going to call
this start scene. And I'm going to expose
this as an input here. Here on start, I'm going to add a new load sin
asynchronous action. And then for the
scene reference, I'm going to use
the scene by name, and I'm going to pick the
start scene variable here, and we want to set
this to additive, and we want to enable the
all scene activation. And this will load the
start scene by default. So now we can just remove the City scene from
the sample scene here, but I'm going to do this later. The next thing that
we want to do is we want to access the
safe manager here. But we need to create a new
variable in the Safe manager. So we want to keep
track the current loaded scene in
the Safe manager. So here in the Safe manager, I'm going to create a new
variables, a type of string. And I'm going to call this
current loaded scene. For this variable,
I'm going to save the value whenever we are
saving the data here. Here inside the save
all data state, we can just add a
new string a entry, set this 21 here, and we can set the first element to the current loaded scene. So this will save
the loaded scene. But the next thing that we
need to do is we need to set this loaded scene to a scene that we are
currently loading. So for example here,
in the scene in it, because we are loading
the start scene on start, then we need to save
the scene that we are loading into that
string variable. In order to do that, we can
just use the set FSM string. And then we have the global
access to the save manager. So we are going to change the game object to
specify game object. And then we can
use variable here, and for the variable, we can use the global variable and
then pick the save manager. And here we don't need
to specify the FSA name, but we need to specify
the variable name. So for the variable
name, we can just type current loaded scene. And this is the variable
name that we've defined previously
in the safe manager. And now for the value, we want to select the
start scene value, and we want to put this above the load
asynchronous action. And we want to make sure that
this is an action sequence, so it will get
executed in sequence. It will execute this one first, and then the next it
will execute this one. And then I'm going to
add a next frame event. Because by default, the safe manager might
not be initialized yet. Because we are assigning the
safe manager on start here. Here, as you can
see here on start, we are setting we are getting the owner of
this safe manager FSM, and we are saving this to the global variable safe manager. So this might create race
condition if we don't use the next frame event on the scene in
game object here. So I'm going to move this
next frame event to be the top actions in
the stack here. And this will make sure
that we are delaying the execution of these
two other actions after the next frame. So by the time we are
setting the FSM string here, the safe managers should
be already initialized. Okay, so we can just ignore this error because
we are not sending. We are using this
action sequence. So I'm going to minimize this, and I'm going to save
the sample scene. And the next thing that we
want to fix is we want to modify the template
switch scene FSM here. Here in the interactable
cyto interactions in the success response. We have this template
switch scene, so we want to edit this here. And basically, whenever we are loading the sine asynchronously, we want to set the current
loaded sin string variable in the safe manager to the target scene that
we are loading here. So here, I'm going to use
the set FSM string again. And put this before the load
scene asynchronous here. And for the game object, I'm going to specify
game object. And then we can pick
the safe manager. And for the variable
name, we can just type carbon loaded scene, and we want to set this
value to the target scene. Okay, so this should
do the trick. The logic is that whenever
we are loading scene, we want to set the
current loaded scene in the safe manager to the target scene that
we are loading. Because in a moment when we are executing this load
scene asynchronous, then we should be transported
into the new scene. So we want to set the
current loaded scenes always to the new scenes
that we are loading. That way, whenever
we are pressing the safe button in
the safe manager, then the current loaded
scene will get saved into the JSON file
to our safe system. Okay, so now, I think we can just remove the CT scene here. And then here in
the scene in it, we can just input C in
the start scene here, so it will load the
C scene by default. We can save this. There's one
thing that I forgot here. In the safe manager
in the FSM here. We are saving the current
loaded scene here, but we need to
load that as well. So here whenever we are
loading from the disc here, we want to enable
the string variable, and we want to save
this to a new variable. I don't want to overwrite
the current loaded scene, so I'm going to use
a new variable, and I'm going to call
this saved scene. And here, whenever we are
refreshing inventory, we want to go to the
new state first. And here we want to rename
this to load saved sen. Here, basically, we want to use the load sen asynchronous. And we want to use
the scene by name, and we want to use the
save scene variable here. Let's set this to additive, and we want to allow
scene activation. At the same time,
we want to unload sine asynchronous here below, and then we want to use
the scene by name here, and we want to use the
cirro loaded scene. This way, whenever we
are loading the scene, it will try to load
the safe scene, and then it will remove
the current loaded scene. So if we start a new game, we start in the City scene, but our safe state have
the information that we are in the club hallway
when we are saving last time, that it will try to load the club hallway in the
load scene asynchronous, and then it will try to
unload the city scene here. And once we are loading
the safe scene and we unloaded the previous
curn loaded scene here, we want to set string
value or yeah, we can just type string here, and we can use the set
string value here. And basically, we want to set the current loaded scene
into our safe scene. So because we are loading
the safe scene here, as you can see, we want to set this current loaded
scene to the safe scene. And now we want to add
a finished transition, and then we want to connect
this to initialize. Okay. So now we are
going to test this. So first, I'm going
to run the game, and let's try to go
to the club hallway. Here and let's interact with the writing and
then go to the door. Press help. So I'm going
to save the scene. I'm going to save the game
now here in this game saved. So now let's stop and
then let's press play, and let's try to load the game. And here, as you can see,
the saved scene is working. We managed to load
the clap hallway, and we managed to
remove the city scene. So it removed the
current loaded scene, and then it tries to
load the saved scene. And we can go back to
the CT scene here. For example, we can
try to save again. And if we try to load this
scene again, It loads. So yeah, I'm going
to create a new safe where we are in
the club hallway, and I'm going to show you one bug that we are
having currently, so we need to fix the bug here. So I'm going to save this
in the scene again here. And now let's try to run this. And while we are going
to load the scene, I'm going to walk very far
and then try to load this. And as you can see, it
starts it loads the scenes, but it tries to move the
player to that position. And if the player cannot arrive, it will keep playing
the walking animation. So we need to fix this. First, to fix this, we need to add a new global event in the player game object and
the click to move FSM here. I'm going to add a new
global event called arrived, and I'm going to
broadcast this event, so it's accessible
from another FSM. And I'm going to add
that global transition to the RV that we
just created. Here. And basically in
this arrive here, I'm going to set the speed of our animator using the set
animator float here. I'm going to copy this action, and then paste this arrive in the RF state and then put
this to the top stack here. For the value, I'm
going to select the variable and set
this value to zero, so it will stop the
walking animations whenever we are arriving. Then the other thing that we
want to modify is we want to modify the load
transform template here. I'm going to press dit here. Basically, I want to
create a function that where we can chain another FSM when we are finished loading. Here I'm going to add
a new array variable, and I'm going to call
this chained FSM. I'm going to expose this as an input so we can
assign another FSM here. For the type, I'm going to
change this to a object, and then I'm going to pick
the playmaker FSM here. O Go back to the state here. I'm going to use
the run FSM action. And for this run FSM actions, I'm going to pick
the action run FSMs. And for the actions, I'm going to pass this chain FSM
that we've just created. So I'm going to set
this to chain FSM here. And then we don't want
to do anything here. Okay. Now we have
this implemented. I'm going to create
a new playmaker FSM on the player game object. So let's just add the
playmaker FSM here. Put this above the
audio listener. A And here, I'm going
to add this Oh, I minimize this by mistake. So I'm going to
addit this FSM here. And then I'm going to
call this warp agent. And basically, I'm going
to add a new state here. And for the second
state, I'm going to add a global transition run action. So we can invoke this
FSM using this chain FSM because the run FSM action will trigger this run
actions on all of the FSM that we are going to list in the
chain FSM variable here. So here, basically,
I want just to get the position. Of the owner. When we are loading, we
should get the position, and we want to save this to a new vector called
current position. Then I'm going to set
this space to world, and I'm going to enable
the action sequence here. I'm going to add
agent warp action. This basically will warp the
object to that position, and then it will clear
the set destination. The agent will be in
the correct position. Using this current position
that we are getting here. So it will override the
destinations and it will position the agent in
that position correctly. So for the new position, we can just use
variable, and then we can just use the
current position here. And we don't need to
set anything here. And basically, below here, we want to use the sand event. Action. And for the target
the event target, we want to use the
game object FSM here. Use order because
we want to target the arrived transition or
event on this click to FSM. So here we can just pick
the click to move FSM here, and we should be able
to pick the arrive. Transition here, and
this do the trick. So I'm going to save
the scene here. Now that we have created
this warp Agent FSM, I'm going to
increase the size of this chain FSM and
then drag this FSM. So basically, whenever we are finished loading the transform, whenever we are loading
the game state here. This will trigger
this warp agent, FSM, and then it will try to get the current position because this is going to be
the loaded position. If we execute this in the same frame when we
are finished loading it. And then it will warp the
agent to this position here. That we clearing the
previous set destinations. So here, let's just save
the sample scene here, and let's test this again. Now we know that we have
the safe in our club scene. We can just try to move this far away and then try
to load the scene. And as you can see here, we see that the player was
moving to a certain distance. And then when we are
loading the scene, it loads the character correctly and the character
doesn't move anymore. D try to move to that position that we see in the
previous bugs. So yeah, that is basically
how we set up the safe scene. So we can save the scene whenever we are in
a certain scene, and we can continue
playing in that scene.
38. Bug Fixing: NPC Move Template Fix: In this video, we are going
to improve the NPC move. Template, and this bug is
reported by Niko Tansen. So thanks Nicole for
informing the bug. Here, basically, I'm going
to show you the issue. So I'm going to run the game. And now we have loaded
the game In the C here, in the interactables,
we have this NPC move, the police officers, basically. And I I select the
NPC move here and we highlight the
playmaker FSM here. You can see that we have defined the interactable
position on the start. And when we run or
we interact it, it runs to the interactions, and it doesn't define the new interaction or
interactable position. And I need to do two clicks until it gets
defined a new position. So we want to fix this. And in order to fix this here, basically, we need to
open the template, the intractable templates, and here we need to change a
couple of things here. Here on the start, we want to define the position, and then we want to
go to a new state, which is going to wait
for a mouse peak event. So here I'm going to move
this slightly above, and then I'm going to
create a new state here. And basically, I'm going to copy the mouse peak event here. And I'm going to move the mouse over event to
the second state here. I'm going to add a
new over transition. And I'm going to
connect this mouse over to the switch cursor, similar to the divine
position here. And in the divine position here, I'm going to remove
the mouse peak event, and I'm going to change the
transition event to finish. And I'm going to connect
this transition event to the second state here. And here, let's just call
this wait for clicks. And now we need to create a new state to redefine
the position here. First, we need to create
a new global event, and let's just call this
redefined position, and we need to make sure that this global event is checked. Then I'm going to add
a new state here. Let's just call this
redefined position. And I'm going to add that global transition
redefined position, and I'm going to add a finished transition that goes back to the weight
for click state here. And basically here,
we want to do the same as we do in
defined position. We want to set the
transform directions, and then based on the forward
of the NPC or the owner. And then we want to multiply
with the stopping distance, and we want to add this direction vector
to the new position, which is the target position. Here I'm going to copy all
of this three action here. And then I'm going
to paste it here. And basically, for
the target position, we are going to send a new
vector from another FSM. Remember, we have this
target position vector with capital T and capital P, and we don't want to
use the get owner and position in this
redefined position state. So now we have modified
the template intractable. We need to modify the
templates move PC here. Let's just open this here. And basically whenever
we are interacting, we trigger this run actions, and then we set the
destinations to the agent. We want to update the
interactable position on that template
interactable FSM. So here, basically, if we
open the CD scene here, I'm going just to
direct the CD scene. And we see the NPC move here. The intractable should
have the name intractable. So we want to target this FSM. Here, we need to re
open or we can select the move FSM and then we can
addit the template here. So in the move state
here, basically, we want to set a vector te FSM, and then we want to
send the FSM name here. It would be better if we expose the FSM name in the variable
on the template move NPC, so I'm going to add that
interactable FSM variable. And for the type, I'm going
to change this as string, and I'm going to expose
this as an input variable. So instead of using FSM name, I'm going to pick the
interactable FSM. For the variable
name, we know it's target position
with capital T and capital P. And then we want to set the value of
this target position here. So let's just set this target position after
we are setting this. Then we want to send
the redefined event. Redefined position event. So let's just send event. And for the event target, we want to select
the game object FSM. For the game object,
we want to use the owner and the FSM name,
we want to do the same. We want to select the
interract FSM variable. And then we want to send the global event
redefined position. Okay, now let's
save the project, so this changes in our
templates get saved. And if we select
the NPC move here, the move should have the
interactable FSM exposed here. So let's just copy the name. And now we have set this up. I'm going to save
the City scene, and I'm going to remove the City scene from
our scene here. Now, let's test this out. And to test this, we can select the NPC move. Game object here, and we
can check the FSM here. So now the defined position is setting the interactable
position in the front here. So let's just click here. And then when I run this, you see that it goes
to the state briefly. And if I click this,
one more time, it will go to the new position. So we don't need to click multiple times to get the
defined position refresh. And yeah, this is an improvement
that Nico report to me. So thanks again
for the Help Nico.
39. Bug Fixing: Player Movement Fix: Hi, in this video,
we are going to fix a bug that we have in
the player movement, and basically, we have a bug where whenever we
are moving the player, and while the player is moving, if we click on a invalid area, an empty area, for example, then the animations
will never stop. We will see that the player
will move to the point, and it will stop, but the
run animation will not stop. And I can show you
the issue here. If we press play, and I need to go to
the club hallway to demo this bug here. I'm going to interract here. And let's go to
the club hallway. Oops. So here, basically, whenever let's say I try to
move to this position here, and then I click here. You see, we have this
issue here on the player. And this is basically because whenever we are
waiting to arrive here, when we finish arriving, it will go to the
state here and then it will set the animator
float to zero, so it will stop the animation. But there is a possibility where whenever we are moving
while we are in the state, we click and then we go
to this mouse down event, and transition to the
defined destinations. And when there are
no clicks at all, it goes back to finish
to the first state, and then the animation
never gets reset. So we need to fix this. And in order to fix
this here, first, we need to add a new
Bleion to the player. Click to move FSM. So here I'm going to
go to the arable step. I'm going to create
a new variable. I'm going to call
this is moving. And I'm going to set the type to bleion and create
this variable here. And basically, whenever we
are setting the destination, I'm going to set the
Boolean value to true. I'm going to put this above
the next frame event, and I'm going to set the Boulan variable is moving
to true in the state here. And then basically, I'm going to copy this
action, the set Bolan, and whenever we are arriving to the destination point, here, I'm going to set is
moving bulion to false, so I'm going to uncheck
this value here. So now we have this bulion. We can detect whenever we are moving whenever we are
clicking on empty area here. So basically, here in
the defined destination. The last one, we are
checking for valid clicks. This bulion variable
will be true whenever we are clicking on an
object that has collider. And now basically we want to set the false to empty
on the state here, and we want to add
a new bulion test, so I'm going to just to copy this action and paste it here. And instead of checking
for the valid click, I'm going to check for
the is moving here. So basically, when there is a valid click and there
is a new position, we want to go to the
target position. But if we click
on an empty area, we don't want to go
to finish yet here. We want to check is
the player game object currently moving,
and if it's moving, then we want to go back
to the wait to arrive, and if it's not moving,
then we want to go to to the wait for click here. So here, if it's not moving, I'm going to set this to finish, but we need to
create a new event. So I'm going to call
this is moving. And then we can add the moving transition to this
defined destination state. And then let's connect the is moving back to the
way to arrive here. And here for the Es true event, we want to set this to
the is moving transition. So basically, we just need to do this in order to fix this. So let's save the scene here, and let's test this again. So I'm going to go
to the club hallway. And let's go talk to
the bouncer here. Okay. So I'm going to move to this point here and I'm going
to click somewhere else. And as you can see here, whenever I go and then I click, it goes back to wait to arrive. Yeah, that is
basically how we fix the Tuck on running
animation issue. Whenever we click
on an empty area, and this buck is also
reported by Nico. So thanks for that, Nico.