Module 6 - Game Start and Collection
Manually triggering game start
Bring those gems back!
A common way to have players start a game is to add a Trigger Zone gizmo that players walk through. Let’s set that up in our game.
In the desktop editor, select Build menu > Gizmos :
Select gizmos from the Gizmos panel
Click the Trigger Zone icon to add a trigger zone to the world:
Select Trigger Zone gizmo
Click the Move tool in the toolbar. Move the Trigger Zone to the Start platform in the corner of the provided course.
Scale the trigger zone using the Scale tool available in the toolbar. Make it the same length and width of the visible, raised platform
Select Scale tool in the toolbar
My course looks like this now:
Trigger zone has been positioned and resized
Trigger zones support some useful built-in Code Block Events. Each time a player enters the trigger zone, the OnPlayerEnterTrigger event fires. To access this event, we attach a script to our trigger zone entity and build the code there.
- In the Script panel, create a new script.
- Name it StartGameTrigger.
- In the Main window, select the trigger zone entity.
- In the Properties panel for the trigger zone entity, attach the new StartGameTrigger script.
- Open the new script in your editor.
In the start() function, connect to the OnPlayerEnterTrigger event. Arguments:
- Reference to the trigger zone (this.entity)
- Reference to the onPlayerEnterTrigger event.
- This event takes a callback as the third argument and passes the player object to that callback. Below, this player reference is named enteredBy and can be referenced, if needed, in the callback function.
As we did before, create an event handler method for this event binding and call to it from within the callback function:
start() {
this.connectCodeBlockEvent(
this.entity,
hz.CodeBlockEvents.OnPlayerEnterTrigger,
(enteredBy: hz.Player) => {
this.handleOnPlayerEnter();
}
);
}
private handleOnPlayerEnter(): void {
}
We already set up our GameManager script to subscribe to setGameState events. So, we import the event and GameState enum into our ResetGameTrigger:
import {setGameState, GameState} from 'GameManager';
We can configure our event handler to emit an event to start the game
private handleOnPlayerEnter(): void {
this.sendLocalBroadcastEvent(setGameState, {state: GameState.Playing});
}
Done with setting up the gems and the triggering of them into the world. We can verify all of the work we have done.
- Click the Reset world simulation button in the toolbar.
- Press the Play button, then enter the world in preview mode.
- When first entering preview mode, you should not see any gems in your course.
- Run through the Start platerform area which has our trigger zone.
- All of the gems should appear in your course!
If you are not seeing the expected results:
- Review console for scripting errors.
- Verify that all scripts are attached and props, on triggers and gems, are set.
The gems hide and show correctly, but running into them doesn’t do anything. We must set up the collision events between players and gems.
Click the Stop button in the toolbar to stop the simulation, which stops all scripts from running and returns the gem objects to their original (hidden) position:
Press Stop to halt playback of the simulation
For a platform-style game, a player should “collect” a gem by simply running into it. Whenever a player collides with a gem, an event should fire to handle the effects of collecting the gem. We can configure our gems to receive collision events in the Properties panel for each gem .
Properties of the selected gem
Select one of the gems on your course and configure the following properties:
- Collision Layer: Players Only.
- Our demo game here has no other objects in motion, so this setting is not important at present. However, it’s a good practice to scope as tightly as possible, in case you decide to add other objects in the future.
- Motion: Interactive
- Interaction: Grabbable
- In this game, we just want a player to collect a gem when colliding with it. We do not want the player to have to physically grab a gem.
- However, we need Grabbable to be set for our gems to be interactive and to receive events from player interactions.
We can still set up our objects to behave exactly like we want them to.
Collision properties of the selected gem
Set the following collision-related properties:
- Collision Events: Players
- Disable events from Player Heads and Player Hands.
- Player Torsos: Enable.
- To avoid multiple collision events from firing when a player runs into a gem, we only need events from the player torsos.
- To disable the default grabble behavior, set Who Can Grab? property to Script Assignee(s).
- With this setting, you must explicitly set a player as an owner in TypeScript for an object to be grabbable by that player.
- In our game, we won’t set an owner in TypeScript which will give us the exact “collect” interaction we are after.
Repeat the above property definitions for each gem.
Our gem properties are now set up how we want them. The next step is binding to the correct Code Block Events.
Press the Play button to activate the world simulation, which also executes scripts:
Press Play button to start the simulation
In the GemController script, in the start() function, add a new Code Block event listener for the built-in OnPlayerCollision event:
this.connectCodeBlockEvent(
this.entity,
hz.CodeBlockEvents.OnPlayerCollision,
(collidedWith: hz.Player) => {
this.handleCollision();
},
);
And, as we have done before, create event handler method named handleCollision():
private handleCollision(): void {
}
We can verify collisions are working as expected by adding a console log to the event handler:
private handleCollision(): void {
console.log('gem collision');
}
Console tab
It works!
Our collision events are triggered from the player’s torso only. If the gems aren’t collecting, verify that the position reference objects are placed close to chest height on your avatar.