hey guys
I canāt seem to find how to change a materialās color anywhere (using Material.Color isnāt an option).
using Unity 2022.3.10f1
Edit:
Fixed and solved. Answer in the messages.
by user 198447544408342528
hey guys
I canāt seem to find how to change a materialās color anywhere (using Material.Color isnāt an option).
using Unity 2022.3.10f1
Edit:
Fixed and solved. Answer in the messages.
by user 198447544408342528
Hi, do you have a script to show how you currently try doing it? For what are you trying to change the color? A 3D Object or a UI element?
a 3d object (mesh).
by user 198447544408342528
import { EventList, serializable } from "@needle-tools/engine"
import { IInteractable } from "./IInteractable";
import { Color, Material } from "three";
export class InteractableObject extends IInteractable{
/** The event that will occur opun interaction */
@serializable(EventList) onInteraction?: EventList;
/** The material to set the color of interactable object. Leave undefined to not apply material change */
@serializable() materialToSetColor?: Material;
/** The color of the interactable object. */
@serializable() colorOfInteractable?: Color;
override Interact(): () => void {
return () => this.onInteraction?.invoke();
}
// coloring the object to show its interactable
start(): void {
if (this.materialToSetColor == undefined) return;
if (!this.materialToSetColor) return;
this.materialToSetColor.Color = colorOfInteractable;
}
}
by user 198447544408342528
the last line " this.materialToSetColor.Color = colorOfInteractable; " has an error āProperty āColorā does not exist on type āMaterialā.ts(2339)ā
by user 198447544408342528
Ah yes thatās the way threejs works. They have different material types that represent their shaders - so different Material types have different properties. You can change the type to e.g. MeshStandardMaterial
Btw the lines with Material and Color should also get the type: @serializable(Color)
itās also .color
(lowercase )
The Material class doesnt have a color property
could you please explain more about when I need to put a variable in the serializeable āattributeā?
by user 198447544408342528
Itās for deserialization of the data stored in the GLB. When your GLB exported from Unity or Blender is loaded and the scripts are created we have to re-create the properties (e.g. a Color property) - the type there is letting the deserializer know what he should create with the data. In some cases we can āguessā it (e.g. for Material
we actually do that because of the way the data is stored using a special string /material/<index_of_material_in_glb
for example < thatās a json pointer. For other types we can not really know for sure)
We recommend to always put in the expected type to get rid of any guesswork and make it a habit then thereās no confusion if something isnt correctly deserialized
BTW, the error is now gone but I canāt see the material on my object.
This is the updated code:
import { EventList, serializable } from "@needle-tools/engine"
import { IInteractable } from "./IInteractable";
import { Color, Material, MeshStandardMaterial } from "three";
export class InteractableObject extends IInteractable{
/** The event that will occur opun interaction */
@serializable(EventList) onInteraction?: EventList;
/** The material to set the color of interactable object. Leave undefined to not apply material change */
@serializable(MeshStandardMaterial) materialToSetColor?: MeshStandardMaterial;
/** The color of the interactable object. */
@serializable(Color) colorOfInteractable?: Color;
override Interact(): () => void {
return () => this.onInteraction?.invoke();
}
// coloring the object to show its interactable
start(): void {
if (this.materialToSetColor == undefined) return;
if (!this.materialToSetColor) return;
this.materialToSetColor.color = this.colorOfInteractable!;
}
}
by user 198447544408342528
Thanks for the explanation! I will make sure to update my team of this best practice, and change the snippets file we created for the engine
by user 198447544408342528
Thatās now because the TS ā C# compiler for Unity doesnt know that MeshStandardMaterial
is meant to be a Material
Type in Unity. Iāll make a note to add this! There are multiple ways to solve it. One way would be to add a comment to force the correct type in Unity (these special attributes are documented here or here
//@type UnityEngine.Material
@serializable(MeshStandardMaterial) materialToSetColor?: MeshStandardMaterial;
Oh amazing. Thank you! I will make sure to add this attribute
by user 198447544408342528
A second way would be to leave the type in your class:
@serializable(MeshStandardMaterial) materialToSetColor?: MeshStandardMaterial;
and instead cast it where you know itās of a certain type:
if(this.materialToSetColor instanceof MeshStandardMaterial) this.materialToSetColor.color = this.colorOfInteractable!;
Yes itās super useful sometimes especially if you have the same typename multiple times in Unity and want to force the component compiler to generate a specific field type! Itās not perfect but works most of the time
And a third way:
if("color" in this.materialToSetColor) this.materialToSetColor.color = this.colorOfInteractable!;