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

Unity Canvas中如何为物品图片添加选中高亮轮廓?

Unity UI物品图片添加选中轮廓的几种方案

因为你用的是Canvas中的UI图片,3D物体的轮廓资源自然不生效,以下是针对UI Image的三种实用方案:

方案1:使用Unity内置的Outline组件(最简单)

这是最快捷的实现方式,无需自定义资源:

  1. 选中你的物品图片对象,添加组件 Component → UI → Effects → Outline
  2. 在Outline组件面板中设置:
    • Effect Color:选中时的高亮颜色(比如黄色)
    • Effect Distance:轮廓的偏移量(比如(2,2))
    • Use Graphic Alpha:保持原图透明度,建议勾选
  3. 给图片添加Button组件(用于接收点击事件),然后挂载以下脚本:
using UnityEngine;
using UnityEngine.UI;

public class ItemSlotSelector : MonoBehaviour
{
    private Outline _outline;

    void Awake()
    {
        _outline = GetComponent<Outline>();
        _outline.enabled = false; // 默认隐藏轮廓
    }

    // 绑定到Button的OnClick事件
    public void OnSlotClicked()
    {
        // 先取消所有其他物品槽的选中状态
        foreach (var slot in FindObjectsOfType<ItemSlotSelector>())
        {
            slot._outline.enabled = false;
        }
        // 启用当前槽的轮廓
        _outline.enabled = true;
    }
}

方案2:双图片叠加(无代码/轻量代码)

适合需要更粗或自定义形状轮廓的场景:

  1. 给每个物品槽创建一个父对象,在父对象下添加两个Image:
    • 底层Image命名为OutlineImage:使用物品原图,设置高亮颜色,RectTransform尺寸比上层图大3-5像素(比如原图64x64,轮廓图设为68x68),默认禁用
    • 上层Image命名为ItemImage:放置正常物品图标,添加Button组件
  2. 挂载简单的控制脚本(或直接通过Button的SetActive事件控制):
using UnityEngine;
using UnityEngine.UI;

public class ItemSlotToggle : MonoBehaviour
{
    public Image outlineImage;

    void Start()
    {
        outlineImage.gameObject.SetActive(false);
    }

    public void OnSlotClicked()
    {
        // 取消其他槽的轮廓显示
        foreach (var slot in FindObjectsOfType<ItemSlotToggle>())
        {
            slot.outlineImage.gameObject.SetActive(false);
        }
        outlineImage.gameObject.SetActive(true);
    }
}

方案3:自定义UI Shader(灵活定制效果)

适合需要复杂轮廓效果(比如渐变、模糊)的场景:

  1. 创建一个新Shader,替换为以下代码:
Shader "UI/CustomOutline"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        _OutlineColor ("Outline Color", Color) = (1,0,0,1)
        _OutlineWidth ("Outline Width", Range(0, 10)) = 2
        _EnableOutline ("Enable Outline", Float) = 0
    }

    SubShader
    {
        Tags
        { 
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent" 
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
            };

            fixed4 _Color;
            fixed4 _OutlineColor;
            float _OutlineWidth;
            float _EnableOutline;
            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
                OUT.color = IN.color * _Color;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 baseColor = tex2D(_MainTex, IN.texcoord) * IN.color;
                if (_EnableOutline > 0.5)
                {
                    // 采样四个方向的像素生成轮廓
                    float2 offset = float2(_OutlineWidth / _ScreenParams.x, _OutlineWidth / _ScreenParams.y);
                    fixed4 outline = tex2D(_MainTex, IN.texcoord + offset) + 
                                      tex2D(_MainTex, IN.texcoord - offset) + 
                                      tex2D(_MainTex, IN.texcoord + float2(offset.x, -offset.y)) + 
                                      tex2D(_MainTex, IN.texcoord + float2(-offset.x, offset.y));
                    
                    outline = step(0.1, outline.a) * _OutlineColor;
                    baseColor = lerp(outline, baseColor, baseColor.a);
                }
                return baseColor;
            }
            ENDCG
        }
    }
}
  1. 创建一个Material,Shader选择UI/CustomOutline,将其赋值给物品Image的Material属性
  2. 挂载控制脚本:
using UnityEngine;
using UnityEngine.UI;

public class ShaderOutlineController : MonoBehaviour
{
    private Material _uiMaterial;

    void Awake()
    {
        _uiMaterial = GetComponent<Image>().material;
        _uiMaterial.SetFloat("_EnableOutline", 0);
    }

    public void OnSlotClicked()
    {
        foreach (var slot in FindObjectsOfType<ShaderOutlineController>())
        {
            slot._uiMaterial.SetFloat("_EnableOutline", 0);
        }
        _uiMaterial.SetFloat("_EnableOutline", 1);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:22:45