Unity动画关键帧与曲线操作

2024-08-24 19:32

本文主要是介绍Unity动画关键帧与曲线操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在项目开发中,动画的编辑一般由美术完成,他们会输出一个.anim的文件。

其实.anim文件实际上由一系列的关键帧组成,可以对这些关键帧进行操作,达到一定的目的。

本文章介绍实现将曲线变换形状,值偏移,时间偏移,上下、左右翻转。

目录

一、获取一个动画文件上的所有曲线

1.获得动画文件的bind属性

2.通过bind属性获得曲线

3.拿到曲线后获得关键帧

4.操作关键帧后,创建新的曲线

5.通过bind属性,将对应的新曲线应用回去,或者应用到新的动画文件,最后保存刷新资源

二、关键帧KeyFrame的属性和曲线的关系

三、对曲线上的关键帧进行偏移

四、复用曲线而不改变取值范围

1.首先添加编辑好的曲线

2.获取编辑好的曲线

3.根据原曲线上的关键帧进行一定比例的缩放和偏移

五、上下和水平翻转


一、获取一个动画文件上的所有曲线

1.获得动画文件的bind属性

EditorCurveBinding[] editorCurveBindings = AnimationUtility.GetCurveBindings(mClip);

2.通过bind属性获得曲线

AnimationCurve curve = AnimationUtility.GetEditorCurve(mClip, bind);

3.拿到曲线后获得关键帧

Keyframe[] frame = curve.keys;

4.操作关键帧后,创建新的曲线

AnimationCurve ac2 = new AnimationCurve(frame);

5.通过bind属性,将对应的新曲线应用回去,或者应用到新的动画文件,最后保存刷新资源

AnimationUtility.SetEditorCurve(targetClip, bind, curve);

二、关键帧KeyFrame的属性和曲线的关系

通过操作关键帧上的数值,达到形状变换,偏移,翻转的目的。

关于属性的详细介绍和曲线形状插值可以参考Unity动画关键帧插值

inTangent、outTangent代表斜率

inWeight、outWeight代表这个方向上影响的权重

这几个值是影响曲线走向的关键

三、对曲线上的关键帧进行偏移

偏移不影响原本的贝塞尔曲线插值,通过修改KeyFrame.value达到值偏移,修改KeyFrame.time达到时间偏移

四、复用曲线而不改变取值范围

1.首先添加编辑好的曲线

2.获取编辑好的曲线

EditorGUILayout.CurveField(shapeCurve);

3.根据原曲线上的关键帧进行一定比例的缩放和偏移

对值和时间进行偏移后,会改变原本的曲线形状,这里要根据原曲线的插值,对新曲线的关键帧参数进行修改

根据Unity动画关键帧插值提供的公式,计算出未缩放前的坐标,按照缩放比例缩放计算新的P1和P2,然后利用缩放后的P0和P3这两个端点的值,得到ow0,ot0,iw1,it1,设置到关键帧。

五、上下和水平翻转

上下和水平翻转都影响了原本贝塞尔曲线的斜率,tangent值其实是正切值,翻转过后刚好为原本值对应的角α的补角正切,即-tanα

所以上下翻转:

//切值取相反方向的切角补角的值
Keyframe key = new Keyframe(oldKey.time, 2 * first.value - oldKey.value, -oldKey.inTangent, -oldKey.outTangent, oldKey.inWeight, oldKey.outWeight);

左右翻转还需要对权重翻转,in和out对换

//切值取补角,权重调换
Keyframe key = new Keyframe(2 * midTime - oldKey.time, oldKey.value, -oldKey.inTangent, -oldKey.outTangent, oldKey.outWeight, oldKey.inWeight);

以上情况是针对默认曲线的(他们的关键帧inTangetn和outTangent相等),如果曲线是线性的,需要注意inTangent和outTangent不相等的情况

 

这篇关于Unity动画关键帧与曲线操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103392

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字

PR曲线——一个更敏感的性能评估工具

在不均衡数据集的情况下,精确率-召回率(Precision-Recall, PR)曲线是一种非常有用的工具,因为它提供了比传统的ROC曲线更准确的性能评估。以下是PR曲线在不均衡数据情况下的一些作用: 关注少数类:在不均衡数据集中,少数类的样本数量远少于多数类。PR曲线通过关注少数类(通常是正类)的性能来弥补这一点,因为它直接评估模型在识别正类方面的能力。 精确率与召回率的平衡:精确率(Pr

MySQL——表操作

目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,接下来来看一下表的相关操作。 一、创建表 create

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

PHP7扩展开发之流操作

前言 啥是流操作?简单来讲就是对一些文件,网络的IO操作。PHP已经把这些IO操作,封装成流操作。这节,我们将使用PHP扩展实现一个目录遍历的功能。PHP示例代码如下: <?phpfunction list_dir($dir) {if (is_dir($dir) === false) {return;} $dh = opendir($dir);if ($dh == false) {ret