Creating An Event Driven, Click to Move System Using ScriptableObjects.
First, let me introduce you to one of the best free assets on the Unity Asset Store. Scriptable Object Architecture.
This incredible asset was based on Ryan Hipple’s 2017 Unite Talk. I HIGHLY recommend you watch this talk before reading any further. You’ll still understand what's going on if you don’t, but this legendary talk will definitely make the big picture more clear.
If you want to go deeper, here is another talk by Richard Fine on scriptable objects.
The SOA asset took the principals from Ryan’s talk and wrapped them all up into a clean, intuitive package for us to use. And did I mention it’s free?
Let’s jump into creating an event system with this!
First, I’m going to show you how I would do this system without SO’s. I’ll just use the C# Actions and the observer pattern to make it work. Hopefully that will help this make more sense.
I’m going to use my personal project for this but you can easily follow along using primitives and a terrain.
As for the system, we’re going to make an event driven click to move system.
Create a terrain and then create a MonoBehaviour script called Walkable a put it on the terrain.
Now head into Walkable and let’s define a an Action<Vector3> called “onWalkableClick”.
Create an OnMouseDown() and set up a raycast from the mouse.
So now anytime we click on something with the Walkable script attached to it, we will fire a ray straight down from the mouse position.
We’re going to take that raycastHit and get the point where it intersects the Walkable object and raise our event while passing in that intersection point.
Now, Let’s create a script called ClickToMove with a required component of NavMeshAgent and a reference to the NavMeshAgent.
Cache a reference to the NavMeshAgent in Start.
Next, create a method called MoveToDestination that takes in a Vector3 parameter and in the method set the agent’s destination to that Vector3 parameter.
Now we need to subscribe this method to the Walkable Event we made earlier. Create an OnEnable() and OnDisable() method and subscribe and unsubscribe accordingly.
Ok, we’re almost done with this first part. Make sure you bake a NavMesh on the terrain and put the Walkable script on it as well.
Boom. Modular, event driven point to click system.
Let’s do this same exact thing with scriptable objects.
Download The SOA Asset form the asset store.
Make sure you check out the demo scene that comes with SOA so you can see what else it has to offer.
We’re going to create a Vector3 game event from the create asset menu.
Name this “OnWalkableClick”.
This is what you’ll see in the inspector.
Now let’s head to the Walkable script and define a reference to this game event. You can just comment out where we defined the Action<Vector3> of the same name. Make sure to plug in the game event into the game event reference on the Walkable script in the inspector.
Inside of OnMouseDown(), comment out the Invoke of the Action and call Raise on the Vector3 Game event reference, passing in the same raycastHit.point as before.
Now, head back out into your scene view and on your player character add the script Vector3 event listener.
Plug in the OnWalkableClick game event we created to ‘Previously Registered Event and Event and in the Response, drag in the ClickToMove Script and select the response method MoveToDestination.
Yall, that’s it. That’s the same functionality. When the game event gets raised, it will pass that RayCastHit.point to the event listener which will then pass that into MoveToDestination on the ClickToMove Script.
Click play and check it out!
I hope that can give you a taste of what is possible with ScriptableObjects. I plan on doing more articles using this asset so stay tuned.