Ways of recoloring objects based on a Player's team

I am currently working on a project in which players are split into teams. Team colors are assigned from the perspective of the player, so for the player it will always look like your team is colored ‘blue’ and the enemy is always colored ‘red’. This color-coding is also applied to objects in the game’s map (BaseParts, Decals, etc.). So the same door could be either blue or red depending on which team a player is in. To determine which objects should be recolored, I decided to use CollectionService. So when an object with a specific tag is added, I can change its color on all clients to the right color. This way I can also easily get a list of objects to recolor in case a player switches teams. To determine the right color for an object I figured renaming the tagged object would be best for now.

Now the tricky part I am having trouble with is giving these tagged objects slightly different hues, tones and shades. If every object that can be recolored shares the exact same red or blue, the game would look ugly. So I want to introduce some flexibility.

My first instinct was to add a Vector3Value to some of the objects that I want to give a different shade. I would use the X, Y and Z components of each Vector3 as multipliers for the R, G and B components. So if I were to set the value to Vector3.new(0.1, 0.1, 0.1) the corresponding object would turn to almost pitch black. But I would only add these Vector3Value objects where necessary to make the building process easier. The problem with this approach however is that when CollectionService:GetInstanceAddedSignal() is triggered, the Vector3Value might not be loaded yet and there is no way to tell if the object should have this child added.

A ‘solution’ for the situation above would be to litter all objects that can be recolored with a Vector3Value such that I can use :WaitForChild() for any tagged object that is added, but I am not a big fan of this approach, because it becomes harder to tell if a tagged object has other children as well in the explorer.

Another approach I was thinking of was to use an object’s color to determine its shade. So a bright colored object would change reds and blues to light tints, whereas a dark colored object would apply dark shading to them. The problem with this approach however, is that this translation has a very vague definition. Which Color3’s should define ‘light tint’ and which Color3’s should define ‘dark shades’? And more importantly, when a player switches teams, how do I know what the original color of an object was?


I am wondering if anyone knows a good way to approach this problem. I would like to avoid hierarchical dependencies if possible, and I would like to keep the structure of a map as intuitive as possible as well. Any help is appreciated!

2 Likes

The good news is that there’s a very good way to quantify the brightness and intensity of a Color3 – those are actually the Saturation and Value of a color when it’s converted to HSV.

In this representation, Hue is the only component that represents the actual ‘color’. This means in cases like yours where you just want to change the color and keep the tint the same, you can just swap out the hue with a different one. Something like this would work:

local function swapHue(part, newColor)
  local hue = newColor:ToHSV()
  local _, saturation, value = part.Color:ToHSV()
  part.Color = Color3.fromHSV(hue, saturation, value)
end

It works pretty well for basic recolors:

6 Likes