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

Unity 中使用波浪动画创建 UI 图像

如何使用请添加图片描述

只需将此组件添加到画布中的空对象即可。强烈建议您将此对象放入其自己的画布/嵌套画布中,因为它会弄脏每一帧的画布并导致重新生成整个网格。

注意:不支持切片图像。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Sprites;
using UnityEngine.UI;
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
using UnityEngine.U2D;
#endif#if UNITY_EDITOR
using UnityEditor;// Custom Editor to order the variables in the Inspector similar to Image component
[CustomEditor( typeof( WavyImage ) )]
[CanEditMultipleObjects]
public class WavyImageEditor : Editor
{private SerializedProperty colorProp, spriteProp, preserveAspectProp, waveSpeedIgnoresTimeScaleProp;private GUIContent spriteLabel;private List<WavyImage> wavyImages;private bool inspectingAsset;internal static bool previewInEditor;private void OnEnable(){Object[] _targets = targets;wavyImages = new List<WavyImage>( _targets.Length );for( int i = 0; i < _targets.Length; i++ ){WavyImage wavyImage = _targets[i] as WavyImage;if( wavyImage ){wavyImages.Add( wavyImage );inspectingAsset |= AssetDatabase.Contains( wavyImage );}}colorProp = serializedObject.FindProperty( "m_Color" );spriteProp = serializedObject.FindProperty( "m_Sprite" );preserveAspectProp = serializedObject.FindProperty( "m_PreserveAspect" );waveSpeedIgnoresTimeScaleProp = serializedObject.FindProperty( "m_WaveSpeedIgnoresTimeScale" );spriteLabel = new GUIContent( "Source Image" );}private void OnDisable(){if( previewInEditor ){previewInEditor = false;RefreshWavyImages();}EditorApplication.update -= PreviewInEditor;}public override void OnInspectorGUI(){serializedObject.Update();EditorGUILayout.PropertyField( colorProp );EditorGUILayout.PropertyField( spriteProp, spriteLabel );if( spriteProp.hasMultipleDifferentValues || spriteProp.objectReferenceValue ){EditorGUI.indentLevel++;EditorGUILayout.PropertyField( preserveAspectProp );EditorGUI.indentLevel--;}DrawPropertiesExcluding( serializedObject, "m_Script", "m_Color", "m_Sprite", "m_PreserveAspect", "m_WaveSpeedIgnoresTimeScale", "m_OnCullStateChanged" );EditorGUI.indentLevel++;EditorGUILayout.PropertyField( waveSpeedIgnoresTimeScaleProp );EditorGUI.indentLevel--;serializedObject.ApplyModifiedProperties();if( !EditorApplication.isPlayingOrWillChangePlaymode && !inspectingAsset ){EditorGUILayout.Space();EditorGUI.BeginChangeCheck();previewInEditor = GUILayout.Toggle( previewInEditor, "Preview In Editor", GUI.skin.button );if( EditorGUI.EndChangeCheck() ){if( previewInEditor ){EditorApplication.update -= PreviewInEditor;EditorApplication.update += PreviewInEditor;}else{EditorApplication.update -= PreviewInEditor;RefreshWavyImages();EditorApplication.delayCall += RefreshWavyImages; // Preview is sometimes not reset immediately without this call}}}}private void PreviewInEditor(){if( EditorApplication.isPlayingOrWillChangePlaymode ){previewInEditor = false;EditorApplication.update -= PreviewInEditor;}elseRefreshWavyImages();}private void RefreshWavyImages(){EditorApplication.QueuePlayerLoopUpdate();}
}
#endif[RequireComponent( typeof( CanvasRenderer ) )]
[AddComponentMenu( "UI/Wavy Image", 12 )]
public class WavyImage : MaskableGraphic, ILayoutElement
{[SerializeField]private Sprite m_Sprite;public Sprite sprite{get { return m_Sprite; }set{if( m_Sprite ){if( m_Sprite != value ){m_Sprite = value;SetAllDirty();TrackImage();}}else if( value ){m_Sprite = value;SetAllDirty();TrackImage();}}}[SerializeField]private bool m_PreserveAspect;public bool preserveAspect{get { return m_PreserveAspect; }set { if( m_PreserveAspect != value ) { m_PreserveAspect = value; SetVerticesDirty(); } }}[Header( "Wave Animation" )][Tooltip( "Number of rows and columns in the generated grid. The larger this value is, the smoother the wave animation will be but the calculations will also take more time." )][Range( 0, 10 )][SerializeField]private int m_WaveSegments = 3;public int waveSegments{get { return m_WaveSegments; }set { if( m_WaveSegments != value ) { m_WaveSegments = value; SetVerticesDirty(); } }}[Range( -0.5f, 0.5f )][SerializeField]private float m_WaveStrength = 0.15f;public float waveStrength{get { return m_WaveStrength; }set { if( m_WaveStrength != value ) { m_WaveStrength = value; SetVerticesDirty(); } }}[Tooltip( "As this value increases, the wave animation will become more 'chaotic' because vertices will start moving in more random directions." )][Range( 0f, 1f )][SerializeField]private float m_WaveDiversity = 0.5f;private float waveDiversitySqrt; // The visual impact of waveDiversity's square root seems to be more uniform than waveDiversity itselfpublic float waveDiversity{get { return m_WaveDiversity; }set { if( m_WaveDiversity != value ) { m_WaveDiversity = value; waveDiversitySqrt = Mathf.Sqrt( value ); SetVerticesDirty(); } }}[SerializeField]private float m_WaveSpeed = 0.5f;public float waveSpeed{get { return m_WaveSpeed; }set { if( m_WaveSpeed != value ) { m_WaveSpeed = value; SetVerticesDirty(); } }}[SerializeField]private bool m_WaveSpeedIgnoresTimeScale = true;public bool waveSpeedIgnoresTimeScale{get { return waveSpeedIgnoresTimeScale; }set { waveSpeedIgnoresTimeScale = value; }}private float waveAnimationTime;public override Texture mainTexture { get { return m_Sprite ? m_Sprite.texture : s_WhiteTexture; } }public float pixelsPerUnit{get{float spritePixelsPerUnit = 100;if( m_Sprite )spritePixelsPerUnit = m_Sprite.pixelsPerUnit;float referencePixelsPerUnit = 100;if( canvas )referencePixelsPerUnit = canvas.referencePixelsPerUnit;return spritePixelsPerUnit / referencePixelsPerUnit;}}public override Material material{get{if( m_Material != null )return m_Material;if( m_Sprite && m_Sprite.associatedAlphaSplitTexture != null ){
#if UNITY_EDITORif( Application.isPlaying )
#endifreturn Image.defaultETC1GraphicMaterial;}return defaultMaterial;}set { base.material = value; }}protected override void Awake(){base.Awake();waveDiversitySqrt = Mathf.Sqrt( m_WaveDiversity );}protected override void OnEnable(){base.OnEnable();TrackImage();}protected override void OnDisable(){base.OnDisable();if( m_Tracked )UnTrackImage();}private void Update(){if( m_WaveSegments > 0 && m_WaveSpeed != 0f && m_WaveStrength != 0f )SetVerticesDirty();}protected override void OnPopulateMesh( VertexHelper vh ){vh.Clear();Color32 color32 = color;Rect rect = GetPixelAdjustedRect();Vector4 uv;float bottomLeftX, bottomLeftY, width, height;if( m_Sprite ){uv = DataUtility.GetOuterUV( m_Sprite );Vector4 padding = DataUtility.GetPadding( m_Sprite );Vector2 size = m_Sprite.rect.size;int spriteW = Mathf.RoundToInt( size.x );int spriteH = Mathf.RoundToInt( size.y );if( m_PreserveAspect && size.sqrMagnitude > 0f ){float spriteRatio = size.x / size.y;float rectRatio = rect.width / rect.height;if( spriteRatio > rectRatio ){float oldHeight = rect.height;rect.height = rect.width * ( 1f / spriteRatio );rect.y += ( oldHeight - rect.height ) * rectTransform.pivot.y;}else{float oldWidth = rect.width;rect.width = rect.height * spriteRatio;rect.x += ( oldWidth - rect.width ) * rectTransform.pivot.x;}}bottomLeftX = rect.x + rect.width * padding.x / spriteW;bottomLeftY = rect.y + rect.height * padding.y / spriteH;width = rect.width * ( spriteW - padding.z - padding.x ) / spriteW;height = rect.height * ( spriteH - padding.w - padding.y ) / spriteH;}else{uv = Vector4.zero;bottomLeftX = rect.x;bottomLeftY = rect.y;width = rect.width;height = rect.height;}#if UNITY_EDITORif( ( !Application.isPlaying && !WavyImageEditor.previewInEditor ) || m_WaveSegments <= 0 )
#elseif( m_WaveSegments <= 0 )
#endif{// Generate normal Imagevh.AddVert( new Vector3( bottomLeftX, bottomLeftY, 0f ), color32, new Vector2( uv.x, uv.y ) );vh.AddVert( new Vector3( bottomLeftX, bottomLeftY + height, 0f ), color32, new Vector2( uv.x, uv.w ) );vh.AddVert( new Vector3( bottomLeftX + width, bottomLeftY + height, 0f ), color32, new Vector2( uv.z, uv.w ) );vh.AddVert( new Vector3( bottomLeftX + width, bottomLeftY, 0f ), color32, new Vector2( uv.z, uv.y ) );vh.AddTriangle( 0, 1, 2 );vh.AddTriangle( 2, 3, 0 );}else{// Generate multiple small quads and move their verticesfloat invWaveSegments = 1f / m_WaveSegments;waveAnimationTime += ( m_WaveSpeedIgnoresTimeScale ? Time.unscaledDeltaTime : Time.deltaTime ) * m_WaveSpeed;float widthOffset = m_WaveStrength * width;float heightOffset = m_WaveStrength * height;#if UNITY_EDITORwaveDiversitySqrt = Mathf.Sqrt( m_WaveDiversity );
#endiffor( int i = 0; i <= m_WaveSegments; i++ ){for( int j = 0; j <= m_WaveSegments; j++ ){float normalizedX = j * invWaveSegments;float normalizedY = i * invWaveSegments;Vector2 _uv = new Vector2( uv.z * normalizedX + uv.x * ( 1f - normalizedX ), uv.w * normalizedY + uv.y * ( 1f - normalizedY ) );Vector3 _position = new Vector3( bottomLeftX + width * normalizedX, bottomLeftY + height * normalizedY, 0f );_position.x += ( Mathf.PerlinNoise( normalizedX * waveDiversitySqrt + waveAnimationTime, normalizedY * waveDiversitySqrt ) - 0.5f ) * widthOffset;_position.y += ( Mathf.PerlinNoise( normalizedX * waveDiversitySqrt, normalizedY * waveDiversitySqrt + waveAnimationTime ) - 0.5f ) * heightOffset;vh.AddVert( _position, color32, _uv );}}for( int i = 0; i < m_WaveSegments; i++ ){int firstTriangle = i * ( m_WaveSegments + 1 );for( int j = 0; j < m_WaveSegments; j++ ){int triangle = firstTriangle + j;int aboveTriangle = triangle + m_WaveSegments + 1;vh.AddTriangle( triangle, aboveTriangle, aboveTriangle + 1 );vh.AddTriangle( aboveTriangle + 1, triangle + 1, triangle );}}}}int ILayoutElement.layoutPriority { get { return 0; } }float ILayoutElement.minWidth { get { return 0f; } }float ILayoutElement.minHeight { get { return 0f; } }float ILayoutElement.flexibleWidth { get { return -1; } }float ILayoutElement.flexibleHeight { get { return -1; } }float ILayoutElement.preferredWidth { get { return m_Sprite ? ( m_Sprite.rect.size.x / pixelsPerUnit ) : 0f; } }float ILayoutElement.preferredHeight { get { return m_Sprite ? ( m_Sprite.rect.size.y / pixelsPerUnit ) : 0f; } }void ILayoutElement.CalculateLayoutInputHorizontal() { }void ILayoutElement.CalculateLayoutInputVertical() { }// Whether this is being tracked for Atlas Bindingprivate bool m_Tracked = false;#if UNITY_2017_4 || UNITY_2018_2_OR_NEWERprivate static List<WavyImage> m_TrackedTexturelessImages = new List<WavyImage>();private static bool s_Initialized;
#endifprivate void TrackImage(){if( m_Sprite != null && m_Sprite.texture == null ){
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWERif( !s_Initialized ){SpriteAtlasManager.atlasRegistered += RebuildImage;s_Initialized = true;}m_TrackedTexturelessImages.Add( this );
#endifm_Tracked = true;}}private void UnTrackImage(){
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWERm_TrackedTexturelessImages.Remove( this );
#endifm_Tracked = false;}#if UNITY_2017_4 || UNITY_2018_2_OR_NEWERprivate static void RebuildImage( SpriteAtlas spriteAtlas ){for( int i = m_TrackedTexturelessImages.Count - 1; i >= 0; i-- ){WavyImage image = m_TrackedTexturelessImages[i];if( spriteAtlas.CanBindTo( image.sprite ) ){image.SetAllDirty();m_TrackedTexturelessImages.RemoveAt( i );}}}
#endif
}

相关文章:

Unity 中使用波浪动画创建 UI 图像

如何使用 只需将此组件添加到画布中的空对象即可。强烈建议您将此对象放入其自己的画布/嵌套画布中&#xff0c;因为它会弄脏每一帧的画布并导致重新生成整个网格。 注意&#xff1a;不支持切片图像。 using System.Collections.Generic; using UnityEngine; using UnityEng…...

支付功能测试用例测试点?

支付功能测试用例测试点是指在测试支付功能时&#xff0c;需要关注和验证的各个方面。根据不同的支付场景和需求&#xff0c;支付功能测试用例测试点可能有所不同&#xff0c;但一般可以分为以下几类&#xff1a; 功能测试&#xff1a;主要检查支付功能是否符合设计和业务需求…...

HFS 快速搭建 http 服务器

HFS 是一个轻量级的HTTP 服务工具&#xff0c;3.0版本前进提供Windows平台安装包&#xff0c;3.0版本开提供Linux和macOS平台的安装包。 HFS更适合在局域网环境中搭建文件共享服务或者安装配置源服务器。 甲 非守护进程的方式运行 HFS &#xff08;Ubuntu 22.04&#xff09; 一…...

学生专用台灯怎么选?双十一专业学生护眼台灯推荐

台灯应该是很多家庭都会备上一盏的家用灯具&#xff0c;很多大人平时间看书、用电脑都会用上它&#xff0c;不过更多的可能还是给家中的小孩学习、阅读使用的。而且现在的孩子近视率如此之高&#xff0c;这让家长们不得不重视孩子的视力健康问题。那么孩子学习使用的台灯应该怎…...

Go 常用标准库之 fmt 介绍与基本使用

Go 常用标准库之 fmt 介绍与基本使用 文章目录 Go 常用标准库之 fmt 介绍与基本使用一、介绍二、向外输出2.1 Print 系列2.2 Fprint 系列2.3 Sprint 系列2.4 Errorf 系列 三、格式化占位符3.1 通用占位符3.2 布尔型3.3 整型3.4 浮点数与复数3.5 字符串和[]byte3.6 指针3.7 宽度…...

antv/x6 导出图片方法exportPNG

antv/x6 导出图片方法exportPNG antv/x6 版本如下&#xff1a; "antv/x6": "2.14.1","antv/x6-plugin-export": "2.1.6",在文件中导入 import { Graph, Shape, StringExt } from antv/x6 import { Export } from antv/x6-plugin-exp…...

Decomposed Meta-Learning for Few-Shot Named Entity Recognition

原文链接&#xff1a; https://aclanthology.org/2022.findings-acl.124.pdf ACL 2022 介绍 问题 目前基于span的跨度量学习&#xff08;metric learning&#xff09;的方法存在一些问题&#xff1a; 1&#xff09;由于是通过枚举来生成span&#xff0c;因此在解码的时候需要额…...

C++经典面试题:内存泄露是什么?如何排查?

1.内存泄露的定义&#xff1a;内存泄漏简单的说就是申请了⼀块内存空间&#xff0c;使⽤完毕后没有释放掉。 它的⼀般表现⽅式是程序运⾏时间越⻓&#xff0c;占⽤内存越多&#xff0c;最终⽤尽全部内存&#xff0c;整个系统崩溃。由程序申请的⼀块内存&#xff0c;且没有任何⼀…...

Hadoop+Hive+Spark+Hbase开发环境练习

1.练习一 1.数据准备 在hdfs上创建文件夹&#xff0c;上传csv文件 [rootkb129 ~]# hdfs dfs -mkdir -p /app/data/exam 查看csv文件行数 [rootkb129 ~]# hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l 2.分别使用 RDD和 Spark SQL 完成以下分析&#xf…...

使用Spring Boot限制在一分钟内某个IP只能访问10次

有些时候&#xff0c;为了防止我们上线的网站被攻击&#xff0c;或者被刷取流量&#xff0c;我们会对某一个ip进行限制处理&#xff0c;这篇文章&#xff0c;我们将通过Spring Boot编写一个小案例&#xff0c;来实现在一分钟内同一个IP只能访问10次&#xff0c;当然具体数值&am…...

ES 数据迁移最佳实践

ES 数据迁移最佳实践与讲解 数据迁移是 Elasticsearch 运维管理和业务需求中常见的操作之一。以下是不同数据迁移方法的最佳实践和讲解&#xff1a; 一、数据迁移需求梳理 二、数据迁移方法梳理 三、各方案对比 方案 优点 缺点&#xff08;限制&#xff09; 适用场景 是否有…...

C++中低级内存操作

C中低级内存操作 C相较于C有一个巨大的优势&#xff0c;那就是你不需要过多地担心内存管理。如果你使用面向对象的编程方式&#xff0c;你只需要确保每个独立的类都能妥善地管理自己的内存。通过构造和析构&#xff0c;编译器会帮助你管理内存&#xff0c;告诉你什么时候需要进…...

Linux硬盘大小查看命令全解析 (linux查看硬盘大小命令)

Linux操作系统是一款广泛应用于服务器和嵌入式设备的操作系统&#xff0c;相比于Windows等其他操作系统&#xff0c;Linux的优点之一就是支持强大的命令行操作。在日常操作中&#xff0c;了解和掌握一些简单但实用的命令可以提高工作效率。比如硬盘大小查看命令&#xff0c;在L…...

什么是供应链金融?

一、供应链金融产生背景 供应链金融兴起的起源来自于供应链管理一个产品生产过程分为三个阶段&#xff1a;原材料 - 中间产品 - 成产品。由于技术进步需求升级&#xff0c;生产过程从以前的企业内分工&#xff0c;转变为企业间分工。那么整个过程演变了如今的供应链管理流程&a…...

Qt之实现支持多选的QCombobox

一.效果 1.点击下拉列表的复选框区域 2.点击下拉列表的非复选框区域 二.实现 QHCustomComboBox.h #ifndef QHCUSTOMCOMBOBOX_H #define QHCUSTOMCOMBOBOX_H#include <QLineEdit> #include <QListWidget> #include <QCheckBox> #include <QComboBox>…...

【UI设计】Figma_“全面”快捷键

目录 1.快捷键与键位&#xff08;mac与windows&#xff09;2.基础快捷键3.操作区快捷键3.1视图3.2文字3.3选项3.4图层3.5组件 4.特殊技巧 Figma 是一个 基于浏览器 的协作式 UI 设计工具。【https://www.figma.com/】 Figma Sketch&#xff08;UI 设计&#xff09; InVision&a…...

计算机网络(谢希仁)第八版课后题答案(第一章)

1.计算机网络可以向用户提供哪些服务 连通性:计算机网络使上网用户之间可以交换信息&#xff0c;好像这些用户的计算机都可以彼此直接连通一样。 共享:指资源共享。可以是信息、软件&#xff0c;也可以是硬件共享。 2.试简述分组交换的要点 采用了存储转发技术。把报文(要发…...

argparse模块介绍

argparse是一个Python模块&#xff1a;命令行选项、参数和子命令解析器。argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义了所需的参数&#xff0c;而 argparse 将找出如何从 sys.argv &#xff08;命令行&#xff09;中解析这些参数。argparse 模块还会自动生成…...

分布式、集群、微服务

分布式是以缩短单个任务的执行时间来提升效率的&#xff1b;而集群则是通过提高单位时间内执行的任务数来提升效率。 分布式是指将不同的业务分布在不同的地方。 集群指的是将几台服务器集中在一起&#xff0c;实现同一业务。 分布式中的每一个节点&#xff0c;都可以做集群…...

Android Studio的debug和release模式及签名配置

Android Studio的两种模式及签名配置 使用Android Studio 运行我们的app&#xff0c;无非两种模式&#xff1a;debug和release模式。 https://www.cnblogs.com/details-666/p/keystore.html...

【深蓝学院】手写VIO第8章--相机与IMU时间戳同步--笔记

0. 内容 1. 时间戳同步问题及意义 时间戳同步的原因&#xff1a;如果不同步&#xff0c;由于IMU频率高&#xff0c;可能由于时间戳不同步而导致在两帧camera之间的时间内用多了或者用少了IMU的数据&#xff0c;且时间不同步会导致我们首尾camera和IMU数据时间不同&#xff0c;…...

【Java集合类面试二十一】、请介绍TreeMap的底层原理

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;请介绍TreeMap的底层原理…...

Go语言Channel

在本教程中&#xff0c;我们将讨论Channel以及 Goroutines 如何使用Channel进行通信。 什么是Channel Channel可以被认为是 Goroutine 用来进行通信的管道。与水在管道中从一端流向另一端的方式类似&#xff0c;可以使用Channel从一端发送数据并从另一端接收数据。 声明Chan…...

java 编译 引用 jar 包进行编译和执行编译后的class文件

编译java文件 javac -encoding UTF-8 -Djava.ext.dirs./ -d . ./FtpTest.java 执行编译class文件 java -Djava.ext.dirs./ com.util.FtpTest com.util为包路径...

Linux系统之部署Tale个人博客系统

Linux系统之部署Tale个人博客系统 一、Tale介绍1.1 Tale简介1.2 Tale特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本 四、部署Tale个人博客系统4.1 下载Tale源码4.2 查看Tale源码目录4.3 查看安装脚本内…...

【跟小嘉学 Rust 编程】三十三、Rust的Web开发框架之一: Actix-Web的基础

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

算法通关村|黄金挑战|K个一组进行反转

K个一组进行反转 1.头插法 public ListNode reverseKGroup(ListNode head, int k) {ListNode dummyNode new ListNode(0);dummyNode.next head;ListNode cur head;// 计算链表长度int len 0;while (cur ! null) {len;cur cur.next;}// 计算有几组int n len / k;ListNod…...

【Android Studio】工程中文件Annotate with Git Blame 不能点击

问题描述 工程文件中想要查看代码提交信息但是相关按钮不可点击 解决方法 Android Studio -> Preferences -> Version Control-> 在Unregistered roots里找到你想要的工程文件 点击左上角➕号 然后右下角Apply即可...

Ant Design Vue

2222222222222...

ATA-P2010压电叠堆功率放大器-直流偏置对压电叠堆测试的重要性

随着科技的发展和应用领域的扩展&#xff0c;压电技术在许多领域中得到了广泛的应用。在压电器件的研究和开发过程中&#xff0c;压电叠堆测试是非常重要的一环。本文通过对功率放大器的直流偏置功能在压电叠堆测试中的应用进行了深入研究&#xff0c;探讨了功率放大器直流偏置…...