当前位置: 首页 > news >正文

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
}

相关文章:

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

文章目录 前言一、协程是什么二、在Unity中使用协程1、我们在 Start 中测试一下协程的执行顺序2、我们实现一个点击按钮实现角色受击效果 三、协程中的动画过渡1、首先&#xff0c;在协程内实现中毒并且消散的效果2、在 OnGUI 内&#xff0c;给一个新按钮使用刚刚定义的协程 四…...

WordPress禁止显示指定类别的文章

使用wordpress禁止输出指定类别的文章可以给get_posts()函数传个数组参数&#xff0c;如下&#xff1a; <div class"widget" id"diary1"> <h3>随机呈现</h3> <ul> <?php $argsarray( numberposts>16, category>-9,-12, …...

C#里面的泛型(T),泛型类,泛型方法,泛型接口等简单解释

https://blog.csdn.net/dap769815768/article/details/81946506 只是比较简单的解释&#xff0c;在实际使用中&#xff0c;如果遇到需要深入研究的场景&#xff0c;再翻阅相关资料深入研究下。 一、泛型T 这个T在实际使用中很常见&#xff0c;比如List<T>。其实我们还…...

C语言——指针(五)

&#x1f4dd;前言&#xff1a; 上篇文章C语言——指针&#xff08;四&#xff09;更加深入的介绍了不同类型指针的特点&#xff0c;这篇文章主要想记录一下函数与指针的结合运用以及const和assert关于指针的用法&#xff1a; 1&#xff0c;函数与指针 2&#xff0c;const 3&am…...

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑气电联合需求响应的气电综合能源配网系统协调优化运行》

这个标题涉及到一个涉及气体&#xff08;天然气&#xff09;和电力的综合能源配网系统&#xff0c;并且强调了考虑气电联合需求响应的协调优化运行。让我们逐步解读&#xff1a; 气电综合能源配网系统&#xff1a; 这指的是一个结合了气体&#xff08;通常是天然气&#xff09;…...

PostgreSQL 主键和唯一键的区别

主键和唯一键的区别 主键&#xff08;Primary Key&#xff09;&#xff1a; 主键是用于唯一标识表中的每一条记录的键。主键必须是唯一的&#xff0c;不允许为空。一个表只能有一个主键。主键可以由一个或多个字段组成。主键的值在整个表中必须是唯一的&#xff0c;用于确保数据…...

删除表格中的所有绘图

Ctrl G 调出定位的对话框再点击定位条件 按Delete键&#xff0c;删除...

Linux卸载Nginx

1、停止Nginx软件 #/usr/local/nginx/sbin/nginx-sstop 或者kill进程 #ps -ef|grep nginx #kill -9 PID 2、查找根下所有名子包含nginx的文件 #sudofind/-namenginx* 3、执行命令删掉nignx安装的相关文件 # rm -rf /usr/local/sbin/nginx # rm -rf /usr/local/nginx # r…...

Qt之QGraphicsView —— 笔记1:绘制简单图元(附完整源码)

效果 相关类介绍 QGraphicsView类提供了一个小部件,用于显示QGraphicsScene的内容。QGraphicsView在可滚动视口中可视化。QGraphicsView将滚动其视口,以确保该点在视图中居中。 QGraphicsScene类 提供了一个用于管理大量二维图形项的场景。请注意,QGraphicsScene没有自己的视…...

SpringIoC原理

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…...

如何对售后服务的全流程进行精细化的管理?

——“如何对售后服务的全流程进行精细化的管理&#xff1f;” ——“售后又是一个十分复杂的过程&#xff0c;仅靠手工或者电子表格记录这些内容&#xff0c;肯定是低效率、易出错的。最好的办法是借助合适的管理工具进行精细化的过程管理。” 假设你购买了一台新的家用电器…...

SAP UI5 walkthrough step2 Bootstrap

我的理解&#xff0c;这就是一个引导指令 1.我们右键打开命令行--执行 ui5 use OpenUI5 2.执行命令&#xff1a;ui5 add sap.ui.core sap.m themelib_sap_horizon 执行完之后&#xff0c;会更新 yaml 文件 3.修改index.html <!DOCTYPE html> <html> <head&…...

Gemini:定义下一代人工智能的里程碑

Google最近发布号称世界最强的大模型"Gemini"&#xff0c;其强大多模态LLM&#xff0c;标志着AI技术的一个新时代。 Gemini作为"迄今为止最强大的AI模型"之一&#xff0c;其独特之处在于它融合了多种模式的处理能力&#xff0c;能够同时理解和生成文本、代…...

一些系统日常运维命令和语句

一、前言 记录一些日常系统运维的命令和语句 二、linux命令与语句 1、linux查看各目录使用磁盘情况 du -h /home home为目录 du -h /home 2.查看内存使用情况 free -h 3、查看进程和CPU使用情况 top top 三、数据库语句 1、统计mysql数据库表数量 SELECT COUNT(*) A…...

微信小程序uni.chooseImage()无效解决方案

Bug场景&#xff1a; 微信小程序在上传图片时可以通过 uni.chooseImage()方案进行上传&#xff0c;这里不再赘述具体参数。一直项目都可以正常使用&#xff0c;突然有一天发现无法使用该方法&#xff0c;于是查了一下&#xff0c;发现是用户隐私协议问题。故记录一下解决方案。…...

Rust深入浅出:编程的深邃大海中的奇妙冒险

第一章&#xff1a;前言 欢迎来到Rust的深邃大海&#xff0c;这里是一片充满挑战和奇妙冒险的领域。在这篇文章中&#xff0c;我们将深入浅出&#xff0c;探索Rust编程语言的深层次特性&#xff0c;并通过诙谐而深刻的方式&#xff0c;带你走进这个奇妙的编程世界。 第二章&a…...

go-zero开发入门-API网关开发示例

开发一个 API 网关&#xff0c;代理 https://blog.csdn.net/Aquester/article/details/134856271 中的 RPC 服务。 网关完整源代码 // file: main.go package mainimport ("flag""fmt""github.com/zeromicro/go-zero/core/conf""github.c…...

TCP一对一通信

package 二十一章; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;/*** Socket服务端**/ public class SocketServer {public static void main(String[] args) {ServerSocket ss null;Socket s null;try {// 创建监听…...

laravel DB::connection 报错 Database connection [{$name}] not configured

DB::connection(mysql2);//不是连接数据库名...

快捷支付是什么?快捷支付好申请吗?

快捷支付是指用户在购买商品时&#xff0c;不需要打开网上银行&#xff0c;只需提供银行卡号码、户名、手机号码等信息&#xff0c;银行验证手机号码的正确性&#xff0c;输入动态密码即可完成支付&#xff0c;无需打开网上银行。持卡人将银行卡绑定到第三方支付应用程序&#…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...