character's numbers and colors changing

Hello friends. I don’t know whether the title is almost explaniatory: so sorry, but I’m still new and besides, I’ve some language bareer which constraints me from eventually formulating concise questions with fitting words. In the case, please excuse me in advance and eventually hint me how to correct the title accordingly to what I’m explaining here.
We are planning a minisoccer game (5 vs 5). I’m simply asking how to assign a color (or a color scheme, if it isn’t too hard to do) to the jersey/trunks, accordingly to the choice of the player.
As for the number, should I re-uv the part of the jersey where the number will be (leaving it anyway colored with the color or texture of the jersey map), and put on it a number texture with alpha?
Thanks in advance.

You could use a custom color replacement shader that would replace a base colour on your texture with another one. I use that technique quite extensively.

Firstly, sorry this appears to be actually quite a complicated answer. You can see the results of my shader/mesh mods working here: One Model, One Draw Call.mp4 - YouTube

You could for instance draw the textures for all of your characters using:

  • shades of pure red for the main body of the shirt
  • shades of pure blue for stripes or decals
  • green for perhaps the numbers

The rest of the character would be drawn in similar colours (e.g. hair as red with highlights of green). The skin would normally be drawn as very light caucasian and you would use a “tint” step to change it to different colours.

What I do next is assign a “replacement color” or “tint” to each part of the character by using the uv2 of the meshes to indicate an offset into a set of lookup textures. So for example, if would assign position 0 to the hair, 1 to the skin, 2 to the shirt, 3 to the shorts and 4 to the boots (all of the UV2s for that part of the mesh would be set to the same value where uv2.u would be the the number allocated divided by the total number of colours (rounded up to the next power of 2)). This would then act in the shader as a lookup for the replacement colours for that part.

You would then have lookup textures. for the red, green and blue replacements. Taking the uv2.u you get the color to replace red, green and blue with and then multiply that out by the value of the r,g,b of the colour you are reading from your texture. It so happens that if you set values in the lookup textures for all of r,g and b you effectively get the tint you need for skin etc.

This is the shader that I use (single light source, vertex lit):

Shader "Custom/ColorRemappingVertexLit" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Color1Tex ("Color1 (RGB)", 2D) = "white" {}
		_Color2Tex ("Color2 (RGB)", 2D) = "white" {}
		_Color3Tex ("Color3 (RGB)", 2D) = "white" {}
	SubShader {
			Lighting On
		Tags { "RenderType"="Opaque" "IgnoreProjector"="True" "LightMode" = "Vertex" }
		Pass {
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members lightDirection)
#pragma exclude_renderers d3d11 xbox360
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"
			sampler2D _MainTex;
			sampler2D _Color1Tex;
			sampler2D _Color2Tex;
			sampler2D _Color3Tex;
			float4 _Color; 
			float4 _MaskColor;
			float4 _MainTex_ST;
			float4 _Color1Tex_ST;
			struct a2v
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
				float4 texcoord1 : TEXCOORD1;
			struct v2f
				float4 pos : SV_POSITION;
				float2 uv  : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
				float4 color : COLOR;


			v2f vert (a2v v)
				v2f o;
				o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
				o.uv = TRANSFORM_TEX (v.texcoord, _MainTex); 
				o.uv2 = TRANSFORM_TEX (v.texcoord1, _Color1Tex);
				float4 lightColor = UNITY_LIGHTMODEL_AMBIENT;
				lightColor.a  = 1;
		        //Angle to the light
		        float diff = dot (v.normal,ObjSpaceLightDir(v.vertex))*0.5 + 0.5;   
		        lightColor.rgb += unity_LightColor[0].rgb * (diff);
				o.color = lightColor;
				return o;
			float4 frag(v2f i) : COLOR
				float3 c1 = tex2D (_Color1Tex, i.uv2);
				float3 c2 = tex2D (_Color2Tex, i.uv2);
				float3 c3 = tex2D (_Color3Tex, i.uv2);
				float4 c = tex2D (_MainTex, i.uv);
				float3 f = saturate(((c1.rgb * c.r) + (c2.rgb * c.g) + (c3.rgb * c.b)));
			    return float4(f, c.a) * i.color * 2;

	FallBack "Diffuse"

And here’s a code extract of how I set those customising colours:

private readonly Texture2D[] _colorReplacementTextures = new Texture2D[3];
private readonly Dictionary<string, int> _modelMapping = new Dictionary<string, int>();
private int _customiserTextureWidth;

public void SetColor(string partName, int sourceColor, Color replaceColor )
    if (!_modelMapping.ContainsKey(partName))
    var position = _modelMapping[partName];
    _colorReplacementTextures[sourceColor].SetPixel( position % _customiserTextureWidth, Mathf.FloorToInt(position/_customiserTextureWidth), replaceColor);

I dynamically create square textures as I build my model (which I do by combining the skinned meshes for each part into a single mesh to get a single draw call).

All of these characters are one combined model where the parts have been modified with Megafiers Morph Channel support first to get different body and face shapes.


Here is what the base model looks like with all of the clothing/body parts turned on - you can see the stripes etc:


Ok Mike: I’ll make treasure of your teachings (as surely will do also others who seeked for the same argument, which I see it was not dealt with satisfactoriously elsewhere). Thank you for now. Cheers.