Vertex Bullet Offset

About the project

For this project I wanted to create a system to easily allow bullets to visibly move inside their magazines without the need for rigging and animation. The idea for it came from the submachine gun FN P90 whose magazine is transparent thus allowing the people to see all the bullets in it. In many video games they tend to move around this by either making the magazine opaque or by making the bullets static.


This project is split into three parts:

  • The Maya Setup

  • Converting Data into Unreal

  • FN P90 Setup

Maya Setup

Python Script

The python script in Autodesk maya checks for all the objects in my bulletGroup and assigns them a PolyColorSet RGB so that it can be assigned a Vertex Color. It then goes through every vertex of each bullet and calculates each vertex position and then compares it to the nexts bullet in the list. These positions are saved as the variables and using them I can calculate the offset value between the bullets. This offset will represent the XYZ position of the bullet and will be assigned for each vertex separately to the RGB channels of the ColorSet.

Using a ShaderFX material in Maya I can now move each bullet by connecting a Time and a Frac node and multiplying them with the ColorSet. The Frac node limits the movement between 0-1 so when the bullet reaches the position of the next bullet it resets back to its original position, giving me a conveyor belt of bullets.


This method could of course also be used for different purposes, as long as you have two identical objects you can reuse the script. I later found more use cases for the script when I needed to move a spring within the magazine and the result I got was much cleaner than what I would have gotten if I had tried scaling the mesh or rigging it.


Identifying each bullet

At this stage I wanted to combine all the bullets into one object, since the XYZ data for each bullet was saved in the colorset it still worked even when combined.  Although this did present a new problem, with them all combined into one object I need a way to later be able to identify each bullet separately in Unreal Engine 4. To do so I made sure that the python script gave each bullet a unique value between 0-1 and stored it in the Alpha channel of the colorset. There is 50 bullets in the magazine of a P90, thus 1/50 = 0,02 * the bullet index. Visually it looks like this if the alpha channel is plugged into the color output.


Unreal Setup

When converting the project into unreal the first thing i had to do was to recreate my ShaderFX material. When I did I took the time to add a few extra additions to make the material more dynamic. This was not completely straight forward as things tend to work differently in different programs.

Re-scaling the values for Unreal

When going from Autodesk Maya into Unreal Engine 4 something will work differently and the first thing I encountered was how each platform handles vertex colors. Unreal Engine 4 does not support negative values in vertex colors which meant that most of the time the values i generated would end up as 0 when they were imported into unreal. To fix this i rescaled the values to make them work in Unreal Engine 4. I did this by going back to my python script in maya, there i took my final offset value and added 10 and then divided it with 20.

Then later in Unreal Engine 4 I scaled the vertex color values back by doing the previous formula again in reverse, multiplying it by 20 and then subtracting 10.


Converting to model space

Inorder to have the bullets movement follow the players rotation i needed to convert them to model space. To do this I first had to transform it from local space to world space and then remove world position to prevent it from adding it to the offset.


Removing Bullets

To remove the bullets in the magazine I created a parameter that I could later reference in the first person blueprint, this parameter determines how many bullets remain in the magazin. By using the values saved in my alpha channel I could identify each bullet in order. To remove the bullets I had to change the material Blend Mode from Opaque to Masked. Then I simply scaled my variable value to fit into a range of 0-50 so that I could easily control the number of bullets visible and then I used it as my Opacity Mask.


FN P90 Setup

To properly demonstrate my project in action i put together a FN P90 setup, this was mostly a bonus but i felt that it was necessary for the bigger picture. The work done includes:

  • Automatic Fire

  • Ammo Count

  • Reloading

  • Recoil

  • Bullet Spread

  • Decal Impacts

  • Niagara System for Bullet Impact and Muzzle Flash

  • Sound Ques

  • Animations


I am generally very satisfied with the final result although there is plenty of room for improvement. There was an issue I encountered in the project that involved the normals of the bullets not changing with their rotation, this would normally not be noticable but since the bullets rotate at the end of the line it is slightly noticeable. I did work on a method that would rotate the normals when this happened but it proved difficult to test and at the end of the day it was only noticeable when you looked at the bullets in slow motion so i decided to move on. If i would return to this project that would be an issue i would like to find a clean and easy way to fix.