top of page

    Polarity VR

    Overview

    Polarity VR is my Final Major Project at university. It's an Unreal Engine 5 VR physics-based game where the player's hands are magnetic, as well as every single object in the level; the player can press trigger to activate the magnets on their hand and another object, pushing or pulling themselves to the object or vice versa depending on weight.

    This project is an early prototype designed to purely test the mechanic design, and my implementation of this idea.

    Note: This project is still in development - so you won't find a retrospective at the bottom of the page. More information will get added and updated as I keep working on the game.

    Skills I developed during the project

    Mechanic Design // Blueprint // VR Development // Interaction Design

    A major focus is on designing the mechanics of the attraction and repulsion with the player's hands to actually feel good and not clunky. I regularly test it and gather peer feedback through testing sessions every week or so at uni in order to improve the design of the attraction and repulsion.

    Developing this entire project using Blueprint is quite complicated as I had to dive deep into the UE5 VR Template and understand the way it handles the motion controllers, as well as the default GrabComponent, which I struggled a lot with adapting to the new hand functions during development.

    I am also putting my research in VR development and interaction design from both my dissertation and my other VR project, Machina Amelia, to good practice, in order to make the interactions feel fulfilling and satisfying to the player.

    Pre-Production

    Initial Plan for Mechanics

    Initially I had no idea what I wanted to make for my final major project, except for the fact that it was going to be a VR game. I thoroughly enjoyed working on my previous VR project and wanted to test the waters with VR development in Unreal.

    I enjoyed the physics-based interactions of games like BONELAB, and while developing a full body IK system was completely out of the scope of this project, I wanted the interactions in the game to be purely physics based.

    I was initially inspired (though it's not a particularly original idea) by the Kuuvahki system in Genshin Impact, which is essentially just magnetic energy that allows the player to imbue themselves with a specific polarity - red or blue - to attract or repel objects of another polarity in order to solve various puzzles. I wanted to create a game that uses these principles in VR to allow the player to interact with the world in a unique way.

    Using "kuuvahki" to solve a puzzle in Genshin Impact

    By coincidence this also allows to solve the issues of players having to physically pick up objects in VR from hard to reach locations, like the floor (especially when seated), more easily - an issue that Half-Life Alyx had to solve diegetically with the Gravity Gloves, for example.

    The idea is that your hands and objects are inert until the player presses trigger. Then, when the player holds trigger while pointing to an object, it activates the relevant magnetic polarity. If they aim their blue hand at a red object and hold trigger, it attracts the object to their hand. If they aim their blue hand at a blue object, it repels away from them.

    If they attract to an object heavier than themself, or fixed to the wall/floor, they will move their own body to the object instead. Likewise, if they repel an object heavier than themself, they will be pushed away from it.

    Hand Mechanics

    Hand attracting objects

    The way the hands attract objects currently uses a capsule collider that stretches outwards from the controller, in a way that makes it natural to aim, like most VR guns or pointers are. When an object overlaps this collider, it checks for the 'Magnetic' actor tag, currently only found on the MagnetClassObject actor, and if true, activates a function in that actor. Within the actor, in that function, it checks the hand's polarity against the object's polarity and then decides what to do afterwards.

    If the polarity is opposite, then it triggers the attract function: it sets various boolean states, used to prevent conflicts and bugs, and calls a function that adds a force to the object every tick, customizable through an AttractStrength float variable that acts as a multiplier. This force has damping to prevent the object from spinning out of control and seamlessly going into the player's hand. Once it gets close enough within range of a sphere collider, it forces the GrabComponent's Try Grab function, albeit modified to lerp to the player's hand more smoothly and snap into position for a more seamless interaction than the default.

    As long as the player is holding the trigger, the object will keep attracting regardless of whether it leaves the collider or not.​ This feature did not exist originally, however - I added it after peer testing and feedback (elaborated more on later.)

    attractobject.gif

    Hand repelling objects

    If the polarity matches between the hand and the object, it instead activates the repel function: again setting various boolean states, then applying the opposite force (away from the hand) to the object until the distance between the hand and object reaches a certain degree.

    This one is a lot simpler than the attract function as it does not need any use of the grab function, it simply just applies a force.

    repelobject.gif

    You can also repel objects through walls - later down the line I may add a line trace + tag system to denote whether or not it can attract through a certain surface, but for now it can attract or repel through any obstacle. This is so that the player can affect objects through glass areas like this:

    repelthruglass.gif

    Attracting self to heavier objects, and wall-grab

    When the object is set to "fixed" via a boolean, it instead activates a separate function. It alters the player's CharacterMovement, reducing their gravity scale, and starts adding a gradual force that pulls the player to the object. The player's air control is increased the closer the player gets to the object, allowing for rope-like swinging while still maintaining the idea of magnetic attraction

    attractself.gif

    Attracting self to objects.

    attractself2.gif

    More advanced swinging using the attraction - including attracting to two objects at once.

    The player's velocity is maintained at any point if they let go of the activation button, allowing them to swing from place to place. Once the player reaches the object, they are lerped based on their hand position to the object's position, and the player is fixed to the object so long as they hold grip or the activation button. Each tick, the player's position is offset by the difference between current pos and last frame's pos, keeping them in place, meaning that the player will be holding the grip and won't deviate their position from it.

    They can let go at any point and grapple to another, or the same, object, or instead repel themselves off of it with their other hand.

    grabfixedobj.gif

    Repelling self from heavier objects

    This function is very simple - if the object is fixed and the polarity matches, it applies a one-time impulse to the player each time they press it. This allows the player to boost themselves off of an object they may be pulling towards, or gain an extra boost to make a larger jump.

    Later I also added a subtle force for as long as you hold the button down after the impulse. This is a small force accompanied by a small gravity change that allows the player to prolong the repulsion to keep it in line with the other attract/repel functions.

    repelself.gif

    Pushing away from one of the handles, and a large platform on the floor. Demonstrates both single impulse and the continuous force.

    repelselfdouble.gif

    Repelling yourself from two platforms, using the velocity to swing upwards in range of another magnetic handle.

    Iterative testing changes

    Movement focus

    As I got more player feedback, I realised that players really enjoyed the platforming and movement parts of the game a lot. Being able to attract yourself to an object to get around, while pushing away from others, depending on the hand you use, was a universally fun VR experience for almost all playtesters, so I wanted to lean into it more than the puzzle part, which to be honest players found a little underdeveloped. I still wanted to retain it as a major part of the game, though, as the mechanic does have significant potential for puzzle design.

    To facilitate more movement testing, I designed the sandbox area with various floating handles that the player can attract and repel to play around with, to demonstrate the parkour potential of the prototype.

     

    One of the major changes was when, after player feedback, I retained more player velocity when attracting themself to a handle, and added more air control to the player. This allowed the player to freely swing around a magnetic object that they were attracting to, much like a grappling hook, while still maintaining a constant force of attraction. The air control tapers off after a distance to prevent the player from going too far from the attracted object.

    Attraction and Repulsion mechanics

    Initially the attraction and repulsion were very rudimentary. As soon as the collider left the object it would stop attracting. This was really bad for a gameplay perspective especially considering that the colliders would ideally be hidden in-game once the build was complete. After testing showed player disappointment with the way this worked, I changed the function to no longer stop itself once it wasn't overlapping the magnet scan collider.

    This brought problems of its own, however - when attracting an object, if the player moved out of the way of the object, it would add more and more force and perpetually increase in motion, starting to orbit the player's position and get farther away while going past the player narrowly missing their hand. I spent a lot of time troubleshooting how to solve this issue before I added damping to the object velocities - something that I was hesitant to do in case it made the physics too unrealistic. After some testing, though, even a small amount of damping ended up solving the issue completely.

    Once hiding the magnet scan collider in-game, I needed a way to effectively demonstrate when the player is in range to attract or repel an object. I decided on a crosshair that would show up when the player's hands are pointing at something in range. This was done via a Widget blueprint, its position set based on the end point of a line trace.

    After testing, players felt that this was a good addition and helped to aim when attracting and repelling, though sometimes players would lose track of their hands since the crosshair would disappear when out of range (if the line trace didn't make a hit). To solve this, if the line trace doesn't get a hit, I instead rendered the crosshair at the end point of the line trace, but reduced the crosshair's size significantly so that the player can recognize when in range while still being able to see their crosshair and aim accordingly.

    © 2026 Alexander Wilkinson. All rights reserved.

    bottom of page