I hope this is the right group to post this in. I’m new to timeline so forgive me if this is a stupid question.
I am writing a 2D game with some hand-drawn art and I want to have “cut scenes” where I animate “paper puppets” and play an audio clip.
I created a PencilPowerPuppet object and added a sprite render, particle trail and audio source and I added a TimelineDirector to it. I animated the position and rotation and dragged an audio clip into the playable asset.

When I play the animation or play the game it works perfect.
But I want to have a collection of “puppets” and my intention is to play a random one from the collection when a level (scene) starts.
So I created a PuppetManager component.

I am using a singleton pattern for this PuppetManager because I will always have the same collection of puppets to choose from for every scene.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class PuppetManager : MonoBehaviour
{
[SerializeField] private List<GameObject> puppets = null;
[SerializeField] private float chanceToPlayPuppet = 25f;
private bool _puppetPlaying;
public static PuppetManager Instance;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(gameObject);
_puppetPlaying = false;
}
}
public void PlayRandomPuppet()
{
if (_puppetPlaying || Random.Range(0, 100) > chanceToPlayPuppet) return;
int index = Random.Range(0, puppets.Count - 1);
var puppet = puppets[index];
if (puppet == null)
{
Debug.Log($"Puppet[{index}] is null.");
return;
}
Debug.Log($"Playing puppet {puppet.name}");
_puppetPlaying = true;
puppet.SetActive(true);
StartCoroutine(StopPuppet(puppet));
}
private IEnumerator StopPuppet(GameObject puppet)
{
yield return new WaitForSeconds(5f);
if (puppet != null) puppet.SetActive(false);
_puppetPlaying = false;
}
}
I have a LevelController class that calls PuppetManager.Instance.PlayRandomPuppet() in OnEnable().
This plays a puppet when starting a level:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
[RequireComponent(typeof(AudioSource))]
public class LevelController : MonoBehaviour
{
[SerializeField] private string _nextLevelName = null;
[SerializeField] private AudioClip _nextLevelSound = null;
private Monster[] _monsters;
private AudioSource _audioSource;
private bool _levelComplete;
private void Start()
{
_audioSource = GetComponent<AudioSource>();
}
private void OnEnable()
{
_levelComplete = false;
_monsters = FindObjectsOfType<Monster>();
MusicManager.Instance.PlayNextSong();
PuppetManager.Instance.PlayRandomPuppet();
}
// Update is called once per frame
void Update()
{
if (MonstersAreAllDead())
{
_audioSource.PlayOneShot(_nextLevelSound);
StartCoroutine(GoToNextLevel());
}
}
private bool MonstersAreAllDead()
{
if (_levelComplete) return false;
foreach (var monster in _monsters)
{
if (monster.gameObject.activeSelf)
return false;
}
_levelComplete = true;
return true;
}
private IEnumerator GoToNextLevel()
{
yield return new WaitForSeconds(1);
SceneManager.LoadScene(_nextLevelName);
}
}
Whenever the scene changes, the puppet I get from the collection is null.
Puppet[0] is null.
UnityEngine.Debug:Log (object)
PuppetManager:PlayRandomPuppet () (at Assets/Scripts/PuppetManager.cs:36)
LevelController:OnEnable () (at Assets/Scripts/LevelController.cs:34)
I only ever change the active state of the puppet game object so how is it getting destroyed? Shouldn’t it get preserved since it’s contained by the Singleton DontDestroyOnLoad PuppetManager?
I don’t have this issue with my MusicManager which uses the same pattern so the Timeline is the only difference I can think of.
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class MusicManager : MonoBehaviour
{
[SerializeField] private List<AudioClip> musicClips = null;
public static MusicManager Instance;
private AudioSource _audioSource;
private int _currentSong = -1;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(gameObject);
_audioSource = GetComponent<AudioSource>();
_currentSong = 0;
}
}
private void PlaySong(int clipIndex)
{
_audioSource.clip = musicClips[clipIndex];
_audioSource.Play();
}
public void PlayNextSong()
{
if (++_currentSong >= musicClips.Count)
_currentSong = 0;
PlaySong(_currentSong);
}
}
Could the timeline somehow be destroying the puppet after animating it?
Thanks in advance!!!


