通过C#脚本更改材质球的参数

news2025/3/20 17:06:16
        // 设置贴图
        Texture mTexture = Resources.Load("myTexture", typeof(Texture )) as Texture;
        material.SetTexture("_MainTex", mTexture );
        // 设置整数
        material.SetInt("_Int", 1);
        // 设置浮点
        material.SetFloat("_Float", 0.1f);
        // 设置颜色 rgba
        material.SetColor("_Color", Color.white);
        // 设置向量 xyzw
        material.SetVector("_Vector", new Vector4());
        // shader的正常接口是没有bool类型的。但通过#pragma multi_compile __ UNITY_name可以实现
        // 设置shader的UNITY_name为true
        material.EnableKeyword("UNITY_name");
        // 设置shader的UNITY_name为true
        material.DisableKeyword("UNITY_name");
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/lengyoumo/article/details/105167565

一、协程的概念

什么是协程? - 知乎 (zhihu.com)

我们都知道多线程,当需要同时执行多项任务的时候,就会采用多线程并发执行。拿手机支付举例子,当收到付款信息的时候,需要查询数据库来判断余额是否充足,然后再进行付款。

假设最开始我们只有可怜的10个用户,收到10条付款消息之后,我们开启启动10个线程去查询数据库,由于用户量很少,结果马上就返回了。

然而当用户开始爆炸增长,这时候有10000人同时在线付款,你打算启动10000个线程来处理任务。等等,问题来了,因为每个线程至少会占用4M的内存空间,10000个线程会消耗39G的内存,而服务器的内存配置只有区区8G,这时候你有2种选择,一是选择增加服务器,二是选择提高代码效率。那么是否有方法能够提高效率呢?

我们知道操作系统在线程等待IO的时候,会阻塞当前线程,切换到其它线程,这样在当前线程等待IO的过程中,其它线程可以继续执行。当系统线程较少的时候没有什么问题,但是当线程数量非常多的时候,却产生了问题。一是系统线程会占用非常多的内存空间,二是过多的线程切换会占用大量的系统时间。

协程刚好可以解决上述2个问题。协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。协程并没有增加线程数量,只是在线程的基础之上通过分时复用的方式运行多个协程,而且协程的切换在用户态完成,切换的代价比线程从用户态到内核态的代价小很多。

回到上面的问题,我们只需要启动100个线程,每个线程上运行100个协程,这样不仅减少了线程切换开销,而且还能够同时处理10000个读取数据库的任务,很好的解决了上述任务。


什么是协程?

协程,从字面意义上理解就是协助程序的意思,我们在主任务进行的同时,需要一些分支任务配合工作来达到最终的效果

稍微形象的解释一下,想象一下,在进行主任务的过程中我们需要一个对资源消耗极大的操作时候,如果在一帧中实现这样的操作,游戏就会变得十分卡顿,这个时候,我们就可以通过协程,在一定帧内完成该工作的处理,同时不影响主任务的进行

首先需要了解协程不是线程,协程依旧是在主线程中进行

然后要知道协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义一个迭代方法,注意使用的是IEnumerator


二、协程的使用

void Start ( )

{

  //第一种,无参可以直接使用方法名“字符串”来启用协程

   StartCoroutine("wjy");

  //第二种,无参可以调用方法来启用协程

  StartCoroutine(wjy());

  //有参

  StartCoroutine(jwy(1));

  //第三种,有参

  StartCoroutine("yjw",1,2);

}

IEnumerator  wjy()

{
    yield return null;
}

IEnumerator  jwy(int b)

{
    yield return null;
}

IEnumerator yjw(int i,int r)

{
    yield return null;
}

IEnumerator需要和yield配合使用

  • yield return null; 暂停协程等待下一帧继续执行

  • yield return 0或其他数字; 暂停协程等待下一帧继续执行

  • yield return new WairForSeconds(时间); 等待规定时间后继续执行

  • yield break; 跳出协程对应方法,其后面的代码不会被执行

  • yield return new WaitForEndOfFrame():等到所有相机画面被渲染完毕后更新

yield 位于 Update() 和 LateUpdate() 之间


三、使用 yield return new WaitForSeconds() 来控制材质球的变化

通过脚本和材质Shader的配合,给角色添加一个被击的效果

当点击被击Hit按钮时,角色的材质有原来的颜色变为红色,等待数秒后变回原来的颜色

可以使用协程yield return new WaitForSeconds()来实现

首先先创建一个空物体,命名为Scripts,用来挂载脚本。

然后创建脚本并命名为material02,在脚本中创建一个变量,用来存放角色。

public GameObject Monster;

将用于变化材质的对象赋予该变量Monster。

随后在场景中创建一个按钮Button

在脚本中添加一个方法OnHit()(角色被击的方法),将之前挂载了脚本的空对象拖到按钮的On Click()中

然后在方法Function中选择该脚本中的相关方法

创建好被击的方法后

再创建协程,然后在被击的方法中调用该协程,完成角色被击的效果

public void OnHit()

{

        StopAllCoroutines();

        StartCououtine(WaitBeHit());

}

IEnumerator WaitBeHit()

{

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color",Color.red);

        // 挂起,等待0.2s后继续执行下面的语句
        yield return new  WaitForSeconds(0.2f);

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color",Color.balck);

}

四、利用协程 yield return null 将循环中的内容分帧执行,然后实现角色被毒的效果 

首先也是需要创建被毒的按钮,将脚本中的被毒的方法OnDie()拖动到该按钮上

然后在协程中利用循环和Lerp()函数、yield return null 实现角色从绿色到黑色的渐变

yield return null ;   //表示暂停协程等待到下一帧后继续执行

该协程中_Time初始值为0,在循环中_Time每增加一个deltaTime,使用_Time/time的值来采样Lerp()函数中的值(time为自设值),当遇到yield return null时挂起循环,然后等待下一帧继续执行循环中的下一个,直到不满足循环的条件后跳出循环

所以这样就会实现角色在time时间段内,颜色由绿色渐变为源颜色

 public void OnDU()
 {
     Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material01;

     Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.DisableKeyword("_ClipEnable");

     Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip", -0.1f);

     //在一个协程开始前,停止所有协程
     StopAllCoroutines();

     //怪物中毒的协程(在多帧下完成一个函数,常用于变化动态效果)
     StartCoroutine(WaitDu(2f));
 }  

     //被毒协程
    IEnumerator WaitDu(float time)
    {
        float _Time = 0;
        while(_Time<time)
        {
            _Time += Time.deltaTime;
            //yield return new WaitForEndOfFrame();
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.Lerp(Color.green, Color.black, _Time / time));
            //yield return new WaitForEndOfFrame();
            yield return null;
        }
        yield break;
    }

 五、利用循环和协程 yield return null 以及 SetFloat实现角色逐渐熔解的效果

public void OnDie()
{
    Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material01;

    StopAllCoroutines();

    StartCoroutine(WaitDie(2f));
}

    IEnumerator WaitDie(float time)
    {
        float _Time=0;

        while(_Time<time)
        {
            _Time += Time.deltaTime;

            
            //设置颜色参数
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.black);
            //SetFloat用于设置Float类型的参数 例如_Clip

            //使变体有效,引号中需要写宏的名称
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.EnableKeyword("_CLIPENABLE_ON");

            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip",_Time/time);

            //挂起等待这一帧执行完后在继续执行该循环
            yield return null;
        }
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.black);
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip", -0.1f);
        yield break;
    }
}

当shader中有开关效果时,需要使用EnableKeyWord来打开变体开关

Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMateral.EnableKeyword("_CLIPENABLE_ON")

// _CLIPENABLE_ON为变体宏的名称


六、切换材质球


七、Material和sharedMaterial的区别

Material:

sharedMaterial:


【太妃糖耶】视频加载中,速速查收惊喜!

脚本:

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class material02 : MonoBehaviour
{
    public GameObject Monster;
    // Start is called before the first frame update

    public Material material;

    public Material material01;
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    public void Onclick()
    {
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material01;
        //修改材质球的颜色属性
        //Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color",Color.red);

        //在一个协程开始前,停止所有协程
        StopAllCoroutines();

        //怪物被击协程(等待)
        StartCoroutine(WaitBehit());
    }

    public void OnDU()
    {
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material01;

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.DisableKeyword("_ClipEnable");

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip", -0.1f);

        //在一个协程开始前,停止所有协程
        StopAllCoroutines();

        //怪物中毒的协程(在多帧下完成一个函数,常用于变化动态效果)
        StartCoroutine(WaitDu(2f));
    }

    public void OnDie()
    {
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material01;

        StopAllCoroutines();

        StartCoroutine(WaitDie(2f));
    }

    public void SwitchMaterial()
    {
        StopAllCoroutines();

            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = material;
            
    }

    //定义关于被击协程
    IEnumerator WaitBehit()
    {
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.EnableKeyword("_ClipEnable");

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip", -0.1f);

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.red);

        yield return new WaitForSeconds(0.2f);

        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.black);
    }

    //被毒协程
    IEnumerator WaitDu(float time)
    {
        float _Time = 0;
        while(_Time<time)
        {
            _Time += Time.deltaTime;
            //yield return new WaitForEndOfFrame();
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.Lerp(Color.green, Color.black, _Time / time));
            //yield return new WaitForEndOfFrame();
            yield return null;
        }
        yield break;
    }

    IEnumerator WaitDie(float time)
    {
        float _Time=0;

        while(_Time<time)
        {
            _Time += Time.deltaTime;

            
            //设置颜色参数
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.black);
            //SetFloat用于设置Float类型的参数 例如_Clip

            //使变体有效,引号中需要写宏的名称
            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.EnableKeyword("_CLIPENABLE_ON");

            Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip",_Time/time);

            //挂起等待这一帧执行完后在继续执行该循环
            yield return null;
        }
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetColor("_Color", Color.black);
        Monster.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial.SetFloat("_Clip", -0.1f);
        yield break;
    }
}

角色Shader:

Shader"unity/practice04"
{
	Properties
	{
		_Color("Color",Color)=(0,0,0,0)
		_MainTex("MainTex",2D)="white"{}
		_DissolveTex("DissolveTex",2D)="white"{}
		_RampTex("RampTex",2D)="black"{}

		[Toggle]_ClipEnable("ClipEnable",int)=0
		_Clip("Clip",Range(-0.1,1))=0
	 }

	SubShader
	{
		Offset 1,1
		// UsePass"unity/X_Ray02/XRayPass"
		Pass
		{
			CGPROGRAM

			#pragma vertex vert;
			#pragma fragment frag;

			//在使用multi_compile变体时,前面须添加一个空变体才有效
			#pragma multi_compile _ _CLIPENABLE_ON

			#include "UnityCG.cginc"

			//声明变量
			sampler2D _MainTex;
			sampler2D _DissolveTex;
			float4 _DissolveTex_ST;
			sampler   _RampTex;         //优化  RampTex贴图只用到了一个方向的数值 
			fixed _Clip;
			float4 _Color;

			struct appdate
			{
				float4 vertex:POSITION;
				float4 uv:TEXCOORD;
			 };

			struct v2f
			{
				float4 pos:SV_POSITION;
				float4 uv:TEXCOORD;
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);    //转换为齐次裁剪空间坐标

				//使第二张纹理贴图uv与主贴图的uv分开,方便调节DissolveTex贴图的平铺与偏移而不影响主贴图

				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;
		     }

			float4 frag(v2f i):SV_TARGET
			{

				float4 c;
				float4 mainTex=tex2D(_MainTex,i.uv.xy);
				c=mainTex;
				c+=_Color;
				float4 dissolveTex=tex2D(_DissolveTex,i.uv.zw);
				

				//smoothstep 需要优化
				//float4 rampTex=tex1D(_RampTex,smoothstep(_Clip,_Clip+0.1,dissolveTex.r)); 

				#if _CLIPENABLE_ON
				fixed ramp=saturate((dissolveTex.r-_Clip)/(_Clip+0.1-_Clip));
				clip(dissolveTex.r-_Clip);
				float4 rampTex =tex2D(_RampTex,ramp);
				c+=rampTex;
				#endif

				return c;
			 }

			ENDCG
		 }
	 }
 }

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

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

相关文章

FPGA管脚约束

目录 前言 一、IO约束 二、延迟约束 前言 IO约束包括管脚约束和延迟约束。 一、IO约束 对管脚进行约束&#xff0c;对应的约束语句&#xff1a; set_property -dict {PACKAGE_PIN AJ16 IOSTANDARD LVCMOS18} [get_ports "led[0]" ] 上面是单端的管脚&…

实现前端.ttf字体包的压缩

前言 平常字体包都有1M的大小&#xff0c;所以网络请求耗时会比较长&#xff0c;所以对字体包的压缩也是前端优化的一个点。但是前端如果想要特点字符打包成字体包&#xff0c;网上查阅资料后&#xff0c;都是把前端代码里面的字符获取&#xff0c;但是对于动态的内容&#xf…

uni-app集成保利威直播、点播SDK经验FQ(二)|小程序直播/APP直播开发适用

通过uniapp集成保利威直播、点播SDK来开发小程序/APP的视频直播能力&#xff0c;在实际开发中可能会遇到的疑问和解决方案&#xff0c;下篇。更多疑问请咨询19924784795。 1.ios不能后台挂起uniapp插件 ios端使用后台音频播放和画中画功能&#xff0c;没有在 manifest.json 进…

Sensodrive机器人力控关节模组SensoJoint在海洋垃圾清理机器人中的拓展应用

海洋污染已成为全球性的环境挑战&#xff0c;其中海底垃圾的清理尤为困难。据研究&#xff0c;海洋中约有2600万至6600万吨垃圾&#xff0c;超过90%沉积在海底。传统上&#xff0c;潜水员收集海底垃圾不仅成本高昂&#xff0c;而且充满风险。为解决这一问题&#xff0c;欧盟资助…

Git的基本指令

一、回滚 1.git init 在项目文件夹中打开bash生成一个.git的子目录&#xff0c;产生一个仓库 2.git status 查看当前目录下的所有文件的状态 3.git add . 将该目录下的所有文件提交到暂存区 4.git add 文件名 将该目录下的指定文件提交到暂存区 5.git commit -m 备注信…

Vitis 2024.1 无法正常编译custom ip的bug(因为Makefile里的wildcard)

现象&#xff1a;如果在vivado中&#xff0c;添加了自己的custom IP&#xff0c;比如AXI4 IP&#xff0c;那么在Vitis&#xff08;2024.1&#xff09;编译导出的原本的.xsa的时候&#xff0c;会构建build失败。报错代码是&#xff1a; "Compiling blank_test_ip..."…

Elasticsearch 在航空行业:数据管理的游戏规则改变者

作者&#xff1a;来自 Elastic Adam La Roche 数字化客户体验不再是奢侈品&#xff0c;而是欧洲航空公司必不可少的需求。它推动了客户满意度&#xff0c;提升了运营效率&#xff0c;并创造了可持续的竞争优势。随着行业的不断发展&#xff0c;优先投资前沿数字技术和平台的航空…

DeepSeek 模型的成本效益深度解析:低成本、高性能的AI新选择

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

利用knn算法实现手写数字分类

利用knn算法实现手写数字分类 1.作者介绍2.KNN算法2.1KNN&#xff08;K-Nearest Neighbors&#xff09;算法核心思想2.2KNN算法的工作流程2.3优缺点2.4 KNN算法图示介绍 3.实验过程3.1安装所需库3.2 MNIST数据集3.3 导入手写数字图像进行分类3.4 完整代码3.5 实验结果 1.作者介…

基于springboot+vue的调查问卷平台

一、系统架构 前端&#xff1a;vue | element-ui | echarts 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven 二、代码及数据 三、功能介绍 01. 注册 02. 登录 03. web端-问卷中心 04. web端-文章中心 05. 管理端-…

美摄接入DeepSeek等大模型,用多模态融合重构视频创作新边界!

今年以来&#xff0c;DeepSeek凭借其强大的深度推理分析能力&#xff0c;在AI领域掀起新的热潮。美摄科技快速响应市场需求&#xff0c;迅速接入以DeepSeek、通义千问、商汤、文心一言为代表的大模型&#xff0c;为企业视频创作生产带来全新体验。 传统视频创作面临着同质化、…

网络编程之客户端聊天(服务器加客户端共三种方式)

最终效果&#xff1a; serve.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/select.h>#define MAX_CLIENTS 2 // 只允许两个客户端 #define BUF_SIZE 1024i…

图莫斯TOOMOSS上位机TCANLINPro使用CAN UDS功能时 编写、加载27服务dll解锁算法文件

【本文发布于https://blog.csdn.net/Stack_/article/details/146303690&#xff0c;未经许可不得转载&#xff0c;转载须注明出处】 软件安装目录下找到如下压缩包&#xff0c;此为dll文件示例工程 使用VisualStudio打开工程GenerateKeyExImpl.vcxproj&#xff0c;可能会提示版…

vue+echarts实现饼图组件(实现左右联动并且数据量大时可滚动)

pieChart.vue(直接cv即可) <template><div class"rBox1"><div id"rBox1"></div></div> </template><script> export default {name: "pieChart",dicts: [],props: {subtext: {type: String,default…

Linux vim mode | raw / cooked

注&#xff1a;机翻&#xff0c;未校。 vim terminal “raw” mode Vim 终端 “raw” 模式 1. 原始模式与已处理模式的区别 We know vim puts the terminal in “raw” mode where it receives keystrokes as they are typed, opposed to “cooked” mode where the command…

IMX8MP Android 10系统编译SDK

概述&#xff1a; 本文描述了在Ubuntu 20.04操作系统上搭建IMX8MP Android10系统编译环境。 ubuntu主机端设置 1. ubuntu 20.04 1. 450G Free Disk space 2. 16GB RAM以上 3. 安装 sudo apt-get install uuid uuid-dev zlib1g-dev liblz-dev liblzo2-2 liblzo2-dev lzop …

ICLR 2025 机器人智能灵巧操作更进一步DexTrack

现实世界的机器人距离科幻小说里的机器人世界还有多远&#xff1f;通用灵巧操控何时才能实现&#xff1f;朝着这一伟大的目标&#xff0c;研究通用灵巧操控轨迹跟踪的 DexTrack 便应运而生。 论文地址&#xff1a;https://arxiv.org/abs/2502.09614代码地址&#xff1a;https:/…

Golang开发

Golang 文章目录 Golang预备技术一、算法与数据结构第1章&#xff1a;基础算法第2章&#xff1a;数据结构第3章&#xff1a;搜索与图论第4章&#xff1a;数论第5章&#xff1a;动态规划第6章&#xff1a;贪心第7章&#xff1a;算法竞赛入门 二、Linux操作系统与Shell编程三、计…

AI入门7:python三种API方式调用本地Ollama+DeepSeek

回顾 书接上篇&#xff1a;各种方式搭建了本地知识库&#xff1a; AI入门&#xff1a;AI模型管家婆ollama的安装和使用-CSDN博客 AI入门2&#xff1a;本地AI部署&#xff0c;用ollama部署deepseek&#xff08;私有化部署&#xff09;-CSDN博客 AI入门3&#xff1a;给本地d…

《线程池:Linux平台编译线程池动态库发生的死锁问题》

关于如何编译动态库可以移步《Linux&#xff1a;动态库动态链接与静态库静态链接》-CSDN博客 我们写的线程池代码是闭源的&#xff0c;未来想提供给别人使用&#xff0c;只需要提供so库和头文件即可。 系统默认库文件路径为&#xff1a; usr/lib usr/loacl/lib 系统默认头文件…