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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to change color of material

Discussion in 'Entity Component System' started by schaefsky, Apr 23, 2020.

  1. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    I have a monoBehaviour to change the color of a material like so:
    Code (CSharp):
    1. materials.SetColor("_Color", c);
    However almost all my game code (besides UI) is written in DOTS, and I would like to change the color (mostly alpha) depending on the value of a thrust component of my spaceships.
    I have spaceships with a mesh for the ship itself and a mesh for the exhaust on which I want to change the color on.
    I am using the Hybrid Renderer v1 I guess (Unity 2019 and used a normal 3D project, would be willing to upgrade to Unity 2020).
    All my searches were pretty confusing to be honest, I am new to Unity and a lot went over my head, things like using MaterialPropertyBlock, and not using it because things work differently now, and people apparently writing their own render pipeline...
    Is there an easy way to change the color to different values for different entities without using SRPs? I use a lot of assets from the store and am worried things like particle effects and shaders won't work in the SRPs out of the box?
     
  2. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
  3. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    With DOTS? No. You need either HDRP or URP to do that.
     
    schaefsky likes this.
  4. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    And is my understanding correct that "legacy" shaders and/or particle effects will not work in HDRP/URP?
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    You may or may not get it to work by mimicking what URP/HDRP shader graphs generate when you check the Hybrid Instanced checkbox. Not sure though, as Unity have stated that codepath uses a modified SRP batcher which is black-box.

    As for legacy shaders, only unlit shaders work in URP/HDRP.

    Texture-wise URP is very similar to legacy and the material upgrader is very good. So it is only custom legacy lit shaders that will have a problem.
     
  6. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    Ok, so I converted one of the example projects to URP and almost everything is pink or white now. So I guess that does not work :)
    Is there really no other way to change material color?
    I found some code here https://reeseschultz.com/pointing-and-clicking-with-unity-ecs/
    Code (CSharp):
    1.         var renderMesh = entityManager.GetSharedComponentData<RenderMesh>(selectedEntity);
    2.         var mat = new UnityEngine.Material(renderMesh.material);
    3.         mat.SetColor("_Color", UnityEngine.Random.ColorHSV());
    4.         renderMesh.material = mat;
    5.  
    6.         entityManager.SetSharedComponentData(selectedEntity, renderMesh);
    What I do not understand is the GetSharedComponentData<RenderMesh>(entity) when my model is built with multiple meshes.
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    The material upgrader is not automatic for URP. It is under Edit->Render Pipeline.

    That code you posted is another way of doing it, but terribly inefficient if you have lots of potential material values.
     
  8. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    Actually I forgot to apply the render pipeline asset in the project settings, but it does not help much. Most things are pink and I got messages like this in the log:

    WarpJumpParticles_red_linear material was not upgraded. There's no upgrader to convert Legacy Shaders/Particles/Additive shader to selected pipeline

    missile_006 material was not upgraded. There's no upgrader to convert FORGE3D/Surface shader to selected pipeline


    So just to try it, how would I get s specififc mesh from an entity? I do not get how to use GetSharedComponentData<RenderMesh>(entity) when my model is built with multiple meshes.
     
  9. soleron

    soleron

    Joined:
    Apr 21, 2013
    Posts:
    522
    Custom shaders are not supported. UNLESS the makers of the shaders have provided an HDRP equivalent but even in that case you will have to do it manually.

    Only Native Unity materials are automatically converted.

    Regarding the particle shaders, you will have to install the related SRP Particle shaders.
    There is a button in the package manager, when you select the relevant package.
     
  10. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    It seems I can not find this button.
    Or did you mean the Upgrade Project Materials to Lightweight RP Materials function?
     
  11. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    Okay, so I did not notice before that all the submeshes get converted to different entities... which explains the GetSharedComponentData<RenderMesh>(entity).

    The way I see it I have a parent entity (my spaceship) and there I have LinkedEntityGroups which will contain the child entities.
    I want to modify the color of some childs (engine glow) depending on a component value of the parent (throttle value).

    My way of thinking is to tag the engine glow childs to process them in a system and change the material (maybe doing some lookup table), but I need to access the thrust value of the parent.

    What is the best way to get that value of the parent in a system that modifies the childs? Should I loop through LinkedEntitiesGroup to set some value or store the parent entity to retrieve the data? Should I go along the parent path until I find the root entity? Or something completely different?
     
  12. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    The way I do this is I store a reference to the root-most ship entity on each child that needs access to the gameplay parameters.

    However, I really encourage you to either switch to an SRP or mentally prepare yourself to try writing custom shaders, because instanced properties are pretty much required for this kind of mechanic when using the Hybrid Renderer.
     
    schaefsky likes this.
  13. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    89
    Well yes, I would like to. The problem is I have absolutly zero knowledge about particle systems or shaders. On top of that I am really not an artist. So all my graphic assets are from the asset store or similar. And currently there do not seem to be assets available for the new pipelines.
    I will mostly use things like explosions and projectile effects, which do not seem to auto-convert to URP.
    So my plan is to just try it with hybrid and see what happens performance wise. Then I will see.

    Would you share how you get the root entity? Do you do it during conversion?
     
    Last edited: Apr 28, 2020
  14. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Yes. During conversion. You can do it through code working with Transforms, or you can require a serialized reference to the authoring component that runtime component you need.