Attracting Power-ups in Unity


For today’s article, I’ll be going over how to implement attracting multiple power-ups nearby the player ship. To see the full code-base for reference and to follow along more closely, please visit my github repo:

Adding Attract Behavior in Player Script

Auto-attract ability in effect

In the Player script:

Breaking this script down:

  • I use FixedUpdate() function over Update() function because I’m using the Physics2D.OverlapCircleAll() function as Physics related calculations should be made in FixedUpdate()based on Unity’s Documentation.
  • Physics2D.OverlapCircleAll() returns an array of Collider2D objects where I pass in the current location of the powerup, attract-radius, and layer mask. The layer mask is responsible for only filtering in game objects that belong to the power up layer mask which can be set in the Unity Editor:
Setting all power-up prefabs to Powerup Layer Mask
  • On every FixedUpdate() call, I make a call to Physics2D.OverlapCircleAll() to determine which new power-ups to add to attractedPowerups list. One of the problems I ran into when implementing this solution was determining if my list of attracted power-ups are valid on the next physics step.
  • The way I resolved this issue was using a HashSet to hold a unique set of PowerUp components and checking in the list if the Power-up still exists in the set. If it does not exist in the set, I remove the stale power-up from the list and decrement the loop counter by 1. Note: Decrementing the loop counter by 1 when removing a power-up ensures we don’t skip over a power-up when checking for stale power-ups. Lists behind the scenes will shift valid entries to the left by 1 when deleting an entry in the middle of the list.
  • Lastly, I add all the new power-ups into the list and to make sure they are all unique copies, I use a HashSet and convert it back to a list afterwards.

Movement Code

  • Here I use isAttracted flag to prevent default movement of the power-up when attracted to the Player ship.

Visualizing Attraction Radius in Unity Editor

I wrote a script named PlayerInspector.cs which needs to be stored in the Editor directory in order for Unity to recognize it as a Custom Editor tool. Below is a script snippet where I use OnSceneGUI() function to draw a circle that represents what Physics2D.OverlapCircleAll() would look like:

The OnSceneGUI() function will allow us to view the red circle drawn above when the Player game-object is selected in the Game Hierarchy view. The CustomEditor attribute allows us to define what Component this Editor script is for. In my case, it is used only for game objects with the Player component attached.

Thanks for reading :)

Software Engineer