ChangeTransparent:用于控制物体材质透明和高亮显示

0 阅读2分钟

概述(Overview)

ChangeTransparent 是一个用于控制物体材质透明和高亮显示的 Unity 组件。它支持将非聚焦物体透明化,并恢复指定结构的原始材质,适合教学拆解展示、设备结构聚焦等场景。


依赖(Dependencies)

  • UnityEngine
  • UnityEngine.UI
  • Renderer
  • Material

公共成员(Public Fields)

名称类型说明
Transform rootTransform父物体根节点,作为查找范围起点
List<Transform> allListList<Transform>所有可操作物体缓存列表
List<ChangeMat> changeMatsList<ChangeMat>需要显示的结构列表,含按钮和子物体
Material transparentMaterialMaterial用于透明化的材质

事件(Events)

名称类型说明
ChangeMatAction<string>用于请求显示指定结构
RecoveryMatAction恢复所有结构原始材质

方法一览(API Index)

方法名访问级别说明
AddMaterialToDictionary()private缓存所有物体的原始材质
Recovery()private恢复所有结构材质
GetItem(string itemName)private显示指定结构,透明其他
RecoveryTransparent(Transform tran, Dictionary<string, Material[]> matDict)private static恢复指定物体的原始材质
ModTransparent(Transform tran, Material transparentMaterial)private static应用透明材质到指定物体
GetGameObjectPath(Transform obj)private static获取物体层级路径
GetChild(Transform father)private static获取指定父物体所有带 Renderer 的子物体
DemoTest()private演示用,恢复材质测试
Transparent()private (ContextMenu)编辑器初始化所有角色材质缓存

方法详情(Methods)

AddMaterialToDictionary

/// <summary>
/// 缓存所有物体的原始材质
/// </summary>
/// <remarks>
/// - 以 Transform 的完整层级路径作为 Key
/// - 仅缓存包含 Renderer 的物体
/// - 必须在 Awake 或 Start 阶段调用
/// </remarks>
private void AddMaterialToDictionary()
{
    foreach (var child in allList)
    {
        var path = GetGameObjectPath(child);
        if (child.GetComponent<Renderer>() == null) continue;

        var materials = child.GetComponent<Renderer>().materials;
        _materials.Add(path, materials);
    }
}

Recovery

/// <summary>
/// 恢复所有结构的原始材质
/// </summary>
private void Recovery()
{
    changeMats.ForEach(x =>
    {
        x.child.ForEach(o => { RecoveryTransparent(o, _materials); });
    });
}

GetItem

/// <summary>
/// 显示指定结构,其余结构全部透明
/// </summary>
/// <param name="itemName">结构根节点名称</param>
private void GetItem(string itemName)
{
    var item = changeMats.First(x => x.root.name == itemName);

    foreach (var child in allList)
    {
        ModTransparent(child, transparentMaterial);
    }

    item.child.ForEach(o =>
    {
        RecoveryTransparent(o, _materials);
    });
}

RecoveryTransparent

/// <summary>
/// 恢复指定物体的原始材质
/// </summary>
/// <param name="tran">目标物体 Transform</param>
/// <param name="matDict">材质缓存字典</param>
private static void RecoveryTransparent(
    Transform tran,
    Dictionary<string, Material[]> matDict)
{
    var path = GetGameObjectPath(tran);
    tran.GetComponent<Renderer>().materials = matDict[path];
}

ModTransparent

/// <summary>
/// 将指定物体设置为透明材质
/// </summary>
/// <param name="tran">目标物体 Transform</param>
/// <param name="transparentMaterial">透明材质</param>
private static void ModTransparent(Transform tran, Material transparentMaterial)
{
    var mat = new Material[tran.GetComponent<Renderer>().materials.Length];
    for (var i = 0; i < mat.Length; i++)
    {
        mat[i] = transparentMaterial;
    }

    tran.GetComponent<Renderer>().materials = mat;
}

GetGameObjectPath

/// <summary>
/// 获取物体在层级中的完整路径
/// </summary>
/// <param name="obj">目标 Transform</param>
/// <returns>层级路径字符串</returns>
private static string GetGameObjectPath(Transform obj)
{
    var path = "/" + obj.name;
    while (obj.parent != null)
    {
        obj = obj.parent;
        path = "/" + obj.name + path;
    }
    return path;
}

GetChild

/// <summary>
/// 获取指定父物体所有带 Renderer 的子物体列表
/// </summary>
/// <param name="father">父物体 Transform</param>
/// <returns>子物体列表</returns>
private static List<Transform> GetChild(Transform father)
{
    return (from show in father.GetComponentsInChildren<Transform>()
            let temp = GetGameObjectPath(show)
            where show.GetComponent<Renderer>() != null
            select show).ToList();
}

DemoTest

/// <summary>
/// 演示用函数,恢复材质测试
/// </summary>
private void DemoTest()
{
    foreach (var child in allList)
    {
        var path = GetGameObjectPath(child);
        if (child.GetComponent<Renderer>() == null) continue;
        var materials = child.GetComponent<Renderer>().materials;
        _materials.Add(path, materials);
    }

    var item = changeMats.First(x => x.root.name == "itemName");

    foreach (var child in allList)
    {
        ModTransparent(child, transparentMaterial);
    }

    item.child.ForEach(o =>
    {
        RecoveryTransparent(o, _materials);
    });
}

Transparent

#if UNITY_EDITOR
/// <summary>
/// 编辑器上下文菜单:初始化所有角色的材质缓存
/// </summary>
[ContextMenu("初始化所有角色")]
private void Transparent()
{
    allList.Clear();
    foreach (var t in GetChild(root))
    {
        allList.Add(t);
    }

    changeMats.ForEach(x => { x.child = GetChild(x.root.transform); });
}
#endif