We begin the game by creating the gun controllers that will move around our gun and fire bullets. This will also provide a basic introduction to Finite State Machines (FSM), events and actions, which are the core concepts that make up any playMaker game.
First, create an empty child object of PlayMaker Tutorial Game and name it gunController_R. This will be where all of the logic for the right gun controller goes. It will then be duplicated and altered slightly to create a similar object for the left gun controller. Please also note that in screenshots of the game development process, you may see an object called playmaker GameFinished in the scene hierarchy – this is only there for the purposes of writing this tutorial, so do not be alarmed that it is not present in your project.
Next, with gunController_R selected, right click in the PlayMaker editor and select “Add FSM” to add an FSM to the object.
An FSM, or Finite State Machine, is a machine that works based on transitions between different states. To accomplish this, it needs states, representing the current state of an object, and events, which are the transitions between them. A simple example of this would be a door opening and closing. The two states in the FSM representing this phenomenon would be open and closed, and the transitions between them would be called “open door” and “close door”. As we progress throughout this tutorial, you will become more familiar with all of these concepts and how they are used in playMaker.
Right-click again and then from the menu select Add State to add a state to the game. Name the state Setup. This will perform all the initial setup on our gun controller object.
Now go to the Actions window and search for the “Find Game Object” action, and click on it to add to the Setup state.
Next, enter “Controller (Right)” as the name of the object you would like to locate and store it in a new variable called “controller”.
The purpose of this action is to find the right controller in the scene and then store it in a variable that we can use in this FSM to perform certain actions on it. This works just like normal programming, except with this nice graphical interface. Next, we obtain the controller’s position in the scene by adding a Get Position action and setting the object to the controller variable we stored earlier, which represents the right controller. This position will be stored in a vector variable called controllerPosition, which we will use later.
Next, we store the current rotation of the controller in a variable called controllerRotation. To store the x, y and z rotation angles in one vector, we use the “Euler Angles” option and store these angles in the controllerRotation variable.
Next find the RainbowCrossbow asset from the asset list. It is stored inside the FPL_ISBIT weapons pack folder under 3D weapons.
Drag it into the Scene Hierarchy. This will allow us to make it into a prefab after editing it visually in the Unity Scene Editor. Make sure to set the Rainbow Crossbow’s Scale to 0.2, 0.2, 0.2 so that it is correctly sized when it appears in the game.
Next create a sphere as a child object of the RainbowCrossbow. This will act as the spawn point for the bullets.
Move the sphere to be directly in front of the gun barrel head and also disable the mesh renderer by unchecking the corresponding box in the inspector. This positions the sphere so it spawns bullets in the right location and also makes it invisible to the player, as we don’t want to actually see the bullets’ spawn point.
Next drag the entire RainbowCrossbow object into the myPrefabs folder to make it a prefab. Congratulations on making your first custom prefab for the game! It is incredibly easy to just create systems of entire objects in Unity and then turn them into prefabs like this. The great thing about playMaker is that every instance of that prefab that you put back into the scene will have exactly the same properties and FSM code, and you can also edit the FSM code of the prefabs directly without having to put them back into the Scene Hierarchy.
Also make sure to rename the sphere as spawnPointSphere so we can find it easily in the scene.
Once this is done and the prefab is made, delete the RainbowCrossbow from the Scene Hierarchy to remove clutter.
Next, we are going to attach the RainbowCrossbow prefab to the controller to make the actual gun. With the right gun controller selected, go to its FSM and add a Create Object action. The object we want to add is the RainbowCrossbow prefab, which can be accomplished by simply draggint the prefab into the Game Object field of the action. We want to set its position and rotation to that of the controller so it is in exactly the same orientation, and to do this we will use the controllerPosition and controllerRotation variables that we created earlier. Finally, save this as a new variable called “crossbow” so we can reference it later on.
After some experimentation with the crossbow’s angle relative to the controller, we found rotating it 40 degrees about the x axis put it in the best position to be perfectly horizontal when the user holds the VR controller in the most comfortable for firing the crossbow. Set this angle of rotation by adding a Rotation action from the action browser, like in the image below:
Make sure to un-check “Every Frame” since we only want to perform this rotation once!
Next create a Set Parent action and set the crossbow’s parent to be the controller. Setting the crossbow as a child of the controller with move the crossbow around with the controller at all times.
Next, add a Get Child action and locate a child of the crossbow object called spawnPointSphere. This will be a sphere with the same properties that we set directly in the Unity Scene Editor when creating the RainbowCrossbow prefab. Store this child in a new variable called spawnPointSphere for easy future reference.
Now we want to delete the model for the controller so it does not interfere visually with the crossbow model. Create another Get Child action and search for a child of the controller object named “Model”, which contains the 3D model for the VR controller. Store the result in a variable called controllerModel.
Next destroy the controllerModel variable with the Destroy Object action to delete it from the controller.
This whole process of finding the child model and deleting it with playMaker is necessary as we don’t have a prefab of the controller that we can directly edit in the Scene Hierarchy. Rather, the controllers will be created by the game and we must interface with them by locating them by name in the game world.
Next, we will code the rest of the logic for the right gun controller. Create a new state called “Waiting for Trigger” and make a transition called finished in the Setup state that connects to the new state. You can do this by right-clicking on Setup and selecting “Add Transition” and then “FINISHED” from the menu and then left-click dragging an arrow from FINISHED to the new state.
Next add two global events with the exact names “Global_TriggerPressDown_R” and “Global_TriggerPressUp_R” from the Events list. These names must be spelled exactly like this so they correctly interface with STYLY when we upload the game.
Next add Global_TriggerPressDown_R as a transition in the Waiting for Trigger state.
This trigger will eventually cause bullets to fire when the trigger is pressed down (so the crossbow is fired) by the user. Global_TriggerPressUp_R needs to be added as a global event from the Add Global Transition menu as follows:
The reason we add press up as a global transition is that when the trigger is pressed down, it will create a loop in which bullets continuously fire, and an easy way to get out of this loop is to simply have a global transition that takes the system out of the loop and right back to the Waiting for Trigger state without any other complex logic. This means that when you let go of the trigger, bullets will stop firing, which is what we want.
Next create a new state called “Spawning Bullet” and connect it to Waiting for Trigger via the Global_TriggerPressDown_R transition.
The first thing we are going to do in the Spawning Bullet state is to get the rotation of the spawnPointSphere in order to have the bullets orientated with their axes aligned to those of the spawn point sphere. This is necessary so that when we fire the bullet directly away from the gun, we know exactly which direction to apply the necessary force in to cause this motion. This can be accomplished by adding a Get Rotation action from the action browser and filling out the required fields as shown in the image below.
Next we need a Create Object action that will actually create the bullet. Set the spawn point of the bullet to be spawnPointSphere and the rotation to spawnPointRotation, which is the rotation of the spawn point that we just obtained with the previous action we added. For now, we will leave the Game Object field blank as we have not created the bullet prefab yet, but we will come back later to fill this in. playMaker helpfully put a red warning mark over the state to indicate that this is an incomplete action so we can easily find it later.
When Spawning Bullet is finished we want to spawn another bullet, however we want there to be some delay in between these actions. A nice way to do this without creating too much clutter in the Spawning Bullet state is to create a separate Waiting State that has a wait action in it. Create such a state as shown below and have it transition back to the Spawning Bullet state once finished. Also make sure that the Spawning Bullet state connects to the Waiting state once it is finished as well.
Inside the Waiting state, create a Wait action to have the state wait for 0.2 seconds. Set the finish even to FINISHED and check Real Time under the Wait action’s options menu, as we want 0.2 second of real world time to pass in-between each bullet.