As you can see, the FPS drop frop 90fps to 70fps once the hexagons get rendered, which is pretty terrible
The video is running on a Quest 2, so it’s an android-based project.
I’m animating the hexagons with perlin noise, executing the following script on every single hexagon :
[HideInInspector] public float x, y;
private Renderer mesh;
private MaterialPropertyBlock _propBlock;
// Start is called before the first frame update
void Start()
{
x = transform.position.x;
y = transform.position.z;
mesh = GetComponent<Renderer>();
_propBlock = new MaterialPropertyBlock();
}
// Update is called once per frame
void Update()
{
if (mesh.isVisible)
{
float level = Mathf.PerlinNoise(Time.timeSinceLevelLoad / 4 + x / 10, Time.timeSinceLevelLoad / 4 + y / 10);
transform.position = new Vector3(transform.position.x, -2f + level * 0.75f, transform.position.z);
//mesh.materials[1].SetColor("_EmissionColor", Color.white * level * 1.5f);
mesh.GetPropertyBlock(_propBlock);
_propBlock.SetColor("_EmissionColor", Color.white * level * 1.5f);
mesh.SetPropertyBlock(_propBlock);
}
}
Do anyone know what I could do to further optimize it ?
I had GPU Instancing disabled, but once enabled, nothing changed (stuck at 250 draw calls)
Then I disabled SRP Batcher from the URP settings and it dropped to 160 draw calls !
It was now batching the concrete material from the hexagons but not the neon part on the sides.
There’s definitely something wrong with the SRP Batcher…
In addition to running all the animation on a single script instead of on each hexagon, I’m now at 80fps in worst case ! Which is way better than the previous 70 but still 10fps too low (targeting 90fps)
Any idea how I could batch the neon material while still keeping the color animations going ?
(edit: definitely GPU limited)
To be honest i am still using built in renderer for my project so i can’t really comment on srp batcher. From what i have read online gpu instancing support is not great but don’t take my word for it.
The hexagons look like they are using a fairly simple shader. It might be worth trying the following:
disable all animations, check fps. The animation of position and or colour might be breaking batching
make a single large mesh of all hexagons baked together.
If (2) achieves the speed you need then maybe look to a pure shader implementation of the animation? For example use a perlin texture lookup to animate vertex position
Updates on material properties require a unique runtime material to store/track unique values per use —that will break batching. But I think updating all materials (get/set) every frame might be the bigger deal.
if you disable all the material read/write instructions is it a significant improvement?
(in terms of division of labor; Color operation will be handled by shader)
single static material : the Shader reads objects (center point) world location (pos.z) to factor on vertex color based on height (material Color / Tint / Emissive causes runtime material creation and breaks batching)
While leaving motion in your posted script operating on object level (not on the shader and vertices)
you can use vertex position in shader, might be a savings as it means object level doesn’t move
Im not sure about this, but does calling a perlin function on each object cause a tiny issue? rather than having 1 function globally outside and the objects only offset time by their XorY location
also when you say ‘neon’, you mean setting “_EmissionColor” to 1.5f right? (that can be in the shader but needs to stay static, you just fine tune the vertex i/o based on position z height)