PrefabControlPlayable.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. using System;
  2. using UnityEngine.Playables;
  3. using UnityEngine.SceneManagement;
  4. namespace UnityEngine.Timeline
  5. {
  6. /// <summary>
  7. /// Playable that controls and instantiates a Prefab.
  8. /// </summary>
  9. public class PrefabControlPlayable : PlayableBehaviour
  10. {
  11. GameObject m_Instance;
  12. #if UNITY_EDITOR
  13. private bool m_IsActiveCached;
  14. #endif
  15. /// <summary>
  16. /// Creates a Playable with a PrefabControlPlayable behaviour attached
  17. /// </summary>
  18. /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
  19. /// <param name="prefabGameObject">The prefab to instantiate from</param>
  20. /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
  21. /// <returns>Returns a Playabe with PrefabControlPlayable behaviour attached.</returns>
  22. public static ScriptPlayable<PrefabControlPlayable> Create(PlayableGraph graph, GameObject prefabGameObject, Transform parentTransform)
  23. {
  24. if (prefabGameObject == null)
  25. return ScriptPlayable<PrefabControlPlayable>.Null;
  26. var handle = ScriptPlayable<PrefabControlPlayable>.Create(graph);
  27. handle.GetBehaviour().Initialize(prefabGameObject, parentTransform);
  28. return handle;
  29. }
  30. /// <summary>
  31. /// The instance of the prefab created by this behaviour
  32. /// </summary>
  33. public GameObject prefabInstance
  34. {
  35. get { return m_Instance; }
  36. }
  37. /// <summary>
  38. /// Initializes the behaviour with a prefab and parent transform
  39. /// </summary>
  40. /// <param name="prefabGameObject">The prefab to instantiate from</param>
  41. /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
  42. /// <returns>The created instance</returns>
  43. public GameObject Initialize(GameObject prefabGameObject, Transform parentTransform)
  44. {
  45. if (prefabGameObject == null)
  46. throw new ArgumentNullException("Prefab cannot be null");
  47. if (m_Instance != null)
  48. {
  49. Debug.LogWarningFormat("Prefab Control Playable ({0}) has already been initialized with a Prefab ({1}).", prefabGameObject.name, m_Instance.name);
  50. }
  51. else
  52. {
  53. #if UNITY_EDITOR
  54. if (!Application.isPlaying)
  55. {
  56. m_Instance = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefabGameObject, parentTransform);
  57. UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabUpdated;
  58. }
  59. else
  60. #endif
  61. {
  62. m_Instance = Object.Instantiate(prefabGameObject, parentTransform, false);
  63. }
  64. m_Instance.name = prefabGameObject.name + " [Timeline]";
  65. m_Instance.SetActive(false);
  66. SetHideFlagsRecursive(m_Instance);
  67. }
  68. return m_Instance;
  69. }
  70. /// <summary>
  71. /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
  72. /// </summary>
  73. /// <param name="playable">The playable this behaviour is attached to.</param>
  74. public override void OnPlayableDestroy(Playable playable)
  75. {
  76. if (m_Instance)
  77. {
  78. if (Application.isPlaying)
  79. Object.Destroy(m_Instance);
  80. else
  81. Object.DestroyImmediate(m_Instance);
  82. }
  83. #if UNITY_EDITOR
  84. UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabUpdated;
  85. #endif
  86. }
  87. /// <summary>
  88. /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
  89. /// </summary>
  90. /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
  91. /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
  92. public override void OnBehaviourPlay(Playable playable, FrameData info)
  93. {
  94. if (m_Instance == null)
  95. return;
  96. m_Instance.SetActive(true);
  97. #if UNITY_EDITOR
  98. m_IsActiveCached = true;
  99. #endif
  100. }
  101. /// <summary>
  102. /// This function is called when the Playable play state is changed to PlayState.Paused.
  103. /// </summary>
  104. /// <param name="playable">The playable this behaviour is attached to.</param>
  105. /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
  106. public override void OnBehaviourPause(Playable playable, FrameData info)
  107. {
  108. // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
  109. // the effectivePlayState will test if the pause is due to the clip being out of bounds
  110. if (m_Instance != null && info.effectivePlayState == PlayState.Paused)
  111. {
  112. m_Instance.SetActive(false);
  113. #if UNITY_EDITOR
  114. m_IsActiveCached = false;
  115. #endif
  116. }
  117. }
  118. #if UNITY_EDITOR
  119. void OnPrefabUpdated(GameObject go)
  120. {
  121. if (go == m_Instance)
  122. {
  123. SetHideFlagsRecursive(go);
  124. go.SetActive(m_IsActiveCached);
  125. }
  126. }
  127. #endif
  128. static void SetHideFlagsRecursive(GameObject gameObject)
  129. {
  130. if (gameObject == null)
  131. return;
  132. gameObject.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
  133. if (!Application.isPlaying)
  134. gameObject.hideFlags |= HideFlags.HideInHierarchy;
  135. foreach (Transform child in gameObject.transform)
  136. {
  137. SetHideFlagsRecursive(child.gameObject);
  138. }
  139. }
  140. }
  141. }