1 前言
选中物体消融特效中基于 Shader 实现了消融特效,本文将基于 Shader Graph 实现消融特效,两者原理一样,只是表达方式不同,另外,选中物体消融特效中通过 discard 丢弃片元,本文通过 alpha 测试丢弃片元。
Shader Graph环境搭建、简单应用详见→Shader Graph简介。
本文完整资源见→Unity3D消融特效。
2 消融特效实现
创建 Unlit Shader Graph,重命名为 DissolveEffect,编辑如下。
其中,Alpha 测试需要在 Graph Settings 中开启,如下。
为实现点击消失效果,需要编写脚本如下。
DieController.cs
using UnityEngine;public class DieController : MonoBehaviour {private RaycastHit hit; // 碰撞信息private void Start() {hit = new RaycastHit();}private void Update() {if (Input.GetMouseButtonUp(0)) {GameObject hitObj = GetHitObj();if (hitObj != null) {GameObject rootObj = GetRootObj(hitObj);rootObj.AddComponent<DissolveEffect>();}}}private GameObject GetHitObj() { // 获取屏幕射线碰撞的物体Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out hit)) {return hit.collider.gameObject;}return null;}private GameObject GetRootObj(GameObject obj) { // 获取根对象while (obj.transform.parent != null && obj.layer == obj.transform.parent.gameObject.layer) {obj = obj.transform.parent.gameObject;}return obj;}
}
DissolveEffect.cs
using UnityEngine;[DisallowMultipleComponent] // 不允许在同一对象上挂载多个该组件
public class DissolveEffect : MonoBehaviour {private Renderer[] renderers; // 渲染器private Material dissolveMat; // 消融材质private float burnSpeed = 0.25f; // 燃烧速度private float burnAmount = 0; // 燃烧量, 值越大模型镂空的越多private void Awake() {dissolveMat = Resources.Load<Material>("DissolveMat");renderers = GetComponentsInChildren<Renderer>();}private void OnEnable() {foreach (Renderer renderer in renderers) {Material[] materials = renderer.sharedMaterials;Material[] dissolveMaterials = new Material[materials.Length];for (int i = 0; i < materials.Length; i++) {Material newMaterial = new Material(dissolveMat);SetTexture(materials[i], newMaterial);SetColor(materials[i], newMaterial);newMaterial.SetFloat("_BurnAmount", 0);dissolveMaterials[i] = newMaterial;}renderer.sharedMaterials = dissolveMaterials;}}private void Update() {burnAmount += Time.deltaTime * burnSpeed;foreach (Renderer renderer in renderers) {Material[] materials = renderer.sharedMaterials;foreach (Material material in materials) {material.SetFloat("_BurnAmount", burnAmount);}}if (burnAmount >= 1f) {Destroy(gameObject);}}private void SetTexture(Material oldMaterial, Material newMaterial) { // 设置材质if (oldMaterial.HasTexture("_MainTex")) {Texture texture = oldMaterial.GetTexture("_MainTex");newMaterial.SetTexture("_MainTex", texture);}}private void SetColor(Material oldMaterial, Material newMaterial) { // 设置颜色Color color = Color.white;if (oldMaterial.HasColor("_Color")) {color = oldMaterial.GetColor("_Color");}newMaterial.SetColor("_Color", color);}
}
运行效果如下。