Do you want a way to give your Core players a Health Boost but you're not sure how? Check out this tutorial on how to make a Health Pickup in Core that increases your health when you consume it.
How To Create A Health Pickup In Core
In this example, I will show you how to make a Health Pickup item that restores 10 Hit Points when you touch it.
We will use the finished product as a basis for expansion in future articles where we will talk more about adding more functions and optimizing for network use.
Let's get started!
The Requirements:
Consumed on touch regardless of how many HP you have.
Cannot go over MaxHP
Plays 1 video effect
Plays 1 audio effect
Restores 10 Hit points
We're going to need:
- A trigger to detect when the Character has touched the Health Pickup.
- A script to take action when the trigger is touched.
- A sound effect to play
- A video effect to play
- A 3D mesh to represent the Health Pickup in the game
Getting Started: Laying Out A Framework
Create a new project.
Create a new Group called Health Pickup.
Make the group Networked.
Inside the Health Pickup Group make the following:
Create a Trigger and rename it Health Trigger.
Create a blank script called Health Pickup
Create two Groups:
- FX (to hold the audio and video FX for the health pickup)
- Health Geo (to hold the geometry of the pickup item)
Your Health Pickup Group hierarchy should look like this:
Next, let's start filling in the groups.
Move the Health Pickup script so it is under Health Trigger.
In the FX Group:
- Add in an Audio Effect of your choice to be played when the Health Item is picked up. Call it Health Audio Effect. For this example, I used Magic Sparkle Heart Whoosh 01.
- Add in a Video Effect of your choice to be played when the Health Item is Picked up. Call it Health Video Effect. For this example, I used Heart Volume FX.
Add a 3D Object of your choice to the Health Geo Group. This will be the item displayed in the game as the Health Pickup. For this example, I used Heart - Polished.
Remember to drag these directly to the hierarchy so they are all created at the origin point (0,0,0).
The hierarchy should now look like this:
The workspace should look something like this:
Interacting With The Trigger
Our script needs to know when a Character has touched the bounding box of the Health Trigger.
Open up the Health Pickup script and enter the following:
local TRIGGER = script.parent
function GetHealthPickup(trigger, other)
if other:IsA("Player") then
print(trigger.name .. ": Begin Trigger Overlap with " .. other.name)
end
end
TRIGGER.beginOverlapEvent:Connect(GetHealthPickup)
Let's take a look at that line by line.
local TRIGGER = script.parent
Here we are defining a Constant called TRIGGER and setting it to be the parent of this script. I like to make scripts as children to the switches that control them. If more than one switch can control a script, then I will make them at the sibling level. Let's keep this example simple for learning's sake.
Next, we define a function to be called whenever the Trigger's bounding box is touched.
The function receives the trigger that is being touched and the object that is touching it.
function GetHealthPickup(trigger, other)
...
end
The function checks to make sure the object that touched the Trigger is a Player and not another Core Object.
If the object is a Player, then a message is sent to the Event Log.
if other:IsA("Player") then
print(trigger.name .. ": Begin Trigger Overlap with " .. other.name)
end
In Lua, functions must be defined before they can be called.
On the last line, we have the only piece of code that will run every time the Trigger bounding box is touched. We use that event to call the OnBeginOverlap() function.
TRIGGER.beginOverlapEvent:Connect(GetHealthPickup)
-- function called whenever an object overlaps the Trigger's bounding box
-- whenever an object overlaps the Trigger bounding box, call the OnBeginOverlap() function
Ok great!
Now we have a working script and it is commented so the next time we work on it we won't forget what we were doing.
Let's Test Our Trigger
Since the Health Pickup has been created at the center of the map, it might overlap the Spawn Point for your Character, so move the Spawn Point off to the side while creating this object.
By creating it at the center of the map, it will be easier to manipulate and make into a Template later.
Open the Event Viewer (Window> Event Viewer), and run the game in Preview Mode.
When you touch the Health Trigger bounding box you should see a message in the Event Viewer.
If things went wrong, check the Event Viewer for details, or make sure the script is a child of the Health Trigger.
Now that we have been detected crossing the trigger, let's give ourselves some hit points.
Adventurer, Heal Thyself!
We want to heal ourselves for 10 points, so we need another constant to hold the Healing Amount.
At the top of the script, find this line:
local TRIGGER = script.parent
..and insert immediately after it:
-- set the amount to heal
local HEALING_AMOUNT = 10
Let's add a line after the Event Log message that actually adds to HP and sends us a message with the new hit points.
Find this line:
-- send a message to the Event Log for troubleshooting purposes
print(trigger.name .. ": Begin Trigger Overlap with " .. other.name)
...and insert this immediately after it:
Run the Preview game and touch the Health Item, your Hit Points should be going up by 10 each time.
Put A Cap On Over-healing
We don't want the Health Pickup to take our health over MaxHitPoints, so let's make a modification that prevents Hit Points from exceeding the maximum.
After this line:
other.hitPoints = other.hitPoints + HEALING_AMOUNT
Insert this:
Save the script and test in Preview mode.
Now you should get the message that your health is at 100 when you touch the Health Pickup. This is happening because you are not hurt and are already at Max Hit Points.
Well, everything seems to be working so far - except that pesky Health Pickup is just sitting there, giving us health every time we touch it, but we want it to be consumed the first time a player touches it.
Destroying Yourself
We want to object to destroy itself after it has been consumed so that it can only be used once. We can do that with the Destroy command.
First, we need to create a reference to the Trigger's Parent, then we need to destroy the parent (from the game world).
It is possible to trigger the Destroy more than once, due to timing issues, so we'll check to see if it has already been done before calling the Destroy command.
At the top of the script, find this line:
Now that we have this Object's ID, we can destroy it when consumed.
Find this section:
And insert this line below it:
-- destroy the Health Pickup so it is consumedif Object.IsValid(HEALTH_PICKUP) then
HEALTH_PICKUP:Destroy()
end
Now save the script and run it in Preview mode.
You should now heal 10 points (up to your max hit points) if you are below max, and the Health Pickup will disappear when consumed.
Adding Effects
Now, it would be nice to have some feedback when the Player consumes the Health Pickup.
Drag the Health Audio Effect and Health Video Effect to the ADD CUSTOM Property button on the script Properties to provide access to the script.
At the top of the script, in the section where the CONSTANTS are defined, find the following line:
...and insert right the following:
This code can be copied from the Custom Properties panel after you drag the Effects to the Custom Property button. This will give us the IDs of the two Effects we want to play.
Next, locate this section:
...and insert this BEFORE the HEALTH_PICKUP:Destroy() line:
Turn off Autoplay on the Health Video Effect so it doesn't start after spawning and is only turned on through scripting.
Now, when you run the Preview mode to test, you will see the visual Effect, hear the Audio Effect, and there will be a 2-second pause to give the effects a chance to play out.
The script should look like this:
-- CONSTANTS
-- get the Trigger ID from this script's parent
local TRIGGER = script.parent
-- set the amount to heal
local HEALING_AMOUNT = 10
-- get the ID of this object - the parent of the trigger
local HEALTH_PICKUP = script.parent.parent
-- get the ID of the audio effect
local HEALTH_AUDIO_EFFECT = script:GetCustomProperty("HealthAudioEffect"):WaitForObject()
-- get the ID of the video effect
local HEALTH_VIDEO_EFFECT = script:GetCustomProperty("HealthVideoEffect"):WaitForObject()
-- function is called whenever an object overlaps the Trigger's bounding box
function GetHealthPickup(trigger, other)
-- check to make sure this is triggered by a player (rather than another Core Object)
-- only activate if this Health Pickup has not already been used
if other:IsA("Player") then
-- send a message to the Event Log for troubleshooting purposes
print(trigger.name .. ": Begin Trigger Overlap with " .. other.name)
-- add points to health
other.hitPoints = other.hitPoints + HEALING_AMOUNT
-- if the player's hitpoints are now greater than max, make them equal to max
if other.hitPoints > other.maxHitPoints then
other.hitPoints = other.maxHitPoints
end
-- play the video and audio effects, pause to let the effects play out
HEALTH_VIDEO_EFFECT:Play()
HEALTH_AUDIO_EFFECT:Play()
Task.Wait(2)
print("Player Hit Points: " .. other.hitPoints)
-- destroy the Health Pickup so it is consumed
if Object.IsValid(HEALTH_PICKUP) then
HEALTH_PICKUP:Destroy()
end
end
end
-- whenever an object overlaps the Trigger bounding box, call the GetHealthPickup() function
TRIGGER.beginOverlapEvent:Connect(GetHealthPickup)
We now have a working Health Pickup!
There are two small things I'd like to fix:
- The Health Geo should be set to no collision since I consume it by hitting the Trigger bounding box anyway.
- The Health Geo should go invisible when touched, while the effects are played.
Let's start with the collision.
Finishing Touches
Just a few more modifications!
Turning Off Collision
First, turn off the collision of the Health Pickup geometry by making sure it is set to Inherit From Parent then go to its parent (Health Geo) and turn off the Game Collision property. This will allow the player to collect the health Pickup by running through it or otherwise touching it somehow.
Making The Health Pickup Disappear
Now we want the Health Geo to disappear when we "consume" the Health Pickup.
To access the properties of Health Geo, drag it to the script's properties then add this line to the end of the CONSTANTS/Custom section:
Find this line:
HEALTH_GEO.visibility = Visibility.FORCE_OFF
One Last Thing
It is possible to trigger the script more than once by leaving the Trigger and then quickly reentering. To keep this from happening we should define a local variable for a flag status to keep track of if the item has already been used before it could be destroyed.
-- set a flag to detect if the pickup has already been used once - prevents double-dipping the health pickup
local used = false
That's it!
Congratulations on making it to the end of the tutorial! You should now have a working Health Pickup item.
Don't forget to make it into a template so you can reuse it.
The final script should look like this:
-- CONSTANTS
-- get the Trigger ID from this script's parent
local TRIGGER = script.parent
-- set the amount to heal
local HEALING_AMOUNT = 10
-- get the ID of this object - the parent of the trigger
local HEALTH_PICKUP = script.parent.parent
-- get the ID of the audio effect
local HEALTH_AUDIO_EFFECT = script:GetCustomProperty("HealthAudioEffect"):WaitForObject()
-- get the ID of the video effect
local HEALTH_VIDEO_EFFECT = script:GetCustomProperty("HealthVideoEffect"):WaitForObject()
-- variables
-- function is called whenever an object overlaps the Trigger's bounding box
function GetHealthPickup(trigger, other)
-- check to make sure this is triggered by a player (rather than another Core Object)
-- only activate if this Health Pickup has not already been used
if (other:IsA("Player") and used == false) then
-- send a message to the Event Log for troubleshooting purposes
print(trigger.name .. ": Begin Trigger Overlap with " .. other.name)
-- turn off the geometry of the Health Pickup
HEALTH_GEO.visibility = Visibility.FORCE_OFF
-- add points to health
other.hitPoints = other.hitPoints + HEALING_AMOUNT
-- if the player's hitpoints are now greater than max, make them equal to max
if other.hitPoints > other.maxHitPoints then
other.hitPoints = other.maxHitPoints
end
-- play the video and audio effects, pause to let the effects play out
HEALTH_VIDEO_EFFECT:Play()
HEALTH_AUDIO_EFFECT:Play()
Task.Wait(2)
print("Player Hit Points: " .. other.hitPoints)
-- destroy the Health Pickup so it is consumed
if Object.IsValid(HEALTH_PICKUP) then
HEALTH_PICKUP:Destroy()
end
end
end
-- whenever an object overlaps the Trigger bounding box, call the GetHealthPickup() function
TRIGGER.beginOverlapEvent:Connect(GetHealthPickup)
Customizing The Health Pickup
It's easy to customize this for different Health Pickups.
Changing The Healing Amount
If you want to change the amount the Health Pickup restores, change the value of HEALING_AMOUNT.
Changing The Audio and Video Effects
If you want to substitute your own Health Video Effect and Health Audio Effect, just delete the existing Effects and be sure to rename the new Effects as Health Audio Effect and Health Video Effect respectively so the script can access them next time.
Once you have renamed the Effects, be sure to drag them to the appropriate empty slot in the Custom Properties of the script.
Changing The Health Pickup Geometry
You can use any 3D Object or group of objects just by dropping them in the Health Geo group. Don't forget to adjust the bounding box of the Trigger so it encompasses the Health Geo Group.
Conclusion
I hope you enjoyed this tutorial and I hope it helps you learn more about the Core Game Engine. Follow me for more informative articles like this one!
Join My Game Dev Journey!
It's nice to have company on a long trip.
If you want to follow my production progress, check my blog at MakeYourOwnRPG.com.
You can also join the CyborgPrime Discord server, where I post my progress and interact with the community.
Click here for more articles in this series about my Core Game Engine game dev journey.
Your Turn. What Do You Do?
Did you find this article helpful? Do you have a different way of doing Health Pickups?
Please share with us in the Comments section below. Let me know faster/easier/better ways to do things in Core.
If you found this article helpful, please give it a good rating at the top, thanks!
E-mail Notification Opt-in
Do you want to follow my Core Game Engine game dev journey?
Sign up on my private mailing list.
YES! Please notify me of new Core Game Engine game dev posts!
You can also join me and my friends on the CyborgPrime Discord server.