Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question What's the best way to optimize a moving pattern like this ?

Discussion in 'General Graphics' started by Wasplay, Nov 8, 2020.

  1. Wasplay

    Wasplay

    Joined:
    Jun 2, 2018
    Posts:
    46
    Hi !
    I can't manage to correctly optimize this :

    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 :
    Code (CSharp):
    1.     [HideInInspector] public float x, y;
    2.     private Renderer mesh;
    3.     private MaterialPropertyBlock _propBlock;
    4.  
    5.     // Start is called before the first frame update
    6.     void Start()
    7.     {
    8.         x = transform.position.x;
    9.         y = transform.position.z;
    10.         mesh = GetComponent<Renderer>();
    11.         _propBlock = new MaterialPropertyBlock();
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update()
    16.     {
    17.         if (mesh.isVisible)
    18.         {
    19.             float level = Mathf.PerlinNoise(Time.timeSinceLevelLoad / 4 + x / 10, Time.timeSinceLevelLoad / 4 + y / 10);
    20.             transform.position = new Vector3(transform.position.x, -2f + level * 0.75f, transform.position.z);
    21.  
    22.             //mesh.materials[1].SetColor("_EmissionColor", Color.white * level * 1.5f);
    23.  
    24.             mesh.GetPropertyBlock(_propBlock);
    25.             _propBlock.SetColor("_EmissionColor", Color.white * level * 1.5f);
    26.             mesh.SetPropertyBlock(_propBlock);
    27.         }
    28.     }
    Do anyone know what I could do to further optimize it ?
     
  2. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    390
    Hi. Are you using a gpu instanced shader for the hexagons presumably? Maybe have a look with the profiler to see if you are gpu or cpu limited?
     
  3. Wasplay

    Wasplay

    Joined:
    Jun 2, 2018
    Posts:
    46
    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)
     
    Last edited: Nov 8, 2020
  4. Wasplay

    Wasplay

    Joined:
    Jun 2, 2018
    Posts:
    46
    Looks like even without the neon animation and having only 80 draw calls, those hexagons are still draining a lot of performance.. :S
     
  5. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    390
    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:

    1) disable all animations, check fps. The animation of position and or colour might be breaking batching

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

    Good luck with your project!
     
    Wasplay likes this.
  6. BrandyStarbrite

    BrandyStarbrite

    Joined:
    Aug 4, 2013
    Posts:
    2,067
    @Wasplay
    What is the polycount of 1 of those hexagons?
     
  7. Wasplay

    Wasplay

    Joined:
    Jun 2, 2018
    Posts:
    46
    About 30, but this doesn't seem to affect the performance.
     
  8. Torbach78

    Torbach78

    Joined:
    Aug 10, 2013
    Posts:
    295
    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)

    1. 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)
    2. 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)
     
    Last edited: Dec 14, 2020