Unity:圆底烧瓶中液体液面升降变化的效果

这篇具有很好参考价值的文章主要介绍了Unity:圆底烧瓶中液体液面升降变化的效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、效果展示

Unity:圆底烧瓶中液体液面升降变化的效果

二、实现的原理

1、从image的filled模式说起

image的filled模式,适合用来做进度条:
Unity:圆底烧瓶中液体液面升降变化的效果
Unity:圆底烧瓶中液体液面升降变化的效果

2、能否为一个3D object实现一个image filled 的shader ?

Shader "Custom/FilledImageEffect"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1, 1, 1, 1)
        _FillAmount ("Fill Amount", Range(0, 1)) = 1
    }

    SubShader
    {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}
        LOD 100

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        float4 _Color;
        float _FillAmount;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            float2 uv = IN.uv_MainTex;
            float4 c = tex2D(_MainTex, uv) * _Color;

            if (uv.x > _FillAmount)
            {
                c.a = 0;
            }

            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

3、液面变化的Shader

Shader "Custom/LiquidBottle"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor("MainColor",Color) = (1, 1, 1, 1)
        _TopColor("TopColor",Color) = (1, 1, 0, 1)
        _FillAmount("FillAmout",Range(-1 , 2)) = 0
        _EdgeWidth("EdgeWidth",Range(0 , 1)) = 0.2

        _BottleWidth("BottleWidth",Range(0,1)) = 0.2
        _BottleColor("BottleColor",Color) = (1,1,1,1)

        _RimColor("RimColor",Color)=(1,1,1,1)
        _RimWidth("RimWidth",float)=0.2

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Cull OFF
            AlphaToMask on
            //ZWrite On
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
               
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float fillEdge : TEXCOORD1;
                float3 viewDir : COLOR;
                float3 normal : COLOR2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _MainColor;
            float _FillAmount;
            float4 _TopColor;
            float _EdgeWidth;

            float4 _RimColor;
            float _RimWidth;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                o.fillEdge=mul(unity_ObjectToWorld,v.vertex.xyz).y+_FillAmount;
                o.normal=v.normal;
                o.viewDir=normalize(ObjSpaceViewDir(v.vertex));
                return o;
            }

            fixed4 frag (v2f i,fixed facing : VFace) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv) * _MainColor;
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);

                float dotProduct = 1-pow(dot(i.normal, i.viewDir),_RimWidth);
                float4 rimCol=_RimColor*smoothstep(0.5,1,dotProduct);

                fixed4 edgeVal=step(i.fillEdge,0.5)-step(i.fillEdge,0.5-_EdgeWidth);
                fixed4 edgeCol=edgeVal *= _TopColor*0.9;

                fixed4 finalVal=step(i.fillEdge,0.5)-edgeVal;
                fixed4 finalCol=finalVal*col;
                finalCol+=edgeCol+rimCol;

                 fixed4 topCol=_TopColor * (edgeVal+finalVal);
                // float dotVal = 1- pow(dot(i.normal, i.viewDir),0.3);
                // return float4(dotVal,dotVal,dotVal,1);
                return facing > 0 ? finalCol : topCol;
            }
            ENDCG
        }

        Pass
        {
            //Cull Front
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float4 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 viewDir : COLOR;
                float3 normal :NORMAL;
            };

            float4 _BottleColor;
            float _BottleWidth;

            float4 _RimColor;
            float _RimWidth;

            v2f vert (appdata v)
            {
                v2f o;
                v.vertex.xyz+=v.normal.xyz*_BottleWidth;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                UNITY_TRANSFER_FOG(o,o.vertex);
                o.normal=v.normal.xyz;
                o.viewDir=normalize(ObjSpaceViewDir(v.vertex));

                return o;
            }

            fixed4 frag (v2f i,fixed facing : VFace) : SV_Target
            {
                // sample the texture
                fixed4 col = _BottleColor;
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);

                float dotProduct = 1-pow(dot(i.normal, i.viewDir),_RimWidth);//1-pow(dot(i.normal, i.viewDir),_RimWidth/10);
                float4 rimCol=_RimColor*smoothstep(0.2,1,dotProduct);
              
                return rimCol;
            }
            ENDCG
        }
    }
}

三、服用方法

  • 1、创建一个液面效果的材质
    Unity:圆底烧瓶中液体液面升降变化的效果

  • 2、把这个材质挂载到瓶子中的【液体】模型上

  • 3、在面板上拖动FillAmout

  • 4、在脚本中设置mat的该属性
    mat.SetFloat(“_FillAmount”, currentValue);文章来源地址https://www.toymoban.com/news/detail-506970.html

四、附录:C#调用代码

1、液面升降动画的异步方法

/// <summary>
/// 容器的液面变化:化学实验中,量筒中倒入液体或者被吸取液体后,液面会升降
/// 材质用shader,控制其fillAmout参数
/// </summary>
/// <param name="mat">操作的材质</param>
/// <param name="levelStart">起始液面位置</param>
/// <param name="levelEnd">结束页面位置</param>
/// <param name="duration">动画的时间</param>
/// <returns></returns>
public static async UniTask DoLiquidLevel(Material mat, float levelStart, float levelEnd, float duration)
{
    float currentValue = levelStart;
    float timeElapsed = 0f;
    while (timeElapsed < duration)
    {
        currentValue = Mathf.Lerp(levelStart, levelEnd, timeElapsed / duration);
        Debug.Log(currentValue);
        mat.SetFloat("_FillAmount", currentValue);      //变量名字确保与Shader源码中的变量一致。
        await UniTask.Yield();
        timeElapsed += Time.deltaTime;
    }
    mat.SetFloat("_FillAmount", levelEnd);              //确保最终结果准确
}

2、monobehaviour示例脚本

using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using static txlib;//包含 DoLiquidLevel()

/// <summary>
/// 容器的液面升降控制
/// </summary>
public class ChangeLiquidLevel : MonoBehaviour
{
    /// <summary>
    /// 物体
    /// </summary>
    public GameObject obj;

    /// <summary>
    /// 起始液面
    /// </summary>
    public float levelStart;

    /// <summary>
    /// 终止液面
    /// </summary>
    public float levelEnd;

    /// <summary>
    /// 动画耗时
    /// </summary>
    public float duration;
    
    /// <summary>
    /// 材质
    /// </summary>
    private Material mat;

    [ContextMenu("测试液面")]
    async UniTask Test()
    {
        mat = obj.GetComponent<Renderer>().sharedMaterial;
        while (true)
        {
            await DoLiquidLevel(mat, levelStart, levelEnd, duration);
            await DoLiquidLevel(mat, levelEnd, levelStart, duration);
            await UniTask.Delay(TimeSpan.FromSeconds(0.8f));
        }
    }
}

到了这里,关于Unity:圆底烧瓶中液体液面升降变化的效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaScript实现液体流动效果和鼠标交互

    在现代Web应用中,动态效果和交互性已经成为了不可或缺的元素。在这篇博客中,我们将使用JavaScript创建一个液体流动效果,并添加鼠标交互功能,让用户能够与页面进行互动。 创建画布和粒子 首先,我们需要创建一个画布元素,用于绘制我们的液体流动效果。在HTML中添加

    2024年02月13日
    浏览(52)
  • 【Unity】超简单特效 - 液体冒泡泡

    前言: 前面我们学习了气体特效烟雾,那么今天我们来了解一个同样也非常常用且常见的液体特效泡泡。在游戏中我们常常会遇到像沼泽、毒池、沸水、烹饪、药瓶、泥潭等等非会出现液体冒泡的情况,那么这些如果在Unity里用粒子系统如何快速的实现呢。 初步实现: 根据

    2024年02月09日
    浏览(32)
  • 【Unity3d】 教会你如何做一个简单的电梯系统(升降平台)

           博主第一次写博客,语言略俗,有不足之处还请指正!        由于自己还处在unity小白阶段,受2d升降平台的影响(后续我也会上传关于2d升降平台的文章),突发奇想如何用3d做一个电梯系统,查阅网上资料后,发现网上对这方面的讲解少之又少,或者说其他博主提

    2024年02月11日
    浏览(111)
  • opencv实现图像去畸变——几种实现方式(含完整代码)&&效果对比图&&详细参数说明&&核心参数变化对应变化效果图&&常见问题

    以下介绍下opencv实现图像去畸变的几种方式以及详细参数说明,含项目案例,含扩展的相关知识 ① cv::fisheye::initUndistortRectifyMap 和 ② cv::initUndistortRectifyMap 都是 OpenCV 库中的函数,用于摄像机的畸变校正和图像的矫正。二者的区别在于,cv::fisheye::initUndistortRectifyMap 适用于

    2024年02月10日
    浏览(97)
  • 数据可视化:随时间变化的效果图

    获取北京、上海、江苏、广东四省的2008—2012年的GDP数据 在Jupyter Notebook上实现代码如下:

    2023年04月12日
    浏览(45)
  • 【UE4基础】天空效果设置、太阳位置的变化

    根据天空球构建天空的基本要素: 天空球:BP_Sky_Sphere 定向光源:DirectionalLight 构建步骤: 把天空球拖入场景中,把定向光源拖入场景中,设置位置都为(0,0,0),无旋转角度。将天空球与定向光源绑定: 定向光源角度: 旋转定向光源y轴角度:太阳上下位置变化 旋转定向光源

    2024年02月04日
    浏览(32)
  • Unity3D完成随时间变化的昼夜交替及光线变化

    Unity3D环境中的昼夜交替,并且控制好光线随着时间的变化而变化,太阳位置跟随经纬度的不同而不同。 重点: 时间范围为0~24小时; 太阳位置跟随当前经纬度; 太阳完成东升西落,世界坐标系中的x正为东方,x负为西方,z正为北; 太阳光线强度变化范围0~1,按照24小时的正

    2024年02月11日
    浏览(74)
  • unity 控制Dropdown的Arrow箭头变化

     Dropdown打开下拉菜单会以“Template”为模板创建一个Dropdown List,在“Template”上添加一个脚本在Start()中执行下拉框打开时的操作,在OnDestroy()中执行下拉框收起时的操作即可。 效果代码如下用于控制Arrow旋转可以根据自己的想法进行修改:

    2024年02月09日
    浏览(36)
  • 【unity小技巧】unity3d环境带雾的昼夜系统变化

    链接:https://pan.baidu.com/s/1qlFSJSju6ZjwCylwkh14eA?pwd=veww 提取码:veww 眩光其实可以简单的理解为太阳或月亮 想要相机显示眩光,需要在相机添加Flare Layer组件 配置参数 配置20 25 30 70 75 80位置的灯光颜色,具体的需要根据自己的天空盒 环境等,调配出适合的颜色和过渡 效果 加眩光

    2024年02月22日
    浏览(53)
  • Unity中C#使用协程控制Shader材质变化

    在上一篇文章实现了C#脚本简单修改Shader材质的效果后,我们使用按钮点击结合协程来实现一下游戏中角色常见的效果:受击、中毒、消融效果 我们继续使用上一篇的 Shader 和 C# 脚本来继续测试 Unity中C#如何访问并修改Shader材质 Unity中的协程可以理解为 C# 中多线程的作用,在

    2024年02月04日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包