【Unity】创建自定义Playable,使用Timeline控制Particle System的参数

本文详细介绍如何使用Unity的Timeline系统控制粒子系统的开始颜色。通过创建自定义Playable,包括ParticleBehaviour、ParticleClip、ParticleMixerBehviour、ParticleTrack和ParticleDrawer等脚本,实现对粒子系统的StartColor参数的动态控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Timeline功能强大,但可控的参数还是较少,官方提供了自定义编写Playable的方法,用于扩展Timeline,使其更加强大。

上一篇我们介绍了一些官方发布到Asset Store上的免费Playable,我们以其为模板,创建自己的Playable。

 

官方的例子提供了控制Text,Light,等。我们来尝试控制下Particle,粒子系统。

根据这个模板,我们可以进行扩展,进而可以使用Timeline控制粒子系统的任意参数

 

本篇目标:

通过Timeline控制粒子系统的StartColor,即

 

我们需要创建如下五个脚本

 Drawer用来绘制,ParticleClip在Inspector中的颜色块,粒子将会根据这个颜色块更改颜色

在ParticleBehaivour中,定义要更改的变量

几个脚本的代码内容如下:

ParticleBehaivour:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

[Serializable]
public class ParticleBehaviour : PlayableBehaviour
{
    public Color p_startColor = Color.white;
}

ParticleClip.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline;
using UnityEngine.Playables;
using System;

[Serializable]
public class ParticleClip : PlayableAsset , ITimelineClipAsset
{

    public ParticleBehaviour templete = new ParticleBehaviour();

    public ClipCaps clipCaps {
        get { return ClipCaps.Blending; }
    }

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner) {
        var playable = ScriptPlayable<ParticleBehaviour>.Create(graph, templete);
        return playable;
    }
}

ParticleMixerBehviour.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class ParticleMixerBehviour : PlayableBehaviour
{
    Color m_DefaultColor;

    ParticleSystem m_TrackBinding;
    bool m_firstFrameHappened;

    public override void ProcessFrame(Playable playable, FrameData info, object playerData) {

        m_TrackBinding = playerData as ParticleSystem;

        if (m_TrackBinding == null)
            return;

        if (!m_firstFrameHappened) {
            //
            var p_main = m_TrackBinding.main;
            m_DefaultColor = p_main.startColor.color;

            m_firstFrameHappened = true;
        }

        int inputCount = playable.GetInputCount();

        Color blendedColor = Color.clear;
        float totalWeight = 0f;
        float greatestWeight = 0f;
        int currentInputs = 0;

        for(int i = 0; i < inputCount; i++) {
            float inputWeight = playable.GetInputWeight(i);
            ScriptPlayable<ParticleBehaviour> inputPlayable = (ScriptPlayable<ParticleBehaviour>)playable.GetInput(i);
            ParticleBehaviour input = inputPlayable.GetBehaviour();

            blendedColor += input.p_startColor * inputWeight;
            totalWeight += inputWeight;

            if (inputWeight > greatestWeight) {
                greatestWeight = inputWeight;
            }

            if (!Mathf.Approximately(inputWeight, 0))
                currentInputs++;
        }

        var main = m_TrackBinding.main;
        main.startColor = blendedColor + m_DefaultColor * (1f - totalWeight);
        
    }

    public override void OnPlayableDestroy(Playable playable) {

        m_firstFrameHappened = false;
        if (m_TrackBinding == null)
            return;

        var main = m_TrackBinding.main;
        main.startColor = m_DefaultColor;
    }

}

ParticleTrack.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

[TrackColor(0.35f,0.97f,0.64f)]
[TrackClipType(typeof(ParticleClip))]
[TrackBindingType(typeof(ParticleSystem))]
public class ParticleTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) {
        return ScriptPlayable<ParticleMixerBehviour>.Create(graph, inputCount);
    }

    public override void GatherProperties(PlayableDirector director, IPropertyCollector driver) {
#if UNITY_EDITOR
        ParticleSystem trackBinding = director.GetGenericBinding(this) as ParticleSystem;
        if (trackBinding == null)
            return;

        var serializedObject = new UnityEditor.SerializedObject(trackBinding);
        var iterator = serializedObject.GetIterator();
        while (iterator.NextVisible(true)) {
            if (iterator.hasVisibleChildren)
                continue;

            //driver.AddFromName<ParticleSystem>(trackBinding.gameObject, iterator.propertyPath);
        }
#endif
        base.GatherProperties(director, driver);
    }
}

ParticleDrawer.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(ParticleBehaviour))]
public class ParticleDrawer : PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
        int fieldCount = 1;
        return fieldCount * EditorGUIUtility.singleLineHeight;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        SerializedProperty colorProp = property.FindPropertyRelative("p_startColor");

        Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        EditorGUI.PropertyField(singleFieldRect, colorProp);
    }
}

 

创建如上脚本,粘贴以上代码,即可在Timeline中创建相应轨道。拖拽任意物体到Timeline中,也可创建Particle轨道

 

 

源码在这:

https://download.youkuaiyun.com/download/u011643463/11268727

同篇笔记(这里也能下到源码,万恶资本主义,我没法在本站上传0积分资源)

http://note.youdao.com/noteshare?id=28beb40d88f30e41af212c72e8de1d8f&sub=432815D8787545BB9FE0B1E57067AB99

### 使用 Unity Timeline 进行 2D 游戏开发 在 Unity 中,Timeline 是一种强大的工具,用于创建复杂的动画序列、过场动画以及动态的游戏事件。以下是关于如何利用 Timeline 功能来增强 2D 游戏开发的具体方法: #### 创建和配置 Timeline 资源 要开始使用 Timeline,在 Unity 编辑器中通过 `Assets -> Create -> Timeline Asset` 来创建一个新的 Timeline 文件[^1]。随后将其拖拽到场景中的任意 GameObject 上,并附加 `Playable Director` 组件以便控制播放。 #### 添加轨道 (Tracks) 每条 Track 可以承载不同类型的剪辑 (Clips),例如 Animation Clips 或 Audio Clips。对于 2D 开发而言,通常会涉及 Sprite 动画或者 UI 的变化效果。右键点击空白区域选择合适的 Clip 类型即可完成添加操作[^2]。 #### 制作角色对话或剧情触发机制 借助 Signal Assets 和 Scriptable Objects 技术,可以实现当特定时间点到达时发送信号给其他脚本逻辑的功能。比如让 NPC 发言结束后自动开启玩家移动权限等功能都可以轻松达成[^3]。 ```csharp using UnityEngine; using UnityEngine.Timeline; public class ExampleSignalReceiver : MonoBehaviour, ISignalReceiver { public void ReceiveSignal(Signal signal){ Debug.Log("Received a signal!"); } } ``` 上述代码片段展示了如何定义接收者类去响应来自 TimeLine 的自定义信号消息。 #### 整合音效与视觉特效 为了提升用户体验感,可以在关键时刻加入背景音乐切换或是粒子系统爆发等元素作为辅助表现手法之一。只需简单地把对应的音频文件或者是预制好的 Particle System 放置进相应位置上的新建立轨之中就可以了[^4]。 #### 测试优化性能 最后一步就是反复运行项目并调整各项参数直至达到理想状态为止。注意观察帧率波动情况以及其他可能影响最终成品质量的因素。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值