The last few videos we've been creating
this selection manager using the SOLID
principles, which means it's really easy
to create and implement new behaviors.
But what's not easy is setting up those
behaviors in the scene. It's a very
hands-on process in which I have to go
into the hierarchy, find the selection
manager, and replace the behaviors that I
want by hand. So in this video we're
gonna try to make a simple tool, that'll
live in the editor, that's gonna make it
really easy to hot-swap behaviors on the
fly. My name is Charles and this is
Infallible Code, a channel designed to
help you become a better game developer.
If you'd like to learn more about Unity,
programming, and game development, then be
sure to subscribe and hit that bell icon
so you'll be notified whenever a new
video is made available. If we take a
look at the hierarchy window we can see
that we currently have three selection
managers in the scene. And the only thing
that's different between them is the
selection response. So we have one that
highlights, one that outlines, and another
one that just places an indicator above
the object. And this is what I was
talking about in the intro: that in order
to try out a new selection response, or
even a new selector or a provider, I need
to create a prefab or manually swap out
an existing selection managers
components in order to match the
behavior that I want to test. What I'd
prefer to do is be able to hot-swap them
by hitting a key or maybe exposing a
debug button that's only available in
the editor. So with that being said, why
don't we switch into the code editor and
see what we can come up with. Let's start
by taking a look at the selection
manager. We can see here that we have a
reference to ISelectionResponse that
gets initialized in the awake method and
then used whenever there's a new
selection to delegate OnDeselect and
OnSelect to whatever class is implementing
the ISelectionResponse. And that's our
highlight indicator and outline
selection responses. But I know that
we're going to be prototyping some more
of these selection responses and I don't
want to keep having to mess around with
my hierarchy in order to test them all.
So let's create a composite selection
response that will inherit from
ISelectionResponse and still call
OnSelect and OnDeselect but delegate a
step further to whichever selection
response it's currently pointing at.
So to start out I'll create a new class
and call it CompositeSelectionResponse
and first things first have it implement
ISelectionResponse. Now I want to treat
this like a component so I'm going to
also have it derived from MonoBehaviour.
Perfect. Now I know I need to have some
sort of reference to a list of selection
responses so I'll create a list of those.
And I'm also going to need to keep a
reference to the current index so I'll
add an int to represent that. Alright now
in the OnSelect and OnDeselect methods
all I need to do is delegate the task to
the current selection response. So call
OnSelect and pass down the selection
and do the same for OnDeselect.
Alright good start.
But we may not always have a selection,
say if the list changes or is empty so.
I'm going to wrap these in an if
statement to check that. Let's create a
method called HasSelection and I'll
wrap both of these with that. And of
course we'll need to implement a
selection. And in HasSelection all I
really need to do is just make sure that
the current index is valid so I'll check
if the current index is greater than
negative one and less than the count of
the selection responses list. Alright.
So the next thing we'll need to do is
expose a method that allow us to call
next on this composite selection
response so we can cycle through all of
the responses. So create a method at the
top here. We'll call it "Next".
And in here we're going to need to
increment the current index. But if we
just blindly increment it we're going to
go past the size of the selection
responses list so we're gonna need to
factor that in. So I'll just set current
index equal to current index plus one,
modulus the selection responses count.
And we're gonna need to wrap current
index plus one in parentheses so that
gets evaluated first. And then for now,
just so we can test this really quickly,
I'm going to add a context menu called
next. So when we go to test this we can
just right click on the component and
click Next and see this in action. But
before we do that we need a mechanism
for retrieving these selection responses.
Unfortunately you can't serialize a list
of interfaces. It just doesn't work in
the editor, so I won't be able to drag
the selection responses on to this
component manually. So there's a couple
ways I could approach this. I could maybe
use reflection to instantiate all of my
selection responses at one time or maybe
just instantiate them right here. But I'd
like to have a little more granular
control, so I think what I'm gonna do is
have a GameObject that's going to hold
these selection responses and then I'm
just going to grab the selection
responses off of that GameObject at the
start of the scene. So I'll add a
reference to a GameObject that I'll
call "SelectionResponseHolder" and then
at the start of the scene I'll go ahead
and try to grab a list of all of the
selection response components it has.
So I'll call GetComponents and then use
that to initialize this list and I'll
just inline that so it's cleaner. Perfect.
Alright this should be enough to get
us started so why don't we hop back into
Unity and see this baby in action.
So, of course, one last time we're gonna
need to go over to the hierarchy and
create a new selection manager.
So I'll just duplicate my latest one,
disable it, and we'll call this "composite".
And remove the indicator selection
response and replace it with our new
composite selection response. And, like I
mentioned before, we're gonna need to
give it a GameObject that has all of
the selection responses that I'd care to
test. So I'll add a new GameObject to
the scene and call this selection
response. And then, since have already
configured three of my selection
responses, I'm just going to go ahead and
right click and copy these components to
this object.
Alright so now we can go to the
selection manager and drag the selection
responses object to the selection
response holder field on composite
selection response. And then if I click
on the cog here, we can see that next
context menu that I mentioned earlier.
And when we run the scene I'll just go
ahead and click this and we can cycle
through. Why don't we go ahead and test
that now. So we'll press play.
Off the bat this is a really good sign.
We see that we have something working
here. Now let's go ahead and test the
next button. So I'll go over to that cog
and click next and hopefully that would
have called the next function and
iterated on that current index. And it
did. Look at that. Let's do it one more
time. Beautiful! Look at that so now
we're able to iterate over these
selection responses and I can implement
as many as I want and all I really need
to do is just drag them on to this
selection responses holder object and
I'll be able to cycle through them
really quickly at runtime. Except not as
quick as I'd like because I have to
still come over here and click this cog
and click on next, and that's a little
annoying. I'd like to be able to just hit
a key on my keyboard and cycle through
them so why don't we implement something
of a switcher that'll allow us to do
that. It shouldn't take that long so
let's switch back to the code editor and
see what we can come up with. Alright
right off the bat I want to keep this
generic so why don't we create a class
and give it a generic name like "Switcher".
And Switcher will be responsible for
toggling through all of the options on
something like the selection manager,
which it'll do in response to some sort
of player input. In this case I think
we're just going to keep it simple and
use some keyboard input. So let's get
started by implementing MonoBehaviour
and the update method. And we'll just do
a check for Input.GetKeyDown and I'll
just use the N key for next. Alright.
Now when the N key is pressed we want
to be able to call next on the selection
manager, but I don't want the Switcher to
have a reference to selection manager
because it's too tightly coupled. I want
to keep this generic so why don't we
create an interface called IChangeable
and we'll give it a method called Next.
That way Switcher will just have a
reference to all of the IChangeable
objects in the scene and it can iterate
through them and call next. And to do
that it's going to need to have a
reference to a list of these I
IChangeables, so let's add that and now.
We can go ahead and loop through the
changeable objects and call next on each
one. Alright.
So similar to before, I'm just going to
expose a list of GameObjects that we
can use to just grab the components. Now
obviously this method has its caveats. You
have to set it by hand and maybe it's
not optimized if you had a lot of
changeable objects in your scene. But
because we're taking an iterative
approach this method works just fine for
now. And I'll keep it as a public field
so that later on if I needed some other
class to be able to access it and update
it we could do that as well. Alright so
in the start method now we can go ahead
and initialize that list and I'm just
going to loop through these grab the
changeable object using GetComponent
and add it to the list of changeable
objects. Perfect. And we really should
initialize this list so we don't run
into any issues. Perfect. The last thing
we need to do before we can test this is
have the composite selection response
implement IChangeable. And that's it
because the next method is already here
and we can see that we are now
implementing it from the IChangeable
interface. Alright let's switch back to
Unity and now we can quickly set up the
scene by creating a new GameObject.
We'll call it "Switcher", add the switcher
component, and then add a reference to
the selection manager.
Perfect! Let's test this out. Alright so
we can see by default that we are using
the highlighter but if I were to hit N
on my keyboard
we should have triggered the switcher.
And there you go. Now the objects are
being outlined. And if I hit N again,
now the indicators are showing up. But
there's one small problem. If I trigger
the switcher while I'm currently
selecting an object, we can see that it
doesn't properly deselect the object. And
now we can see that the indicator and
now the highlight are still being shown
on these two objects. So we can fix that
with a real quick change. Let's switch
back to the code editor and address that.
The problem is that the next method is
not updating the object that's currently
being selected with the new selection
response so all we have to do to fix
that is before we update the current
index we just need to call the current
selection response's OnDeselect method
and then the next selection responses
OnSelect method. But as you can see we
don't have a reference to the current
selection so now we just need to make a
quick update to our code. We're going to
add another private field that will
store the current selection. So on
selection I'll go ahead and update that
field and same with OnDeselect. Alright
now we can take that selection and pass
it on into the Next method. alright let's
give that a try.
Back in Unity we can go ahead and press
play. And we can see that, now that I'm
selecting an object, if I hit N on my
keyboard, the switcher now correctly
toggles through these selection
responses. And now it doesn't matter if I
have three or a hundred of these, it's
very easy to just test them out and see
which one's I like and which ones I
don't like in my scene. And this concept
doesn't just apply to this particular
example. But tooling in general for your
game is a really important concept that
makes it easier to scale your game for
the people who will be designing it.
So that you're not always digging in the
code, but instead providing tools to
higher-level team members who may not
have programming skills and would prefer
to just use an editor that you create
for them. In case you didn't know, this
video is a part of a series of videos
that covers game development and
programming topics in Unity. So if you
enjoyed it then you'll definitely want
to check out the playlist that can be
found in the description. If you liked
this video then please leave a like and
a comment letting me know what you
thought. And as always I'll catch you in
the next video.
Thank you to all of my Patrons and a
special shout-out to Dark Rush
Photography, Justin Hurst, NZ, Richard
Stanz, Sean Carry, Thomas, Wayne Glows, and
Yakov.