Unity Canvas中如何为物品图片添加选中高亮轮廓?
Unity UI物品图片添加选中轮廓的几种方案
因为你用的是Canvas中的UI图片,3D物体的轮廓资源自然不生效,以下是针对UI Image的三种实用方案:
方案1:使用Unity内置的Outline组件(最简单)
这是最快捷的实现方式,无需自定义资源:
- 选中你的物品图片对象,添加组件
Component → UI → Effects → Outline - 在Outline组件面板中设置:
- Effect Color:选中时的高亮颜色(比如黄色)
- Effect Distance:轮廓的偏移量(比如(2,2))
- Use Graphic Alpha:保持原图透明度,建议勾选
- 给图片添加
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:双图片叠加(无代码/轻量代码)
适合需要更粗或自定义形状轮廓的场景:
- 给每个物品槽创建一个父对象,在父对象下添加两个Image:
- 底层Image命名为
OutlineImage:使用物品原图,设置高亮颜色,RectTransform尺寸比上层图大3-5像素(比如原图64x64,轮廓图设为68x68),默认禁用 - 上层Image命名为
ItemImage:放置正常物品图标,添加Button组件
- 底层Image命名为
- 挂载简单的控制脚本(或直接通过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(灵活定制效果)
适合需要复杂轮廓效果(比如渐变、模糊)的场景:
- 创建一个新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 } } }
- 创建一个Material,Shader选择
UI/CustomOutline,将其赋值给物品Image的Material属性 - 挂载控制脚本:
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
相关产品推荐
相关产品推荐

