You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测Raycast是否停止碰撞物体并实现材质切换

解决Raycast未命中时恢复物体初始材质的问题

要实现仅在Raycast命中时高亮、未命中时恢复初始材质的逻辑,核心是跟踪上一次命中的物体,并在未命中或命中非目标物体时重置它的材质。以下是具体实现方案:

1. 新增必要的变量

在你的脚本中添加以下变量,用于记录上一次命中的物体和它的初始材质:

// 你已定义的高亮材质
public Material highlightMaterial;
// 记录上一次命中的BoardBlock物体
private GameObject _lastHitBlock;
// 临时存储物体的初始材质,无需给每个BoardBlock单独写脚本
private Dictionary<GameObject, Material> _originalMaterials = new Dictionary<GameObject, Material>();

2. 修改OnMouseDrag方法

更新拖拽检测逻辑,加入未命中时的材质恢复处理:

private void OnMouseDrag()
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    
    if (Physics.Raycast(ray, out RaycastHit hit))
    {
        if (hit.collider.CompareTag("BoardBlock"))
        {
            // 如果当前命中的不是上一个物体,先恢复上一个的材质
            if (_lastHitBlock != null && _lastHitBlock != hit.gameObject)
            {
                ResetBlockMaterial(_lastHitBlock);
            }
            
            // 仅在首次命中时存储物体的初始材质
            if (!_originalMaterials.ContainsKey(hit.gameObject))
            {
                _originalMaterials.Add(hit.gameObject, hit.collider.GetComponent<Renderer>().material);
            }
            
            // 设置当前物体为高亮材质
            hit.collider.GetComponent<Renderer>().material = highlightMaterial;
            _lastHitBlock = hit.gameObject;
        }
        else
        {
            // 命中非BoardBlock物体,恢复上一个命中物体的材质
            if (_lastHitBlock != null)
            {
                ResetBlockMaterial(_lastHitBlock);
                _lastHitBlock = null;
            }
        }
    }
    else
    {
        // 未命中任何物体,恢复上一个命中物体的材质
        if (_lastHitBlock != null)
        {
            ResetBlockMaterial(_lastHitBlock);
            _lastHitBlock = null;
        }
    }
}

3. 新增材质重置辅助方法

把重复的材质恢复逻辑抽成单独方法,让代码更简洁:

private void ResetBlockMaterial(GameObject block)
{
    if (_originalMaterials.TryGetValue(block, out Material originalMat))
    {
        block.GetComponent<Renderer>().material = originalMat;
        // 可选:如果不需要长期保留记录,可以移除字典中的条目
        // _originalMaterials.Remove(block);
    }
}

4. 补充OnMouseUp处理(可选但推荐)

为了避免拖拽结束后物体仍保持高亮,在鼠标抬起时也做一次材质重置:

private void OnMouseUp()
{
    if (_lastHitBlock != null)
    {
        ResetBlockMaterial(_lastHitBlock);
        _lastHitBlock = null;
    }
}

逻辑说明

  • 每次拖拽检测时,先判断Raycast命中状态:
    • 命中BoardBlock:先检查是否有上一个命中物体,有则重置;然后存储当前物体的初始材质(仅首次命中),再设置高亮。
    • 命中非BoardBlock或未命中任何物体:如果有上一个命中物体,立即重置它的材质并清空记录。
  • 使用字典存储初始材质,无需给每个BoardBlock单独编写脚本,减少代码耦合。

内容的提问来源于stack exchange,提问作者Solace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 04:50:25