Objective: “Simulate” magnetism in Unity for use as a Game Mechanic or an educational piece that looks cool
Game Development is all about smoke and mirrors. Although these look like magnets I’m sure a physicist is cringing at how inaccurate the simulation is and how “original” the code for it is.
This article will depict a simplified version of what I’ve made in the above GIF, but the main idea is all there
As always lets start with a quick breakdown of what we want our code to do:
- Be able to hold either a Positive, Neutral, or Negative polarity
- If the charges between two objects are are the same, then repel. If they are opposing, then attract. If one of them is neutral, then nothing happens
Very simple on paper and actually in code as well! For this we’ll be using Rigidbodies for quick and easy physics simulations in Unity. Now, let’s translate what this breakdown means into code.
Step 1: Adjusting Polarity
For my purposes I decided to use an Integer to determine whether or not the object was Positive, Neutral or Negative using a simple if statement like so:
The chargeStrength and minimumCharge variables are global variables in place to allow the user to adjust how difficult it is to change the polarity of an object. Mainly a gameplay thing and not necessarily the focal point of this article.
That’s step one done! Pretty straightforward, right?
Step 2: Behaviours Based on Polarity of Nearby Objects
Step 2.1: Determining the Correct Action
Using Integers made this process very easy as we can simply determine an action based on the product of the polarity of two different objects. Since we’re only using 1, -1, and 0 then the only values we’ll get if we multiply them will be the same set of numbers of 1, -1, and 0. In which case, we can determine three different actions to each product as well like so:
Step 2.2: Applying Our Forces
Believe it or not, thanks to the Unity team and their work on RigidBody.AddForce() we actually only need one formula to make this work. It looks like this:
Now, that looks like a mess of code so let’s go ahead and break it down. We’ll start from the left and work our way forward.
targetDirection() is a simple method that returns a Vector3 that tells the object being moved which direction the Force is being applied. We normalize the that Vector3 so that it doesn’t affect the magnetismStrength based on the distance. It’s very simple and looks like this:
A very useful formula that I use a lot. Whenever I want to get a direction between two objects
magnetismStrength is exactly what you think it is. It adjusts the attraction and the repulsion force between the two objects.
magnetismAction is an Integer that is determined using the method in Step 2.1.
What does this mean? If we break it down it essentially does this:
- Determine the direction from the origin object to a different object
2. Add a force to the other object to make it move in that direction so that it will move based on its relative position to the origin object
3. Multiply that force by some variable
4. Flip the direction or do nothing to the force depending on the magnetismAction since it will equal either 1, -1, or 0
You can get the opposite direction of a vector by multiplying all the values by -1. Luckily Unity does this for us if you multiply a Vector3 by an Integer. Here’s a little visual
Because we’re using applying forces and attempting to “simulate” physics, it’s best to put the AddForce() method in the FixedUpdate()
That’s the overall basic idea to how it works! Pretty straightforward right? Unity honestly does most of the work for you with Rigidbody.AddForce(), we’re mainly just supplying the direction of that force. So really, shoutouts to the Unity Dev Team for making such an awesome engine!
The main gif at the top actually iterates through a List<T> of objects within a radius and runs through this calculation on each object in that list. That’s how you’d get that really cool orbiting effect with the two cylinder magnets fighting for the cubes, but I mainly just wanted to go over the actual magnetism section of the code.
Try that out and let me know how it goes! Cheers for reading! ^_^b