The DPT_ShaderVariation component manages per-instance color customization paths across your game scene assets. It works automatically when spawned by the DPT Prefab Painter, but can also be manually attached to custom game objects, empty root parents, or modular prefabs to handle low-overhead color manipulation.
The component reads your selected color, normalizes the RGB channels to maintain full 24-bit hue precision, and encodes the remaining 8 bits as an independent luminance scaler. This vector-packing approach natively accommodates peak HDR brightness settings up to a 2.0 multiplier without color distortion. The resulting data structure is compressed into a single unsigned 32-bit integer (uint) and pushed directly to the GPU instancing buffer using the Renderer Shader User Value (RSUV) stream.
Because the variation data is handled entirely by the GPU instance via SetShaderUserValue, your original shared materials are never cloned, duplicated, or modified. This means thousands of heavily varied objects can be processed inside unified hardware draw calls, keeping your project's VRAM footprint entirely clean.
Select any object holding a DPT_ShaderVariation component in the hierarchy to configure its parameters:
| Field | Description |
|---|---|
| Instance Color | The color tint and brightness modifier pushed to this object's GPU stream. White (1,1,1,1) is default neutral. Darker values dim the object, while values with a high color magnitude lift it into HDR brightness. For emissive objects, the Alpha channel directly controls the emission strength. Driven natively by properties, or tracked dynamically via field analysis. |
| Color Property Name | The shader variable string targeted for fallback standard materials (e.g., _BaseColor for standard URP shaders). This property is completely locked and non-enterable if a custom DPT material is detected on the mesh, as it is only intended for non-DPT fallback scenarios. |
| Update Every Frame | Performance Warning. Enables the per-frame Update() loop to track dynamic color changes. Only enable this for assets whose colors change during gameplay (e.g., damage flashing, pulsing). Leave unchecked for standard props to eliminate CPU overhead entirely. (Formerly Is Animated) |
LOD0, LOD1, or nested broken debris meshes simultaneously, making it fully compatible with destructible object systems.
When you animate a script field inside the Unity Animator or alter it via external scripts, the system directly modifies the serialized backing field (instanceColor). This bypasses standard C# public property setters (InstanceColor), which normally prevents scripts from knowing they need to push updates to the GPU.
To solve this efficiently without killing performance, checking the Update Every Frame toggle activates an internal tracking loop:
void Update()
{
if (instanceColor != lastInstanceColor)
{
lastInstanceColor = instanceColor;
ApplyVariation();
}
}
Update Every Frame keeps the update loop active. The component catches field alterations made by the Animator or other scripts instantly and pushes the packed values to the GPU on the exact frames they change. This includes animating the Alpha channel to create pulsing emission or fading glow effects over time.Update Every Frame causes the component to push the data once during initialization, and then completely deactivate its own logic (enabled = false). This eliminates the common performance issue of Unity-to-Managed lifecycle overhead across thousands of scene props, leaving a net-zero impact on your CPU frame time.To prevent garbage collection (GC) spikes when instantiating large quantities of customized props at runtime, the component avoids array allocations during its setup phase. By utilizing pre-allocated, non-serialized generic lists (tempRendererList and filteredRenderers), the script scans the hierarchy and builds its internal renderer cache with zero memory allocation overhead.
When managing complex or modular structures (such as a siege engine prefab containing a custom lit fuse grandchild), standard recursive scans like GetComponentsInChildren<Renderer>() would normally cause a parent script to hijack child renderers, wiping out their individual colors.
To support nested workflows out of the box, DPT_ShaderVariation implements a bottom-up hierarchy verification filter during its caching state:
for (int i = 0; i < tempRendererList.Count; i++)
{
Renderer rend = tempRendererList[i];
if (rend != null && rend.GetComponentInParent<DPT_ShaderVariation>() == this)
{
filteredRenderers.Add(rend);
}
}
This safety filter ensures that when a parent component scans downward for meshes, it checks whether it is the closest active variation manager. If a closer DPT_ShaderVariation script is found on a sub-object (like the fuse), the parent script gracefully steps aside. This allows independent color control over sub-assemblies while the main parent continues to manage the structural body colors without conflict.
The system integrates natively with modern rendering configurations to protect batch boundaries:
| Render Path | Compatible | Notes |
|---|---|---|
| GPU Resident Drawer (Unity 6+) | Requires VCCore | Fully supported ONLY when using the DPT VCCore material (or custom RSUV-enabled shaders). If you use standard fallback materials like URP Default Lit, the required Material Property Block will break the object out of the GPU Resident Drawer entirely. |
| SRP Batcher (URP / HDRP) | Yes | Fully supported. Keeps CPU draw calls unified across shared shader keywords. |
| GPU Instancing | Yes | Fully compatible. Because all instances share one identical material file, standard GPU instancing loops remain active. |
| Static Batching | No | Not compatible with GPU-driven workflows. Do not mark painted objects as "Batching Static" in the inspector, as mesh-merging prevents the GPU Resident Drawer from instancing individual props. Use the modern GPU paths instead. |
If you choose to use standard Unity materials (e.g., URP Default Lit) instead of the optimized VCCore material, the component automatically executes a fallback pipeline. It unlocks the Color Property Name string field, detects standard material color signatures (like _BaseColor or _Color), and pushes color modifications dynamically on a per-instance basis using a MaterialPropertyBlock (MPB).
unity_RendererUserValue channel, or matches the string designated in the Color Property Name field when using fallback standard materials.DPT_ShaderVariation component attached. The nested hierarchy protection rule relies on the sub-object finding its own script manager during setup queries to cleanly block parent overrides.If your project requires external or custom 3D models to be fully integrated into the DPT ecosystem—including custom vertex-data packing, procedural wood grain mapping, normal array configuration, advanced GPU wind system implementation, or any other bespoke features—freelance technical art services are available. Additionally, availability extends to general 3D asset production, high-to-low poly hard surface modeling, stylized prop creation, and game-ready LOD budgeting built to align cleanly with your specific project constraints.