Unity Timeline学习笔记(4) - 自定义轨道OnCreateClip和CreateTrackMixer用法上的区分

前面我们第二篇文章Unity Timeline学习笔记(2) - PlayableTrack是一个初步的PlayableTrack使用方法,有时候可能会个性化定制专属轨道。

OnCreateClip的例子

下面我们做一个例子:
首先是轨道
在这里插入图片描述

//FeatureTrack.cs
using System.ComponentModel;
using UnityEngine.Timeline;[DisplayName("(Feature)开关轨道")]
[TrackClipType(typeof(FeaturePlayableAsset))]
[TrackColor(0.53f, 0.0f, 0.08f)]//表示在编辑器中,Track轨道前端的标识颜色(不重要啦)
public class FeatureTrack : TrackAsset
{protected override void OnCreateClip(TimelineClip clip){base.OnCreateClip(clip);clip.displayName = "Clip显示名称";}
}

这里有TrackClipType表示我们只能添加类型为FeaturePlayableAsset的对象。

我们把PlayableAsset代码也放上:

//FeaturePlayableAsset.cs
using System;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;[DisplayName("(Feature)开关Clip")]
[Serializable]
public class FeaturePlayableAsset : PlayableAsset
{public string featureName;public override Playable CreatePlayable(PlayableGraph graph, GameObject owner){var p = ScriptPlayable<FeaturePlayableBehaviour>.Create(graph);var b = p.GetBehaviour();b.featureName = featureName;return p;}
}public class FeaturePlayableBehaviour : PlayableBehaviour
{public string featureName;// 当进入区域内触发Playpublic override void OnBehaviourPlay(Playable playable, FrameData info){Debug.Log($"触发 OnBehaviourPlay ,name: {featureName}");}// 当出了区域触发,或者开始的时候触发,或者停止运行的时候public override void OnBehaviourPause(Playable playable, FrameData info){Debug.Log($"触发 OnBehaviourPause , name: {featureName}");} 在区域内每个Frame地方都会触发public override void ProcessFrame(Playable playable, FrameData info, object playerData){var p = (float)(playable.GetTime() / playable.GetDuration());//Debug.Log($"{featureName} - {p.ToString("F2")} , time:{playable.GetTime()} ,dur:{playable.GetDuration()}");}}

我们这时候可以在轨道上点击鼠标右键,就只能看到只有这个对象了。
在这里插入图片描述
在这里插入图片描述
OnBehaviourPlay进入clip就触发。
OnBehaviourPause出了clip就触发。
当然Pause在运行时候会触发一次。

当前滑块可以用playable.GetTime() / playable.GetDuration()的方式获得到百分比。

这种就是OnCreateClip的用法。
下面我们来看CreateTrackMixer的用法

CreateTrackMixer的用法

因为目前我没有用到需要Mixer的算法,可能认识上有点偏差,我的理解是Mixer就是如图
在这里插入图片描述
交叉的这部分,如果某个值需要混合可以按照自己的需求去计算数值,权重可以这样获取:

float inputWeight = playable.GetInputWeight(i);

我们先放上代码,然后再做对比。

首先是轨道

//FeatureMixerTrack.cs
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;[DisplayName("(FeatureMixer)开关轨道")]
[TrackClipType(typeof(FeatureMixerPlayableAsset))]
[TrackColor(0.53f, 0.0f, 0.08f)]//表示在编辑器中,Track轨道前端的标识颜色(不重要啦)
public class FeatureMixerTrack : TrackAsset
{public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount){var temp = ScriptPlayable<FeatureMixerPlayableBehaviour>.Create(graph, inputCount);temp.GetBehaviour().fixedData = "传入的数据";return temp;}}

这里调用了CreateTrackMixer的方法。

//FeatureMixerPlayableAsset.cs
using System;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;[DisplayName("(FeatureMixer)开关Clip")]
[Serializable]
public class FeatureMixerPlayableAsset : PlayableAsset
{public FeatureBehaviour template = new FeatureBehaviour();public ClipCaps clipCaps{get{return ClipCaps.Blending;}}public override Playable CreatePlayable(PlayableGraph graph, GameObject owner){return ScriptPlayable<FeatureBehaviour>.Create(graph, template);}
}[Serializable]
public class FeatureBehaviour : PlayableBehaviour
{public string featureName;  //开启某个featurepublic Material material;   //对应的材质球public AnimationCurve alphaCurve;   //修改某个参数[HideInInspector]public float passtime;  //计算当前块的播放进度[HideInInspector]public bool started;  //是否刚进入
}public class FeatureMixerPlayableBehaviour : PlayableBehaviour
{public string fixedData;// 当进入区域内触发Playpublic override void OnBehaviourPlay(Playable playable, FrameData info){Debug.Log("触发 OnBehaviourPlay");}// 当出了区域触发,或者开始的时候触发,或者停止运行的时候public override void OnBehaviourPause(Playable playable, FrameData info){int inputCount = playable.GetInputCount();for (int i = 0; i < inputCount; i++){ScriptPlayable<FeatureBehaviour> inputPlayable = (ScriptPlayable<FeatureBehaviour>)playable.GetInput(i);FeatureBehaviour input = inputPlayable.GetBehaviour();if (input.started){input.started = false;Debug.Log($"{input.featureName}出去了!!");}}}// 在区域内每个Frame地方都会触发public override void ProcessFrame(Playable playable, FrameData info, object playerData){int inputCount = playable.GetInputCount();for (int i = 0; i < inputCount; i++){ScriptPlayable<FeatureBehaviour> inputPlayable = (ScriptPlayable<FeatureBehaviour>)playable.GetInput(i);FeatureBehaviour input = inputPlayable.GetBehaviour();float inputWeight = playable.GetInputWeight(i);if (!Mathf.Approximately(inputWeight, 0f)){input.passtime += info.deltaTime;// maxTime 当前clip的时长float maxTime = (float)PlayableExtensions.GetDuration(playable.GetInput(i));// curTime 当前clip的执行到哪个时刻float nowValue = input.alphaCurve.Evaluate(input.passtime / maxTime);//Debug.Log("" + input.featureName + "," + (input.passtime / maxTime) + ",nowValue:" + nowValue);//更新材质的变量//input.material.SetFloat("xxxx", nowValue);if (!input.started){input.started = true;Debug.Log($"{input.featureName} 进入了");}}else{input.passtime = 0f;if (input.started){input.started = false;Debug.Log($"{input.featureName} 出去了");}}}}}

在这里插入图片描述

Mixer轨道在使用中发现和普通的轨道有区别:

函数OnBehaviourPlay和OnBehaviourPause失效

OnBehaviourPlay函数在TimeLine播放就执行了,并不会在clip进入才播放
OnBehaviourPause函数在整个TL播放结束才会进入。所以这两个函数失效了。

解决办法

我是这样解决的:
所以这里如果有进入和退出clip的时候要处理逻辑的,我研究可下加了两个变量来处理
started : 表示开始播放了
passtime :表示过去了多久

如果是Frame里的最后一帧刚好可能执行不到关闭,所以再OnBehaviourPause里也添加了结束.

具体就不描述了,参考代码中的ProcessFrame函数。

那么我们如果要处理每个clip,需要通过遍历来处理:

int inputCount = playable.GetInputCount();
for (int i = 0; i < inputCount; i++)

获取当前的有几个inputCount也是clip,然后遍历进行访问计算。

本文写道这里就结束,其实很多地方还没搞懂,例如ClipCaps设置为Blending后这个如何自定使用,后面有时间再研究吧。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AutoMQ 系统测试体系揭秘

01 前言 Apache Kafka 有着比较完备的自测体系。除了常规的单元测试和集成测试以外&#xff0c;Apache Kafka 还有着 1000 的“系统集成和性能测试”&#xff08;以下简称系统测试&#xff09;。系统测试会拉起一套真实的 Kafka 集群&#xff0c;并模拟用户使用 Kafka 集群的方…

《XXL_job技术文档》-分布式任务调度框架-双方式部署-tar.gz安装/docker安装

阿丹&#xff1a; 作为任务调度的使用&#xff0c;xxl_job是经常使用的&#xff0c;可以帮助程序员或者其他业务的定时任务变的可控。但是很多教程都是通过压缩包来进行运行和部署的&#xff0c;但是现在更多的都是将模块容器化。本文章一次性整理。 XXL-Job是一款开源的分布式…

计算机视觉大项目(1)-水果分级系统

项目来源&#xff1a;河北大学计算机视觉课程-杨老师. 一共有四个标题&#xff0c;本篇博客只完成前两问。 目录 实验目的: 实验内容&#xff1a; 实验步骤&#xff1a; 1.水果图像的分割 >掩膜图像Mask 是什么&#xff1f; >改进:去除反光部分的影响 2&#xf…

中颖51芯片学习10. Touch Key触摸按键功能

中颖51芯片学习10. Touch Key触摸按键功能 一、SH79F9476 资源介绍1. 特性2. 系统框图&#xff1a;3.准备环境 二、准备工具三、开发步骤1. 新建项目流程&#xff08;1&#xff09;新建工程&#xff08;2&#xff09;选择芯片和封装&#xff08;3&#xff09;触摸配置按键&…

【人工智能AI书籍】TensorFlow机器学习实战指南(推荐)

今天又来给大家推荐一本人工智能方面的书籍<TensorFlow机器学习实战指南>。TensorFlow是一个开源机器学习库。本书从TensorFlow的基础开始介绍&#xff0c;涉及变量、矩阵和各种数据源。之后&#xff0c;针对使用TensorFlow线性回归技术的实践经验进行详细讲解。后续章节…

Spark原理之Cache Table的工作原理及实现自动缓存重复表的思考

CACHE TABLE的能力 使用此语法&#xff0c;可以由用户自定义要缓存的结果集&#xff0c;实际上就是一个临时表&#xff0c;不过数据存储在Spark集群内部&#xff0c;由Application所分配的executors管理。 一旦定义了一个缓存表&#xff0c;就可以在SQL脚本中随处引用这个表名…

Java并发常见面试题总结(上)

什么是线程和进程? 何为进程? 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。 在 Java 中&#xff0c;当我们启动 main 函数时其实就是启动了一个 JVM 的进…

读懂一本书笔记

文章目录 引言 我是一个用读书改变自己生活的人01 会读书&#xff0c;更要会讲书复杂时代&#xff0c;阅读是大众反脆弱的武器你焦虑吗&#xff1f;如何从“单向度的人”变为“多向度的人”第一&#xff0c;读书是主动的学习方式第二&#xff0c;读书是有针对性的学习方式 讲书…

MAC 本地搭建Dify环境

Dify 介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过…

【VueUse】超越基本功能的高级 Vue 元素操作

在vue开发中我们经常需要操作DOM元素&#xff0c;从简单的添加类到动态创建元素&#xff0c;这些操作都是不可避免的。而在VueUse库中&#xff0c;Elements相关API函数为我们提供了一系列强大而灵活的工具&#xff0c;帮助我们更轻松地处理DOM元素。无论是优雅地处理元素、动态…

Three.js 的优势

Three.js 是一个非常流行的基于 WebGL 的 JavaScript 库&#xff0c;用于在浏览器中创建和展示 3D 内容。以下是 Three.js 的一些主要优势&#xff0c;这些优势使得 Three.js 成为创建和展示 3D 内容的强大工具&#xff0c;无论是对于初学者还是经验丰富的开发者。北京木奇移动…

如何在Linux上安装Python?2024Python安装教程

在Linux上安装Python并不难&#xff0c;对于Ubuntu或Debian系统&#xff0c;使用命令sudo apt install python3&#xff1b;对于CentOS、Red Hat或Fedora系统&#xff0c;使用命令sudo yum install python3。 如何在Linux上安装Python&#xff1f; 确切的安装步骤有所不同&am…