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

2 篇文章 0 订阅
1 篇文章 0 订阅

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.csdn.net/download/u011643463/11268727

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

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

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值