- Home /
How to set GameObject inactive without messing up GPU instancing?
It seems like setting a GameObject inactive (setActine(false)) messses up GPU instancing arrays.
Here is what I did:
public class Instancer : MonoBehaviour
{
public int number = 5000;
public float radius = 50f;
public Transform prefab;
private GameObject[] nodes;
void Start()
{
nodes = new GameObject[number];
MaterialPropertyBlock propBlock = new MaterialPropertyBlock();
for (int i = 0; i < number; i++)
{
Transform t = Instantiate(prefab);
t.localPosition = Random.insideUnitSphere * radius;
t.SetParent(transform);
propBlock.SetColor("InstColor", new Color(Random.value, Random.value, Random.value));
t.GetComponent<MeshRenderer>().SetPropertyBlock(propBlock);
nodes[i] = t.gameObject;
}
}
}
And the following shader:
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma multi_compile_instancing
#pragma target 4.6
sampler2D _MainTex;
struct Input
{
UNITY_VERTEX_INPUT_INSTANCE_ID
};
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, InstColor)
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
UNITY_SETUP_INSTANCE_ID(IN);
o.Albedo = UNITY_ACCESS_INSTANCED_PROP(Props, InstColor).rgb;
}
ENDCG
}
It works exactly like it suppose to - batches multiple static instances together, while assigning random colors in the start:
However, if I add the following update function:
void Update()
{
GameObject node = nodes[0];
node.SetActive(!node.activeSelf);
}
...it starts to change the colors of all GameObjects every frame. ALL GameObjects change its colors randomly every frame.
Not sure what exactly happens, but it seems like it has something to do with constant buffer. Perhapse I use wrong macros in my shader? Is it possible to set instantiated gameobjects inactive at all?
Just in case - Unity version 2019.3.0f3
Small update:
Disactivating only the last gameobject works fine and doesn't affect all others:
void Update()
{
GameObject node = nodes[number-1];
node.SetActive(!node.activeSelf);
}
It seems like the constant buffer is assembled dynamically every frame, but the instance id is assigned statically at the moment of instantiation. Should I report it as a bug?
Your answer
Follow this Question
Related Questions
How to share constant variables between Compute Shaders? 0 Answers
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers