The DPT_ShaderVariation Component

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.

Core Architecture

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.

Component Inspector Fields

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)
The script can be attached directly to empty root parents. It automatically scans down the hierarchy using its filtered collection system to apply color data across LOD0, LOD1, or nested broken debris meshes simultaneously, making it fully compatible with destructible object systems.

Advanced Architecture Features

1. Dynamic Color Updates (Update Every Frame)

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();
    }
}

2. Zero-Allocation Initialization

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.

3. Nested Hierarchy Protection

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.

Performance & Optimization Compatibility

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.

MaterialPropertyBlock Dynamic Fallback Sequence

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).

CRITICAL PIPELINE WARNING: While the MPB fallback preserves memory by avoiding material duplication, Material Property Blocks fundamentally break both the GPU Resident Drawer and the SRP Batcher. If you are building a modern, highly instanced game in Unity 6+, you must use the provided VCCore material to keep your props on the fast path.

Troubleshooting

The color changes in the Inspector but does not update on the mesh
Ensure that the mesh isn't marked as Batching Static (which bakes transforms and breaks the per-instance data stream). Additionally, verify that your shader natively supports the unity_RendererUserValue channel, or matches the string designated in the Color Property Name field when using fallback standard materials.
A script or Animator is changing the color property but nothing changes on screen
Check the Update Every Frame toggle in the component inspector. If this is disabled, the script disables itself after initialization and will not poll for backing field changes caused by an animation timeline or external script modifiers.
A parent script is overwriting my sub-object color animations
Ensure that the sub-object has its own 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.

Support & Custom Pipeline Integration

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.

Contact & Inquiries:
For freelance modeling contracts, custom asset optimization passes, standard package bug reports, and publisher licensing enquiries, please use the Contact Form on the DPT Games Hub.
DPT Support Discord:
For dedicated technical assistance, asset configuration help, and direct feedback on our Unity packages, join the Support Server.