Change material on Object Unity

Is it possible to change the material on a single object in Unity Needle - or assign one material to an object once instantiated ?

The ChangeMaterialOnClick - seems to swap a material on all objects that are using the material.
In Unity it would be : Object.GetComponent ().material = Material1;

Original Post on Discord

by user 634679671727849482

Hi,

  • a no-code solution would be to copy the material in unity that you want to change and only assign it to the object that you want it being changed for
  • with code it’s almost the same as in the unity code. You get the renderer obj.getComponent(Renderer).sharedMaterials[0] = material1

import { GameObject, Behaviour, Renderer, serializable } from “@needle-tools/engine”;
import { Material } from “three”;
import{ Color } from “three”;

export class HK_MaterialSwap extends Behaviour
{
@serializable(Material)
m_material?: Material;

start()
{
console.log("This material " + this.m_material);
if(!this.m_material)
{
const obj = this.gameObject;
obj.getComponent(Renderer).sharedMaterials[0] = this.m_material;
console.log(“Success”);

    }           

    
}

by user 634679671727849482

So - this is throwing errors and I’m not sure why ?

by user 634679671727849482

What errors are you getting? Your check in if(!this.m_material) is probably the opposite of what you want. You’re checking if the material is null and then you assign it.

by user 634679671727849482

Sorry - removed that now - but thought this should work ?

by user 634679671727849482

You need to check if a renderer exists. The vscode overlay should tell you that if you hover the error.

const renderer = obj.getComponent(Renderer);
if(renderer)  { ... } 

ok -thanks - I’ll try that- it was actually telling me the material was NUll - I think ??

by user 634679671727849482

image.png

by user 634679671727849482

well it’s multiple things ^^ your material could be undefined which would be a problem (that’s because you declared it as m_material? ) or your renderer could be null (e.g. if it’s an empty object in Unity or so, not all objects have a renderer)

Just a cube with material assigned in the inspector
image.png

by user 634679671727849482

I thought that’s how you serialise a material in this ?

by user 634679671727849482

Yes sure, i just mean your typescript code says this because of the way you declare it. And it could really be null because you could not have assigned it in Unity (if you forgot or so) so that’s ok. You just need to check the case in your code and then youre good

const renderer = obj.getComponent(Renderer);
if(renderer && this.m_material)  { ... } 

ok Thanks Marcel I’ve got this working -

import { Material } from "three";
import{ Color } from "three";

export class HK_MaterialSwap extends Behaviour
{
    @serializable(Material)
    my_material?: Material;
    
    @serializable(GameObject)
    my_gameobject?: GameObject; // = this.gameObject;

   start() 
    {
        //this.m_material = this.gameObject.getComponent(Renderer)?.sharedMaterials[0];
        console.log("This material " + this.my_material);   
     
           // this.my_gameobject = this.gameObject;
            
            //const myobj = this.my_gameobject;
            const renderer = this.my_gameobject.getComponent(Renderer);

            if(renderer && this.my_material && this.my_gameobject)
            {

                this.my_gameobject.getComponent(Renderer).sharedMaterials[0] = this.my_material;

            } 
        
    }
}```

*by user 634679671727849482*

Should this really be a ‘red line’ though or a warning ?

by user 634679671727849482

It works as expected in the browser but has been throwing me all day ?

by user 634679671727849482

Yes - well technically you do the check a few lines above - just use the rendererthere instead of getting it again

this.my_gameobject.getComponent(Renderer).sharedMaterials[0] = this.my_material; should be renderer.sharedMaterials[0] = this.my_material;

Yes -sorry again - went through a few things to try to see why it was redlining.
So this is it without redlining : for any other other newbies :slightly_smiling_face:

import { Material } from "three";


export class HK_MaterialSwap extends Behaviour
{
    @serializable(Material)
    my_material?: Material;
    
    @serializable(GameObject)
    my_gameobject?: GameObject; // = this.gameObject;

   start() 
    {
        //this.m_material = this.gameObject.getComponent(Renderer)?.sharedMaterials[0];
        console.log("This material " + this.my_material);   
     
           // this.my_gameobject = this.gameObject;
            
            const myobj = this.my_gameobject;
            if(myobj)
            {
                const renderer = myobj.getComponent(Renderer);

                if(renderer && this.my_material)
                {
    
                    renderer.sharedMaterials[0] = this.my_material;
    
                } 
            }
         
        
    }
}```

*by user 634679671727849482*