Managing Materials
Changing parameters of the material assigned to the object surface via code, and replacing one assigned material with another.
Materials can be operated not only in the Editor — sometimes it is required to assign materials via code (in case of procedural content generation, for example) or configure some of their parameters. To control materials via API, we use the following two classes:
- Materials class that represents an interface for managing loaded materials (this is a manager class that can help you find a required material, for example).
- Material class that is used to manage each individual material.
The following example demonstrates how to inherit a new material from the base one, which is called mesh_base.
private void Init()
{
// creating a box (ObjectMeshDynamic node)
ObjectMeshDynamic my_mesh = Primitives.CreateBox(new vec3(1.5f, 1.5f, 1.5f));
// getting the base mesh_base material to inherit from
Material mesh_base = Materials.FindManualMaterial("Unigine::mesh_base");
// inherit a new child material from it
Material my_mesh_base = mesh_base.Inherit();
// save a child material to "materials/my_mesh_base0.mat" (before being saved
// this material only exists in RAM and is deleted as soon as the app is closed)
my_mesh_base.CreateMaterialFile("materials/my_mesh_base0.mat");
// setting the albedo color for the material to red
my_mesh_base.SetParameterFloat4("albedo_color", new vec4(255, 0, 0, 255));
// assigning the "my_mesh_base0.mat" material to surface 0 of the my_mesh object (ObjectMeshDynamiс)
my_mesh.SetMaterialPath("materials/my_mesh_base0.mat", 0);
// assigning the "my_mesh_base0.mat" material to all surfaces of the my_mesh object (ObjectMeshDynamiс)
my_mesh.SetMaterialPath("materials/my_mesh_base0.mat", "*");
}
private void Shutdown()
{
// deleting the "materials/my_mesh_base0.mat" material
Materials.RemoveMaterial(Materials.FindMaterialByPath("materials/my_mesh_base0.mat").GUID, true);
}
Practice#
Now let's create an interactive poster in our interior with an ability to change its albedo texture and apply a light filter to the picture (add a tone).
First, we're gonna need a Static Mesh plane.
- Go to the archviz/textures folder and find the plane.mesh asset.
- Drag it to the scene (a new Static Mesh object will be created) and change its name to "poster".
-
Set poster's transformation as shown on the image below:
- In the Surface Material section create a child material for the surface (click create a child material) to be able to change its parameters and drag the tex01.jpg asset to the Albedo field in the Textures tab.
Let's create the Customizable component (inherited from Interactable) that switches textures from the list (the array parameter) on the object — Action(0), and changes the albedo color multiplier by overrriding the method — Action(1). The code of the component looks like this:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Customizable : Interactable
{
public List<AssetLink> textures = null;
private int current_texture = 0;
public void Init()
{
// setting the tooltip text that will be displayed when hovering over the object
tooltip = "Right-click on the object switches the listed object materials in a cyclic order."
+" Pressing the 'TAB' button randomly changes the color tone.";
}
// overriding the action for the child component
public override void Action(int num)
{
// selecting the action
switch (num)
{
// switching between the listed albedo textures of the object material in a cyclic order
case 0:
// if the texture list is not set or empty, we do nothing
if(textures == null || textures.Count < 0)
return;
current_texture++;
if (current_texture >= textures.Capacity)
current_texture = 0;
(node as Unigine.Object).SetMaterialTexture("albedo", textures[current_texture].AbsolutePath,0);
break;
// randomly changing the albedo color multiplier for the current material on the object
case 1:
(node as Unigine.Object).GetMaterial(0).SetParameterFloat4("albedo_color", MathLib.RandColor());
break;
}
}
}
Then let's assign our component to the poster node and fill the texture array (tex01, tex02, tex03).
Now the image on the poster can be changed in one click.