-
Notifications
You must be signed in to change notification settings - Fork 5
Getting Started
To start making your own custom energy bar, clone this repository or download it as a .zip, then open "CustomEnergyBar-Template" in Unity 2018.1.6f1. Your Unity version must be 2018.1.6f1 or else this may not work. Open the "Template" scene found in the "ExampleBar" folder in your asset browser.
Custom Energy Bars consist of two main scripts: EnergyBarDescriptor and EventManager. You'll mostly be focusing on the EventManager script as it's what drives your energy bar's dynamics like losing/gaining energy, initialization, losing/gaining battery life, and more. Click on the CustomEnergyBar object in the hierarchy. You'll see the EnergyBarDescriptor script attached to it. This holds metadata information like the title, author, and icon. It also allows you to export your energy bar as a .energy file that you can share and put in the "CustomEnergyBars" folder in your Beat Saber directory. If you want to test to see if your Unity environment is set up correctly, export the example bar to your CustomEnergyBars folder. If the energy bar loads in Beat Saber, you're good to go.

If you expand the CustomEnergyBar>Canvas objects, you'll see three objects named "StandardBar", "4LifeBar, and "1LifeBar". These all house different styles of energy bars. StandardBar being your default energy bar seen when you play with no modifiers. 4LifeBar being for the four-life battery life modifier. And 1LifeBar being for the one-life instant fail modifier. NOTE: You aren't required to make a 4LifeBar and 1LifeBar energy bar, and instead the StandardBar will be used whether you choose a "battery life" modifier or not, however, for completeness of your energy bar, it's recommended to make them anyway.
These GameObjects (StandardBar, 4LifeBar, 1LifeBar) must have these exact names for it to work in Beat Saber. Also, if let's say a 3 life modifier came out, you can make a 3LifeBar GameObject and it will work as expected. The battery life bars are made to be future proof in that sense.

As mentioned before, the EventManager script is the most important script as it connects game events to your energy bar to drive animations and component values. Currently there are five main events:
-
OnInit()- Called when the energy bar is spawned (basically when the game scene is loaded). -
OnEnergyReachedZero()- Called when the player's energy reaches 0. -
OnEnergyIncreased()- Called when the player's energy increases. -
OnEnergyDecreased()- Called when the player's energy decreases. -
OnEnergyChanged(float)- Called when the player's energy changes; returns a float that can be used for Animator BlendTrees and such (more on this later).
And two events for the battery life bars:
-
OnBatteryLivesIncreased()- Called when the player's battery life increases. This is pretty much useless as the battery life never increases in-game, but it's there just in case. -
OnBatteryLivesDecreased()- Called when the player's battery life decreases.
With these events, you are able to plug in any component attached to any GameObject in your custom energy bar and control parts of it. You will probably mostly be using the OnEnergyChanged(float) event as it contains the actual energy amount from 0-1. This value can be used for things like a Sprite's fillAmount or an Animator's parameters. An EventManager script can be attached to any GameObject and on as many GameObjects as you want, however it is recommended that you have one EventManager for each bar type (StandardBar, 4LifeBar, 1LifeBar) so then only one is activated at a time in-game for efficiency purposes.
The two battery life events (OnBatteryLivesIncreased() and OnBatteryLivesDecreased()) use an array of UnityEvents that get called in a certain order. For example, for the 4LifeBar, you must make the size of this array 4 as there are, well, 4 lives. The element index (+1) of each event is associated with the player's current life. For example, if you had 4 Sprites that represented the player's lives and you wanted to deactivate them as the player lost lives, Element 3 would contain the first sprite to be deactivated (the one furthest to the right on the default battery life bar), and Element 0 would contain the last sprite to be activated (the one furthest to the left) before the player fails the level. If any of this sounds confusing, take a look at how the Example Bar does it:

These two events can also be used with a StandardBar. For example, for a LEGO Star Wars health bar that consists of four hearts. The left-most heart object would be placed into Element 0 while the right-most heart would be placed in Element 3. This makes sectioned health bars a lot easier to work with as you won't have to do things like creating animations for each health state or a shader, instead you can simply activate/deactivate the health sections based on how much health is left.
In the EventManager, you will also notice a boolean labeled "Deactivate On Energy Reached Zero". When checked, the energy bar will automatically deactivate once the player's energy reaches zero. Turn this off if you want to do anything before the energy bar disappears, like playing a sound effect for example. You will however have to deactivate the bar yourself through OnEnergyReachedZero or an animation.
While the EnergyBarDescriptor and EventManager scripts are important for defining how your energy bar works in Beat Saber, there are still some scripts to take a look at to help you make a great custom energy bar.
The AnimatorEventHandler script is used to modify an Animator's parameters through the OnEnergyChanged(float) event. Since, by default, Animator parameters can't be modified directly by a UnityEvent, this script is necessary to do so.
To use this script, attach the AnimatorEventHandler script to a GameObject and assign an Animator that contains a float parameter. Type the float parameter's name into the "Parameter Name" text box in the AnimatorEventHandler component. In your EventManager, drag the GameObject that contains the AnimatorEventHandler component onto OnEnergyChanged(Single) and choose "AnimatorEventHandler.SetFloat". Then in-game, the animator parameter will change based on the player's energy.
You will also notice an AnimationCurve variable on the AnimatorEventHandler labeled "Interpolation". This curve is to customize the way the float value is set over time, assuming your animator property is a float. By default, the value is instantly set to whatever the event sets it to, but this can be changed using this curve. On the y-axis, a value of 0 on the curve denotes the old value of your float animator property while a value of 1 denotes the new value. The x-axis represents the time it takes to go from the old value to the new value. By default, the time it takes to go from the old value to the new one is 0.01 seconds. You can drag the last keyframe on the curve out to, say, a value of 4 to make the transition last 4 seconds. This is useful if you would like to animate elements of your energy bar based on a gradual change from the old to the new energy value.

The AnimationEventHandler script is very similar to the AnimatorEventHandler, but instead of being used to modify a parameter, it is used to play an animation clip.
To use this script, attach it to a GameObject and assign an Animation component. On your EventManager, drag the GameObject that contains the AnimationEventHandler script onto any of the events and choose either "AnimationEventHandler.Play" or "AnimationEventHandler.StopAndPlay". Type in the AnimationClip name that you have put inside the Animation component's Animations array. The difference between Play and StopAndPlay is that Play works similarly to an Animator in that it will wait for the previous animation to end before it plays the next one while StopAndPlay will stop the current animation and play the next one immediately. This is useful for the OnEnergyDecreased and OnEnergyIncreased events that fire multiple times very quickly in-game.

The MaterialEventHandler component is used for controlling shader properties on specific materials in your project. It works very similarly to the AnimatorEventHandler where you input a property name (for example: _Color or _Fade), choose an interpolation curve if necessary, and assign a material to the handler.
The EnergyText script is used for text-based energy readings. To use this script, attach it to any TextMeshProUGUI GameObject. Choose whether you want to display the energy as a percent, decimal (0.00-1.00), or a battery life value. The Formatted String text box is where you will write how you want it to be displayed. For example, you can type Energy: {0} into the Formatted String box and it will display as "Energy: 50%". The "{0}" gets replaced by the energy value. Another example: Ni {0} ce will display as "Ni 0.69 ce". The "Battery Lives" field is used for the "Battery" display type which is where you must input the number of battery lives of the bar you're editing for it to work properly.
Let's make sure you've done everything correctly:
- You must have everything contained inside a root GameObject
- Your energy bar must contain a StandardBar GameObject
- Your energy bar may optionally contain a 4LifeBar and 1LifeBar GameObject
- Your root GameObject must have an EnergyBarDescriptor script attached to it
- To use events, an EventManager must be present and contain some values
To test your custom energy bar's events, use the EventTester script. Attach it to any GameObject outside the energy bar root, assign an EventManager, hit the play button to enter play mode, and click the buttons to test various events. Once you're done, make sure to edit the information in the EnergyBarDescriptor and hit Export. Test it out in Beat Saber to make sure everything works there and you're done. Congratulations on making your own custom energy bar!