Search Unity

Adding diversity to prefab instances : how to define a textures/materials pool for each Mesh ?

Discussion in 'Shaders' started by smaraux, May 28, 2015.

  1. smaraux

    smaraux

    Joined:
    May 28, 2015
    Posts:
    10
    Hello,

    I would like to add some diversity to my humanoid prefabs instances. I was thinking to switch material, shader or texture of each Mesh ((Skinned)MeshRenderer), taking it from a predefined pool, at instantiation time.

    At the moment, I manage to add a random texture at instantiation time for each Mesh Material, but I have no good place to store the possible texture/Material pool of each mesh.

    MeshRenderer materials are stacked when rendering

    As material is per-mesh on my humanoids, it would be clearer to have a list of all possible shaders / materials in the same location (per mesh). Ideally a single Material accepting a texture pool for example.

    Thanks for reading
     
  2. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Well you can always attach a script to your humanoid prefab called something like "RandomizerPool" that have a list of textures, material or whatever, and pick at random those in the "start" or "awake" function of that script. That way everytime you instance that prefab, it get a different look.

    I would also recommend looking into the MaterialPropertyBlock : http://docs.unity3d.com/ScriptReference/MaterialPropertyBlock.html allow to have only one material, but set parameters PER RENDERER instead of instancing a new material everytime.
     
    chelnok likes this.
  3. smaraux

    smaraux

    Joined:
    May 28, 2015
    Posts:
    10
    Thank you for the answer.
    I took a similar path, making a kind of singleton holding a dictionary of Material -> List of textures.
    At instantiation, I get this singleton (configured by user) and randomize instance material texture from user defined pool. That does the job.

    For MaterialPropertyBlock, I don't really know where I could store it easily, but I keep that in mind for later performance improvement. Is one Renderer.setPropertyBlock call for each Renderer / instance enough to get it working ?
     
  4. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Yes, just set all your properties on the block, and assign it to SetPropertyBlock at instance time. Renderer will copy the block and keep its own copy.
     
  5. smaraux

    smaraux

    Joined:
    May 28, 2015
    Posts:
    10
    Nice, SetPropertyBlock works like a charm in my setup.
    Thanks for advice
     
    Last edited: Jun 3, 2015
  6. smaraux

    smaraux

    Joined:
    May 28, 2015
    Posts:
    10
    I was too optimistic, there is a glitch remaining.
    I instantiate (via Object.Instantiate) some meshes / gameObjects & set MaterialPropertyBlock via script, then hit start.
    When I hit start, materials seems to be reset to base Material without MaterialPropertyBlock.

    If I instantiate them once started, materials are OK until reset (instances removed at stop).
     
  7. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    What do you mean you instantiate & hit start? You mean through a function in editor (Custo;Editor, ContextMenu,ExecuteInEditMode etc..)

    It would guess (it's conjecture, I'm not entierly sure how it work in the underlying system) that MaterialProperty block are NOT serialized, meaning they are not saved with the renderer they are applied to. So you would need to have a call to the "SetPropertyBlock" somehwere during your runtime (i.e in the awake or start function)

    If you really need to instantiate them at edit time, you can try to stock the param of each instance (textures, colors etc..) on the script, in public or [SerializeField] variable so Unity save them, and apply that in the start function throught a MaterialPropertyBlock
     
  8. smaraux

    smaraux

    Joined:
    May 28, 2015
    Posts:
    10
    For the moment, I went back to material instances, as the batching is already killed by using skinning on my models. There is probably some memory/performance hit thou, but I will come back to it later in my project (in optimization part). Thank you for your help, I keep this thread in mind for later feedback..