【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP | ShaderGraph | Decal)

article/2025/8/29 2:20:39

本文最终效果
请添加图片描述

文章目录

      • 一、前言
      • 二、环境准备
        • 1、URP环境准备
        • 2、技能范围图案
      • 二、方案一:写Shader实现
        • 1、Shader脚本:UrpDecal.shader
        • 2、材质球
        • 3、创建Cube
        • 4、地面场景
        • 5、添加Renderer Feature: Decal
        • 6、移动DecalCube,与地面交叉
        • 7、运行效果
      • 三、方案二:使用URP Decal Projector
        • 1、添加Renderer Feature: Decal
        • 2、创建Decal Shader Graph
        • 3、材质球
        • 4、空物体挂 URPDecalProjector组件
        • 4、设置组件参数
        • 5、运行效果
      • 四、工程源码
      • 五、完毕

一、前言

嗨,大家好,我是新发。
我平时偶尔会打打Dota2,在Dota里面,技能释放前会有一个地面贴花效果来作为范围的显示,比如深渊领主的这个技能,如下
请添加图片描述
我们可以看到技能范围特效是可以投射到场景地面和物体上(比如树木),这个在Unity中如何去实现呢?本文我以URP渲染管线为例,讲一下这个技能地面贴花效果的制作过程吧~

注:本文我使用的Unity版本为2021.3.1f1c1Universal RP版本为12.1.6

二、环境准备

1、URP环境准备

首先通过PackageManager安装Universal RP,在Project窗口中右键鼠标,点击菜单Create / Rendering / URP Asset (with Universal Renderer)
在这里插入图片描述
此时会创建出两个文件,如下
在这里插入图片描述
打开Project Settings窗口,点击Graphics,把Uinversal Render Pipeline Asset文件拖给Scriptable Render Pipeline Settings,如下
在这里插入图片描述

2、技能范围图案

接着我们去找一张技能范围的图案,我找了一张这样的,
在这里插入图片描述

接下来就是具体的实现过程了。有两个方案,下面我分别给大家讲解一下。

二、方案一:写Shader实现

1、Shader脚本:UrpDecal.shader

我在GitHub上看到有个外国小哥写了个URP渲染管线的贴花Shader
GitHub地址:https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader

在这里插入图片描述
我给他的Shader添加了中文注释,方便大家阅读,如下

// see README here: 
// github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShaderShader "Universal Render Pipeline/NiloCat Extension/Screen Space Decal/Unlit"
{Properties{[Header(Basic)]_MainTex("Texture", 2D) = "white" {}[HDR]_Color("_Color (default = 1,1,1,1)", color) = (1,1,1,1)[Header(Blending)]// BlendMode官方手册:https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html// 混合模式[Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("_SrcBlend (default = SrcAlpha)", Float) = 5 // 5 = SrcAlpha[Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("_DstBlend (default = OneMinusSrcAlpha)", Float) = 10 // 10 = OneMinusSrcAlpha[Header(Alpha remap(extra alpha control))]_AlphaRemap("_AlphaRemap (default = 1,0,0,0) _____alpha will first mul x, then add y    (zw unused)", vector) = (1,0,0,0)[Header(Prevent Side Stretching(Compare projection direction with scene normal and Discard if needed))][Toggle(_ProjectionAngleDiscardEnable)] _ProjectionAngleDiscardEnable("_ProjectionAngleDiscardEnable (default = off)", float) = 0_ProjectionAngleDiscardThreshold("_ProjectionAngleDiscardThreshold (default = 0)", range(-1,1)) = 0[Header(Mul alpha to rgb)][Toggle]_MulAlphaToRGB("_MulAlphaToRGB (default = off)", Float) = 0[Header(Ignore texture wrap mode setting)][Toggle(_FracUVEnable)] _FracUVEnable("_FracUVEnable (default = off)", Float) = 0//====================================== 在常规的用例中,通常可以忽略下面这些设置 =====================================================================[Header(Stencil Masking)]// https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html_StencilRef("_StencilRef", Float) = 0[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("_StencilComp (default = Disable) _____Set to NotEqual if you want to mask by specific _StencilRef value, else set to Disable", Float) = 0 //0 = disable[Header(ZTest)]// https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html// 默认Disable, 因为我们需要确保即使相机进入贴花立方体体积,贴花渲染也正确,尽管默认禁用ZTest将阻止EarlyZ(不利于GPU性能)[Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("_ZTest (default = Disable) _____to improve GPU performance, Set to LessEqual if camera never goes into cube volume, else set to Disable", Float) = 0 //0 = disable[Header(Cull)]// CullMode官方手册: https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html// 默认为Front, 因为我们需要确保即使相机进入贴花立方体体积,贴花渲染也正确[Enum(UnityEngine.Rendering.CullMode)]_Cull("_Cull (default = Front) _____to improve GPU performance, Set to Back if camera never goes into cube volume, else set to Front", Float) = 1 //1 = Front[Header(Unity Fog)][Toggle(_UnityFogEnable)] _UnityFogEnable("_UnityFogEnable (default = on)", Float) = 1[Header(Support Orthographic camera)][Toggle(_SupportOrthographicCamera)] _SupportOrthographicCamera("_SupportOrthographicCamera (default = off)", Float) = 0}SubShader{// 关于tags的内容可以查阅官网手册:https://docs.unity3d.com/Manual/SL-SubShaderTags.html// 为了避免渲染顺序问题, Queue必须 >= 2501, 它位于透明队列中// 在透明队列中,Unity总是从后到前渲染// 2500以下是不透明物体队列,会进行渲染优化,比如被遮住的就剔除掉不进行渲染// 2500以上是透明物体队列,它会根据距离摄像机的距离进行排序// 从最远的开始渲染,到最近的结束// 天空盒被渲染在所有不透明和透明物体之间// "Queue" = "Transparent-499" 即 "Queue" = "2501", 使得它早于所有透明物体进行渲染Tags { "RenderType" = "Overlay" "Queue" = "Transparent-499" "DisableBatching" = "True" }Pass{Stencil{Ref[_StencilRef]Comp[_StencilComp]}Cull[_Cull]ZTest[_ZTest]// 为了支持透明度混合,关闭深度写入ZWrite offBlend[_SrcBlend][_DstBlend]HLSLPROGRAM#pragma vertex vert#pragma fragment frag// 雾效#pragma multi_compile_fog// 为了使用 ddx() & ddy()#pragma target 3.0#pragma shader_feature_local_fragment _ProjectionAngleDiscardEnable#pragma shader_feature_local _UnityFogEnable#pragma shader_feature_local_fragment _FracUVEnable#pragma shader_feature_local_fragment _SupportOrthographicCamera// 所有URP渲染管线的shader都必须引入这个Core.hlsl// 它包含内置shader的变量,比如光照相关的变量,文档:https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html// 同时它也包含很多工具方法#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"struct appdata{// 模型空间下的坐标,OS: Object Spacefloat3 positionOS : POSITION;};struct v2f{// 齐次裁剪空间坐标,CS: Clip Spacefloat4 positionCS : SV_POSITION;// 屏幕坐标float4 screenPos : TEXCOORD0;// xyz分量: 表示viewRayOS, 即模型空间 (Object Space)下的摄像机到顶点的射线// w分量: 拷贝positionVS.z的值,即观察空间 (View Space) 下的顶点坐标的z分量float4 viewRayOS : TEXCOORD1; // rgb分量:表示模型空间下的摄像机坐标,// a分量:表示雾的强度float4 cameraPosOSAndFogFactor : TEXCOORD2;};sampler2D _MainTex;sampler2D _CameraDepthTexture;// 支持SRP BatcherCBUFFER_START(UnityPerMaterial)               float4 _MainTex_ST;float _ProjectionAngleDiscardThreshold;half4 _Color;half2 _AlphaRemap;half _MulAlphaToRGB;CBUFFER_END// 顶点着色器v2f vert(appdata input){v2f o;// VertexPositionInputs包含多个空间坐标系中的位置(world, view, homogeneous clip space, ndc)// Unity编译器将剥离所有未使用的引用 (比如你没有使用view space)// 因此,这种结构具有更大的灵活性,无需额外的成本VertexPositionInputs vertexPositionInput = GetVertexPositionInputs(input.positionOS);// 得到齐次裁剪空间 (clip space) 下的坐标o.positionCS = vertexPositionInput.positionCS;// Unity雾效
#if _UnityFogEnableo.cameraPosOSAndFogFactor.a = ComputeFogFactor(o.positionCS.z);
#elseo.cameraPosOSAndFogFactor.a = 0;
#endif// 准备深度纹理的屏幕空间UVo.screenPos = ComputeScreenPos(o.positionCS);// 观察空间 (view space) 坐标,即在观察空间中摄像机到顶点的射线向量float3 viewRay = vertexPositionInput.positionVS;// [注意,这一步很关键]//=========================================================// viewRay除以z分量必须在片元着色器中执行,不能在顶点着色器中执行! (由于光栅化变化插值的透视校正)// 我们先把viewRay.z存到o.viewRayOS.w中,等到片元着色器阶段在进行处理o.viewRayOS.w = viewRay.z;//=========================================================// unity的相机空间是右手坐标系(z轴负方向指向屏幕),我们希望片段着色器中z射线是正的,所以取反viewRay *= -1;// 观察空间到模型空间的变换矩阵float4x4 ViewToObjectMatrix = mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V);// 观察空间 (view space) 转模型空间 (object space) o.viewRayOS.xyz = mul((float3x3)ViewToObjectMatrix, viewRay);// 模型空间下摄像机的坐标o.cameraPosOSAndFogFactor.xyz = mul(ViewToObjectMatrix, float4(0,0,0,1)).xyz; return o;}half4 frag(v2f i) : SV_Target{// [注意,这一步很关键]//========================================================================// 去齐次i.viewRayOS.xyz /= i.viewRayOS.w;//========================================================================// 深度纹理的UVfloat2 screenSpaceUV = i.screenPos.xy / i.screenPos.w;// 对深度纹理进行采样,得到深度信息float sceneRawDepth = tex2D(_CameraDepthTexture, screenSpaceUV).r;float3 decalSpaceScenePos;// 正交相机
#if _SupportOrthographicCamera// 我们必须支持正交和透视两种投影// unity_OrthoParams://      unity_OrthoParams是内置着色器遍历,存储的信息如下://      x 是正交摄像机的宽度,y 是正交摄像机的高度,z 未使用,w 在摄像机为正交模式时是 1.0,而在摄像机为透视模式时是 0.0。//      更多的内置着色器遍历可查看官方手册: https://docs.unity.cn/cn/2019.4/Manual/SL-UnityShaderVariables.html// (这里要放 UNITY_BRANCH 吗?) 我决定不放,原因看这里: https://forum.unity.com/threads/correct-use-of-unity_branch.476804/if(unity_OrthoParams.w){// 如果是正交摄像机, _CameraDepthTexture在[0,1]内线性存储场景深度#if defined(UNITY_REVERSED_Z)// 如果platform使用反向深度,要使用1-depth// https://docs.unity3d.com/Manual/SL-PlatformDifferences.htmlsceneRawDepth = 1-sceneRawDepth;#endif// 使用简单的lerp插值: lerp(near,far, [0,1] linear depth), 得到观察空间 (view space)的深度信息               float sceneDepthVS = lerp(_ProjectionParams.y, _ProjectionParams.z, sceneRawDepth);// 投影float2 viewRayEndPosVS_xy = float2(unity_OrthoParams.xy * (i.screenPos.xy - 0.5) * 2 /* 裁剪空间 */);  // 构建观察空间坐标float4 vposOrtho = float4(viewRayEndPosVS_xy, -sceneDepthVS, 1);                                            // 观察空间转世界空间float3 wposOrtho = mul(UNITY_MATRIX_I_V, vposOrtho).xyz;                                                 //----------------------------------------------------------------------------// 世界空间转模型空间 (贴花空间)decalSpaceScenePos = mul(GetWorldToObjectMatrix(), float4(wposOrtho, 1)).xyz;}else{
#endif// 如果是透视相机,LinearEyeDepth将为用户处理一切// 记住,我们不能使用LinearEyeDepth处理正交相机!// _ZBufferParams: //      用于线性化 Z 缓冲区值。x 是 (1-远/近),y 是 (远/近),z 是 (x/远),w 是 (y/远)。float sceneDepthVS = LinearEyeDepth(sceneRawDepth, _ZBufferParams);// 在任何空间中,场景深度 = rayStartPos + rayDir * rayLength// 这里所有的数据在 模型空间 (object space) 或 贴花空间 (decal space)// 注意,viewRayOS 不是一个单位向量,所以不要规一化它,它是一个方向向量,视图空间z的长度是1decalSpaceScenePos = i.cameraPosOSAndFogFactor.xyz + i.viewRayOS.xyz * sceneDepthVS;#if _SupportOrthographicCamera}
#endif// unity 的 cube 的顶点坐标范围是 [-0.5, 0.5,],我们把它转到 [0,1] 的范围,用于映射UV// 只有你使用 cube 作为 mesh filter 时才能这么干float2 decalSpaceUV = decalSpaceScenePos.xy + 0.5;// 剔除逻辑//===================================================// 剔除在 cube 以外的像素信息float shouldClip = 0;
#if _ProjectionAngleDiscardEnable// 也丢弃 “场景法向不面对贴花投射器方向” 的像素// 使用 ddx 和 ddy 重建场景法线信息// ddx 就是右边的像素块的值减去左边像素块的值,而ddy就是下面像素块的值减去上面像素块的值。// ddx 和 ddy 的结果就是副切线和切线方向,利用右手定理,叉乘 (cross) 后就是法线,最后执行归一化 (normalize) 得到法线单位向量float3 decalSpaceHardNormal = normalize(cross(ddx(decalSpaceScenePos), ddy(decalSpaceScenePos)));// 判断是否进行剔除// 注:decalSpaceHardNormal.z = dot(decalForwardDir, sceneHardNormalDir)shouldClip = decalSpaceHardNormal.z > _ProjectionAngleDiscardThreshold ? 0 : 1;
#endif// 执行剔除// 如果 ZWrite 关闭,在移动设备上 clip() 函数是足够效率的,因为它不会写入深度缓冲,所以GPU渲染管线不会卡住(经过ARM官方人员确认过)clip(0.5 - abs(decalSpaceScenePos) - shouldClip);//===================================================// 贴花UV计算// _MainTex_ST.xy: 表示uv的tilling// _MainTex_ST.zw: 表示uv的offset     float2 uv = decalSpaceUV.xy * _MainTex_ST.xy + _MainTex_ST.zw;//Texture tiling & offset
#if _FracUVEnable// UV裂缝处理uv = frac(uv);
#endif// 贴花纹理采样half4 col = tex2D(_MainTex, uv);// 与颜色相乘col *= _Color;// 透明通道重新映射col.a = saturate(col.a * _AlphaRemap.x + _AlphaRemap.y);// 插值col.rgb *= lerp(1, col.a, _MulAlphaToRGB);#if _UnityFogEnable// 混合像素颜色与雾色。你可以选择使用MixFogColor来覆盖雾色col.rgb = MixFog(col.rgb, i.cameraPosOSAndFogFactor.a);
#endifreturn col;}ENDHLSL}}
}

首先有一个前提,就是模型必须使用Cube
最核心的一步就是通过深度信息还原世界空间坐标,再转模型空间坐标(也就是贴花空间坐标),计算出贴花UV,对贴花图案采样输出。

其中关于如何通过深度纹理重建世界坐标,大家可以阅读 冯乐乐 写的 《Unity Shader 入门精要》 这本书第13章的13.3.1小结,她讲得很好,建议大家多看书学习

请添加图片描述

我们把上面的Shader保存为UrpDecal.shader,如下
在这里插入图片描述

2、材质球

我们创建一个材质球,重命名为UrpDecal,并使用刚刚的shader,如下
在这里插入图片描述
设置一下材质球参数,如下
在这里插入图片描述

3、创建Cube

创建一个Cube,重命名为DecalCube
在这里插入图片描述
把上面的材质球赋给这个Cube
在这里插入图片描述

4、地面场景

简单搭建一下地面场景,
在这里插入图片描述

5、添加Renderer Feature: Decal

点击Universal Render Pipeline Asset_Renderer,点击Add Renderer Feature,然后点击Decal
在这里插入图片描述
如下
在这里插入图片描述

6、移动DecalCube,与地面交叉

选中DecalCube,调整下角度和缩放,
在这里插入图片描述
然后移动DecalCube,让它与地面交叉,此时我们就可以看到想要的贴花效果了

7、运行效果

运行效果如下
请添加图片描述

三、方案二:使用URP Decal Projector

在默认渲染管线中,我们可以使用Projector来实现贴花效果,比较常见的是假阴影的实现。
URP渲染管线中,我们可以使用URP Decal Projector

1、添加Renderer Feature: Decal

跟上面一样,也得添加Decal

在这里插入图片描述
在这里插入图片描述

2、创建Decal Shader Graph

点击菜单Create / Shader Graph / URP / Decal Shader Graph,如下
在这里插入图片描述
双击打开它ShaderGraph
在这里插入图片描述
连线图如下
在这里插入图片描述

3、材质球

我们创建一个材质球并重命名为DecalShaderGraph,把上面的ShaderGraph赋给它,如下
在这里插入图片描述
设置一下材质球参数
在这里插入图片描述

4、空物体挂 URPDecalProjector组件

创建一个空物体,重命名为URPDecalProjector
在这里插入图片描述
给它挂上URPDecalProjector组件
在这里插入图片描述

4、设置组件参数

设置一下组件参数,如下
在这里插入图片描述

5、运行效果

调整一下URPDecalProjector的角度和缩放,
在这里插入图片描述
移动URPDecalProjector使其与地面交叉,效果如下
请添加图片描述

我们还可以在ShaderGraph中给加个UV旋转,让图案转起来,
在这里插入图片描述
效果如下
请添加图片描述

四、工程源码

以上两种方案放在一起,效果如下,

请添加图片描述

本文工程源码我已上传到GitCode,地址:https://gitcode.net/linxinfa/unityurpdecaldemo
感兴趣的同学可自行下载学习

在这里插入图片描述

五、完毕

好了,夜深了,收工睡觉。
我是林新发,https://blog.csdn.net/linxinfa
一个在小公司默默奋斗的Unity开发者,希望可以帮助更多想学Unity的人,共勉~


http://chatgpt.dhexx.cn/article/nWScrSVg.shtml

相关文章

UE5实现贴地面效果(RT+Decal)

文章目录 1.实现目标2.实现过程2.1 实现原理2.1.1 Render Target2.1.2 Polygon2.2 具体过程3.参考资料1.实现目标 在之前的文章中基于CesiumForUnreal实现了对地形3DTileset的贴地面绘制效果,在这里基于UE自带的RT和Decal实现更加通用的贴地面效果。依旧是加载在线的Cesium W…

Unity Shader-Decal贴花(SelfDecal,Alpha Blend,Mesh Decal,Projector,Deferred Decal)

前言 最近通关了《What Remains of Edith Finch》(艾迪芬奇的记忆),总体来说应该算是一个剧情解密向的游戏,故事表现手法十分出色。 游戏主要是叙述一个神秘的家族遭遇了一系列类似《死神来了》的故事,家族的人离奇死…

Unity Decal 贴花效果测试

贴花效果,就和名字的直接意思类似,把一张图贴到另一个物体上显示,经常被用于表现一些重复出现的图案,比如弹孔,涂鸦,污渍等。效果图: 常规贴花实现 Unity官方提供了一个工程,这个…

UE4 Decal 贴花不在静态光照下绘制

Decal顶点没有烘焙的光照数据,因此无法在含前向管线的阴影下绘制。特效贴花为unlit自发光材质,阴影下表现影响不大。而场景Decal需要计算光照。 1. Decal实现原理 MobileDecalRendering.cpp 通过矩阵变换 得到FrustumComponentToClip,传入…

游戏中的Decal(贴花)

在游戏中,decal是一种非常常见的效果,常用来实现弹孔,血迹,涂鸦等效果。最近研究了下Decal在游戏引擎中的实现方式,大致总结了一下:1.基于面片实现:直接用一个Quat的mesh,加上一张贴图&#xff…

UE4 Decal实现简介

Decal 是游戏中常见的一个东西,经常被用在 显示弹痕,地面叠加花纹等。 Decal 绘制流程 Decal可以认为是,将一个面的画面沿Decal的Box的X轴方向投影到物体表面。 Decal的绘制实际只有一个Box绘制。 RHICmdList.DrawIndexedPrimitive(GetUn…

跳出for循环

跳出for循环有三种方式&#xff1a; 1&#xff1a;continue&#xff1b;跳出当次循环&#xff0c;可继续进行下一个循环&#xff1b; function ceshi(){for(var i 0 ; i < 6 ; i){if(i 3){continue;}console.log(,i);} }ceshi(); 效果图&#xff1a; 2&#xff1a;brea…

跳出forEach循环

我们平时用到的循环有很多种。for, map, while, forEach, for...of, for...in等等&#xff0c;每种循环都有在某一次循环语句中跳出本次循环的方法&#xff0c;但是除了forEach。 有小伙伴说不用不就好了。其实这些循环里边&#xff0c;当属for的效率最高&#xff0c;for...in最…

Java 8 跳出foreach循环,跳出本次循环,继续执行,之前的for each循环如何跳出本次循环,跳出循环,跳出多层for循环。

在Java8之前&#xff0c;最开始使用for i 循环&#xff0c;很老旧&#xff0c; 后来有了高级的for each 循环&#xff0c;然后这个跳出本次循环和跳出所有的for循环&#xff0c;都简单&#xff0c;稍微没见过的就是跳出多层for循环。 然后就是Java8出的foreach循环&#xff0…

js中的for循环如何跳出,js中for循环的两种语法

js几种for循环的几种用法 谷歌人工智能写作项目&#xff1a;小发猫 js&#xff0c;for循环是怎么运行的&#xff1f; typescript有哪些变化。 最普遍的介绍&#xff1a;for循环是JavaScript中最常用的循环&#xff0c;标准for循环代码格式为&#xff1a;for(定义变量初始值;…

if/while/do-while/for循环以及跳出循环break/return/continue

流程控制对任何一门编程语言都是至关重要的&#xff0c;它为我们提供了控制程序步骤的基本手段。常见对主要分为&#xff0c;条件语句、循环语句、跳转语句。 1、if语句 if 语句是一种判断语句。 语法&#xff1a; if(条件){条件成立时执行的代码 } if...else 语句当条件成…

Python中跳出循环的两种方法

我们经常遇到循环在进行到某一个特定的值时&#xff0c;需要跳出循环&#xff0c;或跳过这个值&#xff0c;python中早已为我们准备了这样的参数:break,continue 比如下面的for循环&#xff1a; for i in range(1,10):print(循环了,i,次) 结果显而易见如图&#xff1a; 当我…

js foreach与for循环之return跳出循环

因为自己比较大只&#xff0c;容易忘记&#xff0c;仅此用来记录一下~ 各种循环中使用return或者退出循环的机制。 1、forEach 使用 return 可以退出循环吗&#xff1f;下面代码打印啥&#xff1f; const list [1, 2, 3, 4, 5]list.forEach(e > {if (e 3) {return}consol…

JS中如何跳出.forEach循环

写在前面 提到在一段程序中如果碰到需要终止&#xff0c;结束一个循环&#xff0c;函数或者一段代码&#xff0c;一般会想到以下这几个关键字return、continue、break 简述一下三者的区别&#xff1a; break: 终止整个循环(有内层循环时终止的是内层循环)&#xff0c;退出swi…

JavaScript foreach 方法跳出循环

通常&#xff0c;在 for循环中跳出循环可以用 break或者 continue 来跳出循环。 break&#xff1a;跳出循环&#xff1b; continue&#xff1a;跳过当次循环。 而有时候需要在 foreach 中跳出循环&#xff0c;该怎么做呢&#xff1f; forEach() 方法用于调用数组的每个元素&am…

C++跳出for循环的方式

注&#xff1a;continue只能跳出当前层的循环&#xff0c;无法直接跳出for循环 方法1&#xff1a; for循环中满足条件后使用break语句&#xff1b; #include <iostream> using namespace std;int main(int argc,char *argv[]) {int i;for(i0;i<5;i){if(i2)break;}cou…

Js之跳出for循环,跳出多次for循环详解

一、for循环退出方式 首先我们都知道循环中最常用的就是continue;break; continue:表示跳出本次循环&#xff0c;也就是不执行本次循环continue之后的操作 break:表示跳出当前的循环&#xff0c;针对整个循环体终止后续的遍历&#xff1b; 最简单的应用效果如下&#xff1a; …

layui遮罩

layui遮罩 在执行某个按钮功能时,可能出现网络延迟或是其他原因时 避免重复表单提交,用遮罩.此次请求不响应,执行完毕,就一直遮罩住其他功能 var loading layer.load(1, {shade: [0.8, #393D49], time: 0}); layer.close(loading);写的位置 在请求开启之前遮住 在请求响应之…

遮罩Mask

一、遮罩&#xff1a;遮罩层范围内可看见被遮罩层图层&#xff0c;遮挡层范围可看见笼罩层图形 遮罩层必须至少有两个图层&#xff0c;上面的一个图层为“遮罩层”&#xff0c;下面的称“被遮罩层”&#xff1b;这两个图层中只有相重叠的地方才会被显示。也就是说在遮罩层中有…

基于vue3.0的遮罩

前言 最近在uniapp中要写一个弹窗&#xff0c;弹窗好写&#xff0c;但是遮罩没有接触过。找到了下面这篇文章&#xff0c;推荐仔细阅读一下。在这篇文章的基础下&#xff0c;简单封装了一个遮罩。 推荐文章&#xff1a;论如何用Vue实现一个弹窗-一个简单的组件实现 遮罩 备…