如何使溶解Shader脚本仅修改单个对象的材质参数
解决材质参数全局生效的问题
你的问题根源在于直接修改了共享材质资源——场景里所有使用这个Mushroom材质的对象都会同步响应参数变化,因为它们共用同一个材质实例。要让参数只对单个对象生效,我们需要为每个对象创建独立的材质实例,具体调整方案如下:
核心思路
- 为挂载脚本的对象创建专属的材质副本(实例化材质),而不是直接操作原始材质资源
- 后续所有参数修改都针对这个专属实例进行,不会影响其他使用原始材质的对象
修改步骤与代码示例
- 在脚本启动时,获取当前对象的
Renderer组件,并为其创建材质实例,替换原来直接引用共享材质的方式 - 修正
Update方法里的小错误:Time.time应该改为Time.deltaTime,否则溶解速度会随时间持续加快
修改后的完整代码如下:
public Material originalMushroomMaterial; // 原始材质资源(从Inspector赋值) private Material mushroomInstance; // 当前对象的专属材质实例 private float currStrength; private float maxStrength; private float speed = 0.6f; public bool let_dissolve = false; private void Start() { // 获取当前对象的Renderer组件 Renderer renderer = GetComponent<Renderer>(); if (renderer != null && originalMushroomMaterial != null) { // 创建材质实例,替换Renderer的材质为专属实例 mushroomInstance = new Material(originalMushroomMaterial); renderer.material = mushroomInstance; } } public void OnMouse() { Dissolve_rules_F(); Invoke("Dissolve_rules_T", 0.3f); } public void Dissolve_rules_T() { currStrength = 1.0f; maxStrength = 0.001f; let_dissolve = true; } public void Dissolve_rules_F() { currStrength = 0.001f; maxStrength = 1.0f; let_dissolve = false; } public void Update() { // 确保材质实例存在再进行操作 if (mushroomInstance == null) return; if (let_dissolve) { currStrength = Mathf.MoveTowards(currStrength, maxStrength, speed * Time.deltaTime); mushroomInstance.SetFloat("_Dissolve", currStrength); } else { // 修复原代码中Time.time导致的速度异常问题 currStrength = Mathf.MoveTowards(currStrength, maxStrength, speed * Time.deltaTime); mushroomInstance.SetFloat("_Dissolve", currStrength); } }
额外说明
- 现在你需要在Inspector里给
originalMushroomMaterial赋值原始的蘑菇材质,脚本会自动为每个对象创建独立副本 - 如果对象由多个子物体组成(包含多个Renderer),可以遍历所有子物体的Renderer并为每个创建实例,或者按需选择目标Renderer
- 材质实例会占用额外内存,若场景中有大量这类对象,记得在对象销毁时调用
Destroy(mushroomInstance)释放资源,避免内存泄漏
内容的提问来源于stack exchange,提问作者Maksym Kucherenko
相关产品推荐
相关产品推荐

