55.C#代码修改材质参数

55.屏幕后期处理效果-CSharp代码修改材质参数


55.1 知识点

知识回顾

Mesh Renderer(网格渲染器)

  • Mesh(网格)
    关联 MeshFilter(网格过滤器组件)
    包含 Geometry Data(几何数据)

  • Material(材质)

    • Shader(着色器)
    • Properties(属性:颜色、纹理等,Shader中决定哪些属性暴露在材质上)

Skinned Mesh Renderer(蒙皮网格渲染器)

  • Mesh(网格)
    包含 Geometry Data(几何数据)

  • Bones & Weights(骨骼与权重)

  • Material(材质)

    • Shader(着色器)
    • Properties(属性:颜色、纹理等,Shader中决定哪些属性暴露在材质上)

如何得到对象使用的材质

步骤

  1. 获取对象的渲染器(Renderer

    • Mesh Renderer 和 Skinned Mesh Renderer 都继承自 Renderer
    • 可以用里式替换原则通过父类获取和装载子类对象
  2. 通过渲染器获取对应材质

    • 使用 materialsharedMaterial 获取单个材质
    • 如果存在多个材质,使用 materialssharedMaterials 获取材质数组

material 与 sharedMaterial 的区别

  • material

    • 返回对象的实例化材质,为对象创建独立材质副本。
    • 修改 material 属性的材质只影响该对象,不影响其他使用相同材质的对象。
    • 增加内存消耗,但支持单独修改单个对象。
  • sharedMaterial

    • 返回共享材质,多个对象共享同一个材质实例。
    • 修改 sharedMaterial 会影响所有使用此材质的对象。
    • 不增加内存消耗,但会批量修改。

示例代码

//获取对象的渲染器
Renderer renderer = GetComponent<Renderer>();

//渲染器不为空才获取材质
if (renderer != null)
{
    //sharedMaterial和material的区别
    //sharedMaterial:一个是改一个都变
    //material:一个是改一个不会影响其它使用相同材质球的对象

    //得到主材质球
    material = renderer.material;
    sharedMaterial = renderer.sharedMaterial;

    //得到所有的材质球
    Material[] materials = renderer.materials;
    Material[] sharedMaterials = renderer.sharedMaterials;
}

如何修改材质属性和材质中的常用方法

修改颜色

材质对象提供 color 成员,用于直接修改材质的颜色。

if (Input.GetKeyDown(KeyCode.Q))
{
    material.color = color;
}

修改纹理

材质对象的 mainTexture 成员用于修改主纹理。

if (Input.GetKeyDown(KeyCode.W))
{
    material.mainTexture = Resources.Load<Texture2D>("transparent_texture");
}

通用修改方式

通过材质的各种 Set 方法修改属性,传入属性名和对应的值即可完成赋值。

注意:属性名必须与 Shader 中 SubShader 定义的名称一致,而非材质面板中的显示名称。

常见方法包括:

  • 检查属性是否存在HasXXX
  • 获取属性值GetXXX
  • 设置属性值SetXXX
if (Input.GetKeyDown(KeyCode.E))
{
    if (material.HasColor("_Color"))
    {
        material.SetColor("_Color", color);
        print(material.GetColor("_Color"));
    }
}

if (Input.GetKeyDown(KeyCode.R))
{
    if (material.HasFloat("_FresnelScale"))
        material.SetFloat("_FresnelScale", fresnelScale);
}

修改渲染队列

可以通过 material.renderQueue 属性修改材质的渲染队列顺序。

material.renderQueue = 2000;

修改 Shader

材质的 shader 属性用于更换当前 Shader,使用 Shader.Find 方法获取目标 Shader。

material.shader = Shader.Find("Unlit/Lesson32_FresnelBase");

设置纹理偏移和缩放

通过 SetTextureOffsetSetTextureScale 方法设置主纹理的偏移与缩放。

material.SetTextureOffset("_MainTex", new Vector2(0.5f, 0.5f));
material.SetTextureScale("_MainTex", new Vector2(0.5f, 0.5f));

总结

在 Unity 中通过 C# 代码修改 Shader 的相关参数信息,一般通过材质对象进行操作。材质提供了多种方法,常见操作包括:

  • 修改颜色、纹理等属性
  • 检查属性是否存在 (HasXXX)
  • 获取属性值 (GetXXX)
  • 设置属性值 (SetXXX)
  • 修改渲染队列
  • 设置纹理的偏移与缩放

材质是 Shader 参数修改的核心,掌握其用法可以更灵活地操作渲染效果。


55.2 知识点代码

Lesson55_屏幕后期处理效果_CSharp代码修改材质参数.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson55_屏幕后期处理效果_CSharp代码修改材质参数 : MonoBehaviour
{
    public Color color;
    [Range(0, 1)] public float fresnelScale;

    private Material material;
    private Material sharedMaterial;


    void Start()
    {
        //获取对象的渲染器
        Renderer renderer = GetComponent<Renderer>();

        //渲染器不为空才获取材质
        if (renderer != null)
        {
            //sharedMaterial和material的区别
            //sharedMaterial:一个是改一个都变
            //material:一个是改一个不会影响其它使用相同材质球的对象

            //得到主材质球
            material = renderer.material;
            sharedMaterial = renderer.sharedMaterial;

            //得到所有的材质球
            Material[] materials = renderer.materials;
            Material[] sharedMaterials = renderer.sharedMaterials;
        }

        #region 知识回顾

        //Mesh Renderer(网格渲染器)
        //  └── Mesh(网格) —— MeshFilter(网格过滤器组件进行关联)
        //        └── Geometry Data(几何数据)
        //  └── Material(材质)
        //        └── Shader(着色器)
        //        └── Properties(属性:颜色、纹理等 —— 在Shader中决定哪些属性暴露在材质上)

        //Skinned Mesh Renderer(蒙皮网格渲染器)
        //  └── Mesh(网格)
        //        └── Geometry Data(几何数据)
        //  └── Bones & Weights(骨骼与权重)
        //  └── Material(材质)
        //        └── Shader(着色器)
        //        └── Properties(属性:颜色、纹理等 —— 在Shader中决定哪些属性暴露在材质上)

        #endregion

        #region 知识点一 如何得到对象使用的材质

        //1.获取到对象的渲染器Renderer 
        //  Mesh Renderer和Skinned Mesh Renderer都继承Renderer
        //  我们可以用里式替换原则父类获取、装载子类对象
        //2.通过渲染器获取到对应材质
        //  我们可以利用渲染器中的material或者sharedMaterial来获取物体的材质
        //  如果存在多个材质,可以使用renderer.materials或renderer.sharedMaterials来获取

        //material和sharedMaterial的区别
        //material:
        //material属性会返回对象的实例化材质, 相当于它会为对象创建一个该材质的独立副本
        //当你通过material属性修改材质时,这些更改只会影响这个特定对象,而不会影响使用相同材质的其他对象
        //使用material会增加内存消耗,因为每个对象都有自己独立的材质副本,但是可以单独修改单个对象

        //sharedMaterial:
        //sharedMaterial属性会返回对象的共享材质,相当于它返回的是所有使用这个材质的对象共享的同一个材质实例
        //当你通过sharedMaterial属性修改材质时,这些更改会影响所有使用这个材质的对象
        //使用sharedMaterial不会增加内存消耗,但是会批量修改所有使用该材质的对象

        #endregion

        #region 知识点二 如何修改材质属性和材质中的常用方法

        //1.颜色
        //  材质对象中有color成员用于颜色修改
        //2.纹理
        //  材质对象中有mainTexture成员用于主纹理修改
        //3.通用修改方式
        //  材质中有各种Set方法,用于修改属性
        //  通过传入属性名,以及对应值进行赋值
        //  注意:属性值以SubShader中声明的属性名为准,而不是面板上的显示
        //4.修改Shader
        //  调用材质中shader属性进行修改
        //  利用Shader.Find(Shader名)方法得到对应Shader


        //除了刚才学习的修改属性的相关方法
        //材质中还有:
        //1.判断某类型指定名字属性是否存在 HasXXX
        //2.获取某个属性值 GetXXX
        //3.修改渲染队列
        //4.设置纹理缩放偏移
        //等等

        #endregion

        #region 总结

        //Unity中想要通过C#代码修改Shader相关参数信息
        //我们一般都是通过材质去进行修改的
        //需要使用材质提供的各种相关方法进行修改

        #endregion
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //修改颜色
            material.color = color;
        }

        if (Input.GetKeyDown(KeyCode.W))
        {
            //修改主纹理
            material.mainTexture = Resources.Load<Texture2D>("transparent_texture");
        }

        //常用的 判断是否存在 设置 得到值 方法 HasXXX SetXXX GetXXX 传入的是材质对应的Shader中的属性名
        if (Input.GetKeyDown(KeyCode.E))
        {
            if (material.HasColor("_Color"))
            {
                material.SetColor("_Color", color);
                print(material.GetColor("_Color"));
            }
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            if (material.HasFloat("_FresnelScale"))
                material.SetFloat("_FresnelScale", fresnelScale);
        }


        //修改渲染队列
        material.renderQueue = 2000;

        //修改材质球使用的shader
        material.shader = Shader.Find("Unlit/Lesson32_FresnelBase");

        //设置主纹理偏移和缩放
        material.SetTextureOffset("_MainTex", new Vector2(0.5f, 0.5f));
        material.SetTextureScale("_MainTex", new Vector2(0.5f, 0.5f));
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏