unity实现选中物体正常让其他物体透明化功能,高亮

通过点击或者调用ShowUnitHighLight方法,即可实现同层级内所有节点的材质半透明和指定物体正常材质的功能。

示例图如下

脚本如下

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

public class RaycastTransparency : MonoBehaviour
{
    public Material transparentMaterial; // 统一的半透明材质

    private Transform lastHitTransform; // 上一次点击的对象
    private Dictionary<Transform, Material[]> originalMaterialsCache = new Dictionary<Transform, Material[]>(); // 缓存每个节点的原始材质

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // 检测鼠标左键点击
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit))
            {
                if (hit.collider != null)
                {
                    ShowUnitHighLight(hit.collider.transform);
                }
            }
        }
    }

    public void ShowUnitHighLight(Transform hit) {
        // 获取点击的对象
        Transform hitTransform = hit;

       // 如果点击的是新对象
        if (hitTransform != lastHitTransform)
        {
            // 恢复上一次点击的对象及其子节点的原始材质
            if (lastHitTransform != null)
            {
                RestoreMaterialsRecursive(lastHitTransform);
            }

            // 获取同级对象
            Transform parent = hitTransform.parent;
            if (parent != null)
            {
                foreach (Transform sibling in parent)
                {
                    if (sibling != hitTransform)
                    {
                        // 将其他同级对象及其子节点设置为半透明材质
                        SetMaterialRecursive(sibling, transparentMaterial);
                    }
                }
            }

            // 将当前点击的对象及其子节点恢复为原始材质
            RestoreMaterialsRecursive(hitTransform);

            // 更新上一次点击的对象
            lastHitTransform = hitTransform;
        }

    }

    // 递归设置对象及其子节点的材质
    void SetMaterialRecursive(Transform target, Material material)
    {
        Renderer renderer = target.GetComponent<Renderer>();
        if (renderer != null)
        {
            // 缓存原始材质(如果尚未缓存)
            if (!originalMaterialsCache.ContainsKey(target))
            {
                originalMaterialsCache[target] = renderer.materials;
            }

            // 设置新材质
            Material[] newMaterials = new Material[renderer.materials.Length];
            for (int i = 0; i < newMaterials.Length; i++)
            {
                newMaterials[i] = material;
            }
            renderer.materials = newMaterials;
        }

        // 递归设置子节点的材质
        foreach (Transform child in target)
        {
            SetMaterialRecursive(child, material);
        }
    }

    // 递归恢复对象及其子节点的原始材质
    void RestoreMaterialsRecursive(Transform target)
    {
        Renderer renderer = target.GetComponent<Renderer>();
        if (renderer != null && originalMaterialsCache.ContainsKey(target))
        {
            // 恢复原始材质
            renderer.materials = originalMaterialsCache[target];
        }

        // 递归恢复子节点的原始材质
        foreach (Transform child in target)
        {
            RestoreMaterialsRecursive(child);
        }
    }
}

            

脚本可随意挂载,需要注意的是hit.collider != null这里只做了碰撞体的判断条件可以根据需求增加其他指定需求,并且改功能只实现了同级节点以及子节点之间的材质交互,碰撞体的父节点无法实现交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值