您现在的位置是:首页 >学无止境 >Unity:圆底烧瓶中液体液面升降变化的效果网站首页学无止境
Unity:圆底烧瓶中液体液面升降变化的效果
简介Unity:圆底烧瓶中液体液面升降变化的效果
一、效果展示
二、实现的原理
1、从image的filled模式说起
image的filled模式,适合用来做进度条:
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"
}
三、服用方法
-
1、创建一个液面效果的材质
-
2、把这个材质挂载到瓶子中的【液体】模型上
-
3、在面板上拖动FillAmout
-
4、在脚本中设置mat的该属性
mat.SetFloat(“_FillAmount”, currentValue);
四、附录: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));
}
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。