Unity中C#使用协程控制Shader材质变化

文章目录

  • 前言
  • 一、协程是什么
  • 二、在Unity中使用协程
    • 1、我们在 Start 中测试一下协程的执行顺序
    • 2、我们实现一个点击按钮实现角色受击效果
  • 三、协程中的动画过渡
    • 1、首先,在协程内实现中毒并且消散的效果
    • 2、在 OnGUI 内,给一个新按钮使用刚刚定义的协程
  • 四、C#控制Shader变体开关 开启死亡消融效果变体
    • 1、C# 怎么开启和关闭 Shader变体
    • 2、在协程中开启死亡消融变体及实现效果
    • 3、在OnGUI中,定义一个新按钮调用死亡协程
  • 五、测试代码
    • Shader:
    • C#脚本:


前言

在上一篇文章实现了C#脚本简单修改Shader材质的效果后,我们使用按钮点击结合协程来实现一下游戏中角色常见的效果:受击、中毒、消融效果

我们继续使用上一篇的 Shader 和 C# 脚本来继续测试

  • Unity中C#如何访问并修改Shader材质

一、协程是什么

Unity中的协程可以理解为 C# 中多线程的作用,在主线程运行的同时,把一些不确定时间的步骤并行操作,不影响主线程。但是协程 和 C#的多线程不一样。

协程模拟了多线程的作用,但是不是真正意义上的多线程

在这里插入图片描述


二、在Unity中使用协程

1、我们在 Start 中测试一下协程的执行顺序

  • 我们定义一个协程在控制台 等待 2 秒 输出 2

IEnumerator Wait()
{
yield return new WaitForSeconds(2);
Debug.Log(2);
}

  • 在 Start 按如下顺序输出

Debug.Log(1);
//这里使用协程输出一个 2
StartCoroutine(Wait());
Debug.Log(3);

  • 我们运行一下看看输出的顺序

请添加图片描述

控制台先输出了1、3 间隔了两秒输出了 2

2、我们实现一个点击按钮实现角色受击效果

  • 我们使用协程实现一个改变颜色后 间隔 0.15 秒恢复原本颜色的效果

IEnumerator WaitBehit()
{
skr.sharedMaterial.SetColor("_Color", Color.red);
yield return new WaitForSeconds(0.15f);
skr.sharedMaterial.SetColor("_Color",Color.white);
}

  • 在 GUI 绘制时,给按钮点击后加上 角色受击后的协程

void OnGUI()
{
if (GUI.Button(new Rect(10, 10, 150, 50), “被击”))
{
StartCoroutine(WaitBehit());
}
}

我们来测试看一下效果:

请添加图片描述


三、协程中的动画过渡

主要实现一个角色中毒后中毒消散的效果

1、首先,在协程内实现中毒并且消散的效果

  • 在协程内定义一个计数器,作为颜色过度的控制器
  • 在协程内使用死循环,实现计数器的累加
  • 在协程内使用 Color.Lerp(A,B,x);实现颜色过度效果
  • 把该过度颜色赋值给我们的小狐狸
IEnumerator WaitMethysis(){float _time = 0;Color color;while (true){_time += Time.deltaTime;yield return new WaitForEndOfFrame();color = Color.Lerp(Color.green, Color.white,_time / 2);skr.sharedMaterial.SetColor("_Color",color );if (_time >= 2){yield break;}}}

2、在 OnGUI 内,给一个新按钮使用刚刚定义的协程

if (GUI.Button(new Rect(10,70,150,50),“中毒”))
{
StartCoroutine(WaitMethysis());
}

我们来测试一下看看效果:
请添加图片描述

在开启一个协程时,记着停止协程

//关闭指定协程
StopCoroutine(string);
//关闭所有协程
StopAllCoroutines();


四、C#控制Shader变体开关 开启死亡消融效果变体

1、C# 怎么开启和关闭 Shader变体

  • 开启关键字

material.EnableKeyword(string);

  • 关闭关键字

material.DisableKeyword(string);

  • 这里的关键字不是Shader属性面板的属性名,是在Shader的Pass中的变体名

2、在协程中开启死亡消融变体及实现效果

  • 先在协程中定义一个_time 计数器
  • 开启死亡消融变体
  • 使用 while 给计数器累加,作为消融的控制值
  • 修改_Clip 属性值实现消融
IEnumerator WaitDead(float time){float _time = 0;while (true){_time += Time.deltaTime;yield return new WaitForEndOfFrame();skr.sharedMaterial.EnableKeyword("_DISSOLVEENABLE_ON");skr.sharedMaterial.SetFloat("_Clip",_time / time);if (_time >=time){skr.sharedMaterial.SetFloat("_Clip",0);skr.sharedMaterial.DisableKeyword("_DISSOLVEENABLE_ON");yield break;}}}

3、在OnGUI中,定义一个新按钮调用死亡协程

if (GUI.Button(new Rect(10,130,150,50),“死亡消融”))
{
StopAllCoroutines();
StartCoroutine(WaitDead(2));
}

我们来测试一下看看效果:
请添加图片描述


五、测试代码

Shader:

//角色消融效果
Shader "MyShader/P2_5_6"
{Properties{//使用这个标签,可以使外部暴露属性,有标题[Header(Base)][NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}_Color("Color",Color) = (1,1,1,1)_Clip("Clip",Range(0,1)) = 0//使用这个标签可以 在两行暴露属性之间加 间隙[Space(10)][Header(Dissolve)][Toggle]_DissolveEnable("Dissolve Enable",int) = 0_DissolveTex("DissolveTex",2D) = "black"{}[NoScaleOffset]_RampTex("RampTex(RGB)",2D) = "black" {}}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag//定义消融变体开关#pragma shader_feature _ _DISSOLVEENABLE_ON #include "UnityCG.cginc"sampler2D _MainTex;fixed4 _Color;float _Clip;sampler2D _DissolveTex; //这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _STfloat4 _DissolveTex_ST;//因为 在使用渐变纹理时,只使用了 渐变纹理的 u 坐标,所以把  sampler2D 换位 samplersampler _RampTex;struct appdata{float4 vertex : POSITION;float4 uv : TEXCOORD0;};struct v2f{float4 uv : TEXCOORD0;float4 pos : SV_POSITION;};v2f vert (appdata v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);//为了减少传入的值 ,所以就不创建新变量来存储,而是把 uv 改为  四维向量 来用//使用 o.uv 的 xy 来存放 原人物贴图//使用 o.uv 的 zw 来存放 噪波贴图缩放 和 偏移 后的值o.uv.xy = v.uv.xy;//o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;o.uv.zw = TRANSFORM_TEX(v.uv,_DissolveTex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv.xy);col *= _Color;#if _DISSOLVEENABLE_ON//外部获取的 纹理 ,使用前都需要采样fixed4 dissolveTex = tex2D(_DissolveTex,i.uv.zw);//片段的取舍clip(dissolveTex.r -  _Clip);//进行归一化fixed4 dissolveValue = saturate((dissolveTex.r - _Clip) / (_Clip + 0.1 - _Clip));fixed4 rampTex = tex1D(_RampTex,dissolveValue.r);col += rampTex;#endifreturn col;}ENDCG}}
}

C#脚本:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;//C#如何访问并且修改材质属性
public class P2_5_6 : MonoBehaviour
{#region [成员变量]public GameObject Fox;private SkinnedMeshRenderer skr;#endregion#region [Start/Update]void Start(){skr = Fox.GetComponentInChildren<SkinnedMeshRenderer>();}void Update(){}#endregion#region [GUI]void OnGUI(){if (GUI.Button(new Rect(10, 10, 150, 50), "被击")){StopAllCoroutines();StartCoroutine(WaitBehit());}if (GUI.Button(new Rect(10,70,150,50),"中毒")){StopAllCoroutines();StartCoroutine(WaitMethysis(2));}if (GUI.Button(new Rect(10,130,150,50),"死亡消融")){StopAllCoroutines();StartCoroutine(WaitDead(2));}}#endregion#region [受击]IEnumerator WaitBehit(){skr.sharedMaterial.SetColor("_Color", Color.red);yield return new WaitForSeconds(0.15f);skr.sharedMaterial.SetColor("_Color",Color.white);}#endregion#region [中毒]IEnumerator WaitMethysis(float time){float _time = 0;Color color;while (true){_time += Time.deltaTime;yield return new WaitForEndOfFrame();color = Color.Lerp(Color.green, Color.white,_time / time);skr.sharedMaterial.SetColor("_Color",color );if (_time >= time){yield break;}}}#endregion#region [死亡消融]IEnumerator WaitDead(float time){float _time = 0;while (true){_time += Time.deltaTime;yield return new WaitForEndOfFrame();skr.sharedMaterial.EnableKeyword("_DISSOLVEENABLE_ON");skr.sharedMaterial.SetFloat("_Clip",_time / time);if (_time >=time){skr.sharedMaterial.SetFloat("_Clip",0);skr.sharedMaterial.DisableKeyword("_DISSOLVEENABLE_ON");yield break;}}}#endregion
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/197732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32通用定时器

本文实践&#xff1a;实现通过TIM14_CH1输出PWM&#xff0c;外部显示为呼吸灯。 通用定时器简介 拥有TIM2~TIM5、TIM9~TIM14 一共10个定时器&#xff0c;具有4路独立通道&#xff0c;可用于输入捕获、输出比 较&#xff0c;同时包含了基本定时去的所有功能。 通用定时器的结…

深入分析爬虫中time.sleep和Request的并发影响

背景介绍 在编写Python爬虫程序时&#xff0c;我们经常会遇到需要控制爬取速度以及处理并发请求的情况。本文将深入探讨Python爬虫中使用time.sleep()和请求对象时可能出现的并发影响&#xff0c;并提供解决方案。 time.sleep()介绍 首先&#xff0c;让我们来了解一下time.s…

前端——html拖拽原理

文章目录 ⭐前言⭐draggable属性&#x1f496; api&#x1f496; 单向拖动示例&#x1f496; 双向拖动示例 ⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 前端——html拖拽原理。 vue3系列相关文章&#xff1a; vue3 fastapi 实现选择目录所有文…

根据已有安装的cuda配置合适的pytorch环境

目前网络上根据电脑配置安装合适的深度学习环境的帖子已经很多了&#xff0c;但是现实中会出现很久之前已经安装了对应的cuda&#xff0c;但是现在忘记了当时安装的是什么版本。本文针对这一问题展开攻略。 1 cuda安装版本查询 我们在查询自己应该安装什么版本的cuda时&#…

【模电】直流通路与交流通路

直流通路与交流通路 通常&#xff0c;在放大电路中&#xff0c;直流电源的作用和交流信号的作用总是共存的&#xff0c;即静态电流、电压和动态电流、电压总是共存的。但是由于电容、电感等电抗元件的存在&#xff0c;直流量所流经的通路与交流信号所流经的通路不完全相同。因此…

【设计模式】职责链模式设计在线文档帮助系统

职责链模式设计在线文档帮助系统 任务三&#xff1a;使用职责链模式设计在线文档帮助系统 某公司欲开发一个软件系统的在线文档帮助系统&#xff0c;用户可以在任何一个查询环境中输入查询关键字&#xff0c;如果当前查询环境下没有相关内容&#xff0c;则系统会将查询按照一定…

获取Spring容器Bean工具类

获取Spring容器Bean工具类 1、创建SpringUtils工具类2、注册 SpringUtils工具类3、如果打包的是War方式&#xff0c;可能上面两个注册工具类的方法都没用 1、创建SpringUtils工具类 public class SpringUtils implements ApplicationContextAware {private static Application…

【鸿蒙应用开发】开发环境搭建及IDE安装使用

1.下载安装包 安装包下载地址&#xff1a; 点击跳转下载页面 可以根据自己的操作系统选择对应版本下载。 本文以Windows安装为例&#xff0c;Mac安装方式相同 2. 安装 下载好后&#xff0c;打开安装包&#xff0c;进入安装界面&#xff1a; 点击Next&#xff0c;进入安…

【Vue】使用 Vue CLI 脚手架创建 Vue 项目(使用命令行创建)

前言 在开始使用Vue进行开发之前&#xff0c;我们需要先创建一个Vue项目。Vue CLI&#xff08;Command Line Interface&#xff09;是一个官方提供的脚手架工具&#xff0c;可以帮助我们快速创建Vue项目。 步骤 打开终端或命令行工具&#xff0c;运行以下命令&#xff1a; vu…

蔚碳科技联合中投会发布国内首个 ESG 尽职调查服务标准

11 月 26 日&#xff0c;蔚碳&#xff08;上海&#xff09;科技有限公司&#xff08;以下简称“蔚碳科技”&#xff09;受邀出席由深圳市人民政府主办&#xff0c;深圳市发展和改革委员会、深圳市生态环境局、龙岗区人民政府共同承办的 2023 碳达峰碳中和论坛暨深圳国际低碳城论…

手机升级到iOS15.8后无法在xcode(14.2)上真机调试

之前手机是iOS14.2的系统,在xcode上进行真机测试运行良好&#xff0c;因为想要使用Xcode的Instruments功能&#xff0c;今天将系统更新到了iOS15.8 &#xff0c;结果崩了 说是Xcode和手机系统不兼容不能进行真机测试。在网上查不好些方法&#xff0c;靠谱的就是下载相关版本的…

05、pytest断言确定的异常

官方用例 # content of test_sysexit.py import pytestdef f():raise SystemExit(1)def test_mytest():with pytest.raises(SystemExit):f()解读与实操 ​ 标准python raise函数可产生异常。pytest.raises可以断言某个异常会发现。异常发生了&#xff0c;用例执行成功&#x…

常见的几种计算机编码格式

前言&#xff1a; 计算机编码是指将字符、数字和符号等信息转换为计算机可识别的二进制数的过程&#xff0c;正因如此&#xff0c;计算机才能识别中英文等各类字符。计算机中有多种编码格式用于表示和存储文本、字符和数据&#xff0c;实际走到最后都是二进制&#xff0c;本质一…

CefSharp 获取POST(AJAX)、GET消息返回值(request)

CefSharp作为专门为爬虫工具开发的库比Selenium这种开发目的是页面测试工具然后用来做爬虫的工具要贴心得多。我们操作网页的时候发送或者做了某个动作提交表单之后需要知道我们的动作或者提交是否成功&#xff0c;因为有的页面会因为网络延迟问题提交失败&#xff0c;需要准确…

VIVADO-FFT IP核学习记录

根据用户手册使用IP核 ① 找到user guide / product guide 并打开 ② 找到Customizing and Generating the Core(不同手册可能题目不一样)&#xff0c;查看IP核的创建过程中各个参数的意义和设置方法。 ③ 找到port description &#xff0c;查看接口注释 根据网络教程使用…

微信小程序调用相机拍摄或手机相册

wx.chooseMedia(Object object) 功能描述 拍摄或从手机相册中选择图片或视频。

Facebook推广工具功能科普!

随着社交媒体的普及&#xff0c;Facebook已经成为全球使用最广泛的社交平台之一&#xff0c;对于广大营销人员来说&#xff0c;利用Facebook推广工具进行营销已经成为不可或缺的一部分。 那么&#xff0c;这些推广工具到底有哪些功能呢?本文将为您揭秘Facebook推广工具的强大…

SaToken利用Redis做持久化

官网解释 官网解释 教程 引入依赖 <!-- 提供Redis连接池 --> <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId> </dependency><!-- Sa-Token 整合 Redis &#xff08;使用 jdk 默认序…

leecode | 从二叉搜索树到更大和树

官方的题目解释永远晦涩难懂 这就是最大的拦路虎 简单介绍&#xff0c;将二叉搜索树&#xff0c;转换成“更大和树”&#xff0c;“最大的和树”&#xff0c;就是更新节点val&#xff0c;二叉树中所有大于等于该节点的的val 总和&#xff0c;包括本身 #对着图看&#xff0c;会更…

pythonGUi不能立即刷新

今天遇到一个UI界面问题&#xff1a; 在修改控件的背景颜色或其他样式后&#xff0c;UI 没有立即更新&#xff0c;而需要晃动窗口或触发一些事件才能看到变化&#xff0c;可能是由于界面的刷新机制问题。这种情况下&#xff0c;我尝试使用 Refresh 方法来强制刷新控件。 在你的…