Setup Toggle Animation start button for LKCNHMViewer

A. Objective
Requires to create a toggle button to allow dinosaur animation to play by user. Otherwise the Dino animation will need to pause by default at around 2 second mark

B. Steps

  1. Step 1 Setup a unity timeline marker
    A marker need to be defined and placed at around 2 second timeline to let script control play and pause

a) Setup TimeMarker.cs Script

using UnityEngine; using UnityEngine.Timeline;   [CustomStyle("TimeMarker")] public class TimeMarker : Marker  { } 

b) Unity Editor Task

(1) Create Marker
Note: Only when the above TimeMarker class has been created, the drop down on the timeline will appears

i) Marker in Unity Timeline

  1. Step 2 Setup default animation pause

a) Using script to find marker created

(1) Define a gameObject for playable director

private GameObject playabledirectorObj; 

(2) Locate and assign the playableDirectorObj by find by Tag at Start()

 playabledirectorObj = GameObject.FindGameObjectWithTag("DinoSceneDir"); 

(3) Find PlayableDirector component

playabledirector = playabledirectorObj.GetComponent<PlayableDirector>(); 

(4) Find Timeline in the component

TimelineAsset timeline = (TimelineAsset)playabledirector.playableAsset; 

(5) Finally Obtain the marker in the Timeline

timeMarker = (Marker)timeline.markerTrack.GetMarker(0); 

b) Setup conditions to pause animation on default

(1) Create a bool variable to check if the PlayAnimation button is on or off

private bool playDinoAnimation; 

Set the variable as false when when the script starts

playDinoAnimation = false; ```

(2) In the Update() set the condition to pause the animation by the marker found 
```csharp        void Update()     {              if (playDinoAnimation == false)             {                  if (timeMarker.time == (int)playabledirector.time)                 {                     playabledirector.Pause();                 }            }     } 

i) Issues and solution

(a) The Time by the marker is an int and the director.time will be double. Hence cannot find the time both numbers are equal
Solution: Simple solution to cast the double value of the playableDirector.time is used

(b) The Lighting in the dinosaur is different when paused

  1. Step 3 Setup Toggle button

a) Unity editor Task

(1) Toggle Setup
Set up the toggle button

i) Unity Toggle Setup

b) Accessing the toggle button by script

(1) Issues and solutions

i) When toggle button is initially disabled, it is not possible to find by tag in the unity script to locate
Solution: Setup Event system to access the DinoAnimToggle

(2) Setup Event to access the toggle gameObject

i) 1. Event Broker – EventBroker.cs

using System; using UnityEngine;  public class EventBroker {      public static event Action<GameObject> onOpenDinoAnimToggle = delegate { };      public static void CallonOpenDinoAnimToggle(GameObject g)     {         if (onOpenDinoAnimToggle != null)             onOpenDinoAnimToggle(g);     }  } 

ii) 2. Publisher – DinoPlayController.cs

public class DinoPlayController : MonoBehaviour  {     private void Awake()     {         EventBroker.CallonOpenDinoAnimToggle(this.gameObject);     } } 

When the Prefab is loaded and the script is activated
Fire up the CallonOpenDinoAnimToggle Event

iii) 3. Receiver – DisplayToggle.cs

using System.Collections; using System.Collections.Generic; using UnityEngine;  public class DisplayToggle : MonoBehaviour {      public GameObject DisplayDinoAnimToggle;      void Awake()     {         EventBroker.onOpenDinoAnimToggle += DinoAnimToggle;     }      private void DinoAnimToggle(GameObject g)     {         if(DisplayDinoAnimToggle != null)         {             DisplayDinoAnimToggle.SetActive(true);         }     } } ```
Subscribe to the onOpenDinoAnimToggle event 
Then display the assigned DinoAnimToggle

C.  Asset Listing 

1.  Scripts 

a)  TimeMarker.cs 

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Timeline; using UnityEngine.Playables;  [CustomStyle("TimeMarker")] public class TimeMarker : Marker  //, INotification {     //public PropertyName id { get; } } 

b) DinoPlayController.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; using UnityEngine.UI;  public class DinoPlayController : MonoBehaviour //,INotificationReceiver {      private GameObject playabledirectorObj;     private GameObject dinoAnimToggleObj;          private bool playDinoAnimation;     private PlayableDirector playabledirector;     private Playable timelinePlayable;     private Marker timeMarker;       private void Awake()     {         EventBroker.CallonOpenDinoAnimToggle(this.gameObject);     }       void Start()     {         //D.log("DinoPlayControl Start is called");         playabledirectorObj = GameObject.FindGameObjectWithTag("DinoSceneDir");         //D.log("Geting dinoSceneDir should be found: " + playabledirectorObj.name);          playabledirector = playabledirectorObj.GetComponent<PlayableDirector>();         //D.log("Geting playable director time: " + playabledirector.time);          TimelineAsset timeline = (TimelineAsset)playabledirector.playableAsset;         //D.log("Geting markerTrack is empty? " + timeline.markerTrack.isEmpty + "The count is: " + timeline.markerTrack.GetMarkerCount());                  timeMarker = (Marker)timeline.markerTrack.GetMarker(0);          //D.log("The  marker time is: " + timeMarker.time);          playDinoAnimation = false;         dinoAnimToggleObj = GameObject.FindGameObjectWithTag("DinoAnimToggle");         Toggle dinoAnimToggle = dinoAnimToggleObj.GetComponent<Toggle>();         dinoAnimToggle.onValueChanged.AddListener(delegate         {             DinoAnimToggleValueChanged(dinoAnimToggle);         });     }      void Update()     {          D.log("playDinoAnimation is: " + playDinoAnimation);              if (playDinoAnimation == false)             {             //D.log("Should be running at playDinoAnimation");             D.log("Playabledirector time: " + playabledirector.time);             D.log("timeMarker time: " + timeMarker.time);                 if (timeMarker.time == (int)playabledirector.time)                 {                     D.log("Calling to pause is activated:");                     playabledirector.Pause();                 }            }     }      void DinoAnimToggleValueChanged(Toggle change)     {          if (playDinoAnimation)         {             //set the playDinoAnimation to false             playDinoAnimation = false;             D.log("The toggle is pressed off");             //set the animation to the pause frame             playabledirector.time = timeMarker.time;            // playabledirector.GetComponent<Playable>().SetTime(timeMarker.time);             playabledirector.Pause();          } else         {             //set the playDinoAnimation to true              playDinoAnimation = true;             D.log("The toogle is pressed on");             //Start play the animation in loop             playabledirector.Play();         }     }      //public void OnNotify(Playable origin, INotification notification, object context)     //{     //    timeMarker = notification as TimeMarker;     //    if (timeMarker == null) return;      //    Playable timelinePlayable = origin.GetGraph().GetRootPlayable(0);       //} } 

c) DisplayToggle.cs

using System.Collections; using System.Collections.Generic; using UnityEngine;  public class DisplayToggle : MonoBehaviour {      public GameObject DisplayDinoAnimToggle;      void Awake()     {         EventBroker.onOpenDinoAnimToggle += DinoAnimToggle;     }      private void DinoAnimToggle(GameObject g)     {         if(DisplayDinoAnimToggle != null)         {             DisplayDinoAnimToggle.SetActive(true);         }     } }   ```

2.  Logics 

a)  Event to control the toggle display button 

b)  Find by Tag to locate the playabledirector 

c)  Requires to find playabledirectorObj > playable director > Timeline > Marker 

3.  Libraries 

a)  using UnityEngine.Playables; 

b)  using UnityEngine.Timeline;