Search Unity

Changing material parameters in pure ECS

Discussion in 'Entity Component System' started by LoganGerberHATS, Oct 22, 2019.

  1. LoganGerberHATS

    LoganGerberHATS

    Joined:
    Jul 31, 2018
    Posts:
    2
    I am currently spawning approx. 40000 entities that have RenderMesh components. I would like to conditionally change a color parameter on each entity, depending on if my mouse is hovering over it or not. I have the logic working for detecting when the mouse is hovering over the entity, but I cannot figure out how to change the entity's color.

    When I hover over an entity, it receives a
    MouseOver
    component.

    Currently, this is what I have:

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3.  
    4. using UnityEngine;
    5.  
    6. [UpdateAfter(typeof(MouseHoverSystem))]
    7. public class HighlightBubbleSystem : JobComponentSystem
    8. {
    9.     private static readonly int mainColor = Shader.PropertyToID("MainColor");
    10.    
    11.     // [BurstCompile]
    12.     struct HighlightJob : IJobForEachWithEntity<MouseOver>
    13.     {
    14.         public void Execute(Entity entity, int index, ref MouseOver mouseOver)
    15.         {
    16.             // ???
    17.         }
    18.     }
    19.  
    20.    
    21.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    22.     {
    23.         HighlightJob job = new HighlightJob();
    24.  
    25.         return job.Schedule(this, inputDeps);
    26.     }
    27. }
    28.  
    Each entity has its own instance of RenderMesh, so changing one won't change any of the others.

    Is this something that is even possible? I've looked everywhere, but couldn't even find anyone else asking this question.
     
  2. Radu392

    Radu392

    Joined:
    Jan 6, 2016
    Posts:
    210
    You can’t currently without changing materials. If you changed the color of the material in one entity, it would change for all entities.

    In your case, since you only highlight units temporarily, swapping materials shouldn’t cause any performance issue. RenderMesh is a bit limiting at the moment, so you might want to switch to other rendering solutions if you plan on doing a little more complex stuff. I had to because RenderMesh doesn't offer a SortingLayer for my 2D needs, among other reasons.
     
  3. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
  4. LoganGerberHATS

    LoganGerberHATS

    Joined:
    Jul 31, 2018
    Posts:
    2
    Thank you for the answers. Any idea when the next release for the hybrid renderer will be?
     
    Noxalus, learc83 and charleshendry like this.
  5. Noxalus

    Noxalus

    Joined:
    Jan 9, 2018
    Posts:
    80
    Do we have some news about this issue?
     
  6. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    deus0 and Noxalus like this.
  7. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    There is some good news (that I'm sure some of you already know)... It is possible to use the new per-instance-material-params for some common parameters without editing shaders and doing a lot of extra work. I can't comment on how performant it is, but it's quite easy to use.

    Everything I read said it only worked with HDRP and you had to somehow make your own shader with shader graph, and set up some experimental things and create a material, and make a component, and do a bunch of other voodoo.... and so much stuff that I just decided it wasn't worth the hassle. In the past 3 months I probably spent an entire day trying to figure out how to change the base color of a single instance.

    Today I went to https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.8/manual/index.html and noticed the "Built-in material property overrides" section has some common parameters listed, such as "base color". It took a lot of mucking around before I finally figured out how to change the overrides at runtime.

    So for anyone else having trouble figuring out what to do... here's an example for changing the base color:

    I know this works with the built-in URP Lit shader, but I'm not sure if it works with others. Disappointingly, it does NOT work with SimpleLit.

    After adding using Unity.Rendering; there are really only two easy steps.

    Step 1, Option A) If you're using a hybrid approach and have a mesh on a prefab (that's being converted to an entity), you will add a URPMaterialPropertyBaseColor "URP Material Property Base Color Authoring" to your prefab.

    Step 1, Option B) Or if you're doing it in pure ECS, whenever you instantiate your call something like EntityManager.AddComponent<URPMaterialPropertyBaseColor>(entity).

    Step 2, Option A) If you can fetch the objects via query, you'll have something like:
    Code (CSharp):
    1. Entities.ForEach((ref URPMaterialPropertyBaseColor color) => {
    2.     color.Value.x = UnityEngine.Color.yellow.r;
    3.     color.Value.y = UnityEngine.Color.yellow.g;
    4.     color.Value.z = UnityEngine.Color.yellow.b;
    5.     color.Value.w = UnityEngine.Color.yellow.a;
    6. });
    Step 2, Option B) Or if you are fetching the entity within another query you can do something like:
    Code (CSharp):
    1. if (EntityManager.HasComponent<URPMaterialPropertyBaseColor>(entity)) {
    2.     URPMaterialPropertyBaseColor color = EntityManager.GetComponentData<URPMaterialPropertyBaseColor>(entity);
    3.     color.Value.x = UnityEngine.Color.yellow.r;
    4.     color.Value.y = UnityEngine.Color.yellow.g;
    5.     color.Value.z = UnityEngine.Color.yellow.b;
    6.     color.Value.w = UnityEngine.Color.yellow.a;
    7. }
    There are several other "built-in" parameters listed in the documentation link I provided above. The way I figured out what the components were called was by going to this folder: C:\Users\Me\AppData\Local\Unity\cache\packages\packages.unity.com\com.unity.rendering.hybrid@0.8.0-preview.18\Unity.Rendering.Hybrid\URPMaterialProperties (where Me is the username). I didn't find anything in the documentation that listed the IComponent derived struct names, so that folder was really helpful in figuring out what components were available.

    One of the ones I tried was URPMaterialPropertyEmissionColor, but it never seemed to work. I don't know if it's a bug or if it doesn't work with certain shaders, or if it needs to be handled differently than the base color one, or if there's some global setting for emission stuff that needs to be tweaked.

    My test setup is 2020.1.2 with Hybrid Renderer V2 0.8.0-preview.18 and URP.
     
    Last edited: Aug 15, 2020