You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity中如何用脚本停止Playable Director(Timeline)?多Timeline控制排障

问题排查与修复方案

看起来你在Unity中用脚本控制Timeline时遇到了Stop()无效的问题,我帮你拆解下代码里的关键问题,然后给出可行的修复方案:

1. TimelineStopper组件的核心问题

你的TimelineStopper类里的thisPd是public字段,但如果没在Unity Inspector面板里把对应的PlayableDirector拖拽赋值给它,调用Stop()thisPd就是null,根本没法触发停止操作——这大概率是Stop无效的直接原因。

2. 冗余组件与低效查找的问题

其实你完全不需要额外的TimelineStopper组件,因为你已经维护了playableDirectors列表来管理所有Timeline的控制器。GameObject.Find()不仅每次调用都会遍历整个场景(性能差),还容易因为物体改名、禁用等情况找不到目标,非常不可靠。

3. 切换逻辑的顺序错误

当前PlayTimelines()是先播放新Timeline,再停止旧的,这会导致两个Timeline可能同时运行;如果旧Timeline已经播放完毕,Stop()调用自然也不会有任何效果。正确的顺序应该是先停当前,再播新的


修复后的完整代码

TimelineController.cs

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

public class TimelineController : MonoBehaviour
{
    public List<PlayableDirector> playableDirectors;
    public int currIndex = 0; // 合并冗余的index字段,直接用currIndex记录当前播放项

    private void Awake()
    {
        // 基础空值与索引检查,避免启动时出错
        if (playableDirectors != null && playableDirectors.Count > 0 && currIndex >= 0 && currIndex < playableDirectors.Count)
        {
            playableDirectors[currIndex].Play();
        }
    }

    private void Update()
    {
        if (Input.GetKeyUp(KeyCode.K))
        {
            if (currIndex < playableDirectors.Count - 1)
            {
                SwitchTimeline(currIndex + 1);
            }
            else
            {
                Debug.Log("已经是最后一段Timeline啦");
                // 要是想循环到开头,就把上面的Debug换成 SwitchTimeline(0);
            }
        }

        if (Input.GetKeyUp(KeyCode.J))
        {
            if (currIndex > 0)
            {
                SwitchTimeline(currIndex - 1);
            }
            else
            {
                Debug.Log("已经是第一段Timeline啦");
            }
        }
    }

    // 封装切换逻辑,更清晰
    private void SwitchTimeline(int newIndex)
    {
        // 先停止当前正在播放的Timeline
        var currentPd = playableDirectors[currIndex];
        if (currentPd.state == PlayState.Playing)
        {
            currentPd.Stop();
            currentPd.time = 0; // 重置到开头,方便下次播放
        }

        // 播放新的Timeline
        playableDirectors[newIndex].Play();
        currIndex = newIndex;
    }
}

直接删除TimelineStopper.cs

现在我们直接通过playableDirectors列表管理所有控制器,这个冗余组件完全不需要了。


最后要注意的点

  • 一定要在Unity Inspector面板里,把场景中所有需要控制的PlayableDirector实例按顺序添加到playableDirectors列表里。
  • 如果你的Timeline设置了循环播放,Stop()后记得重置time为0,不然下次播放会从上次停止的位置继续。
  • 代码里加了基础的空值和索引检查,能避免不少运行时的空引用错误。

内容的提问来源于stack exchange,提问作者arrddon

火山引擎 最新活动