# setCallback not working 😀

**URL:** <https://qa.fmod.com/t/setcallback-not-working/20087>\
**Category:** Unity\
**Tags:** unity, csharp\
**Created:** [April 10, 2023, 1:10pm UTC](https://qa.fmod.com/t/setcallback-not-working/20087 "2023-04-10T13:10:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ZizoMass](https://avatars.discourse-cdn.com/v4/letter/z/bc8723/32.png) [@ZizoMass](https://qa.fmod.com/u/ZizoMass)\
**Post date:** [April 10, 2023, 1:10pm UTC](https://qa.fmod.com/t/setcallback-not-working/20087/1 "2023-04-10T13:10:03Z")

</div>

Hey guys,

I’m trying to use the setCallback function, but nothing I do seems to work. My timeline has two Destination Markers that should work to spawn an NPC when the dialogue reaches certain points. However, the NPC is never spawned, but I don’t get any errors or anything. I don’t even receive my debug log that I put inside FMOD.Studio.EVENT\_CALLBACK.

The worst part is that I spent so much time trying to make this work that at one point I just gave up and decided to use two Command Instruments to change a parameter and check the value of that parameter in Unity to spawn the NPC, but even the Command Instruments are not working and the parameter I made doesn’t change value. Is my timeline cursed or am I doing too many things wrong? Can someone help me with that?

Here is my code:

```auto
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FMODUnity;
using FMOD.Studio;
using System;
using System.Runtime.InteropServices;

public class F_Dialogue : MonoBehaviour
{
    class TimelineInfo
    {
        public FMOD.StringWrapper LastMarker = new FMOD.StringWrapper();
        public Warden warden;
    }

    TimelineInfo timelineInfo;
    GCHandle timelineHandle;

    FMOD.Studio.EVENT_CALLBACK markerCallback;

    public static F_Dialogue Instance { get; private set; }
    private EmoteManager emoteManager;
    private Transform camTransform; //where event instances are attached

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {
        emoteManager = GetComponent<EmoteManager>();
        camTransform = LocalReferenceManager.Instance.camHolder.transform;

        // Explicitly create the delegate object and assign it to a member so it doesn't get freed
        // by the garbage collector while it's being used
        markerCallback = new FMOD.Studio.EVENT_CALLBACK(HandleMarkerCallback);
    }

    public void PlayDialogue(DialogueDatabase _data, EventReference _reference, Warden _warden)
    {
        EventInstance _instance = RuntimeManager.CreateInstance(_reference);
        currentDiaEvent = _instance;
        RuntimeManager.AttachInstanceToGameObject(_instance, camTransform);

        if (_warden != null)
        {
            timelineInfo = new TimelineInfo
            {
                warden = _warden
            };

            // Pin the timelineInfo object in memory and pass a pointer through the user data
            timelineHandle = GCHandle.Alloc(timelineInfo);
            _instance.setUserData(GCHandle.ToIntPtr(timelineHandle));

            _instance.setCallback(markerCallback, FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER);
            Debug.Log("Callback set for warden");
        }

        emoteManager.QueueTimedEmotes(_data.emotes);

        PrintEventPath(_instance);

        _instance.start();
        StartCoroutine(WaitForSoundToFinish(_instance));
    }

    private IEnumerator WaitForSoundToFinish(EventInstance instance)
    {
        instance.getPlaybackState(out PLAYBACK_STATE state);
        while (state != PLAYBACK_STATE.STOPPED)
        {
            yield return new WaitForSeconds(0.1f);
            instance.getPlaybackState(out state);
        }
        instance.setUserData(IntPtr.Zero);
        instance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
        instance.release();
        timelineHandle.Free();
    }

    [AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
    static FMOD.RESULT HandleMarkerCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
    {
        FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);

        // Retrieve the user data
        IntPtr timelineInfoPtr;
        instance.getUserData(out timelineInfoPtr);

        if (timelineInfoPtr != IntPtr.Zero)
        {
            GCHandle timelineHandle = GCHandle.FromIntPtr(timelineInfoPtr);
            TimelineInfo timelineInfo = (TimelineInfo)timelineHandle.Target;

            if (type == FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER)
            {
                var data = (FMOD.Studio.TIMELINE_MARKER_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.TIMELINE_MARKER_PROPERTIES));
                timelineInfo.LastMarker = data.name;

                if (timelineInfo.LastMarker == "WardenIn")
            {
                timelineInfo.warden.SpawnWarden();
                Debug.Log("WardenIn");
            }
            else if (timelineInfo.LastMarker == "WardenOff")
            {
                timelineInfo.warden.DespawnWarden();
                Debug.Log("WardenOff");
            }

            Debug.Log("Callback triggered"); // Add this line to check if the callback is being triggered
        }
    }

    return FMOD.RESULT.OK;
}

private void PrintEventPath(EventInstance instance)
{
    instance.getDescription(out EventDescription eventDescription);
    eventDescription.getPath(out string eventPath);
    Debug.Log("Event path: " + eventPath);
}

```

---

<div class="post-metadata">

**Author:** ![Connor\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/connor_fmod/32/3685_2.png) [@Connor\_FMOD](https://qa.fmod.com/u/Connor_FMOD)\
**Post date:** [April 11, 2023, 4:25am UTC](https://qa.fmod.com/t/setcallback-not-working/20087/2 "2023-04-11T04:25:36Z")

</div>

Hi,

I was able to get the callback to trigger by slightly changing your code as follows:

> **Changed Code**
>
> ```auto
> using System.Collections;
> using System.Collections.Generic;
> using UnityEngine;
> using FMODUnity;
> using FMOD.Studio;
> using System;
> using System.Runtime.InteropServices;
> 
> public class F_Dialogue : MonoBehaviour
> {
> public FMODUnity.EventReference reference;
> 
> class TimelineInfo
> {
> public FMOD.StringWrapper LastMarker = new FMOD.StringWrapper();
> //public Warden warden;
> }
> 
> TimelineInfo timelineInfo;
> GCHandle timelineHandle;
> 
> FMOD.Studio.EVENT_CALLBACK markerCallback;
> 
> public static F_Dialogue Instance { get; private set; }
> //private EmoteManager emoteManager;
> public Transform camTransform; //where event instances are attached
> 
> private void Awake()
> {
> Instance = this;
> }
> 
> private void Start()
> {
> //emoteManager = GetComponent<EmoteManager>();
> //camTransform = LocalReferenceManager.Instance.camHolder.transform;
> 
> // Explicitly create the delegate object and assign it to a member so it doesn't get freed
> // by the garbage collector while it's being used
> markerCallback = new FMOD.Studio.EVENT_CALLBACK(HandleMarkerCallback);
> }
> 
> private void Update()
> {
> if (Input.GetKeyDown(KeyCode.Escape))
> {
> PlayDialogue(reference);
> 
> }
> }
> 
> public void PlayDialogue(/*DialogueDatabase _data*/ EventReference _reference)//, Warden _warden)
> {
> EventInstance _instance = RuntimeManager.CreateInstance(_reference);
> //currentDiaEvent = _instance;
> RuntimeManager.AttachInstanceToGameObject(_instance, camTransform);
> 
> //if (_warden != null)
> //{
> //timelineInfo = new TimelineInfo
> //{
> //	warden = _warden
> //};
> 
> // Pin the timelineInfo object in memory and pass a pointer through the user data
> //timelineHandle = GCHandle.Alloc(timelineInfo);
> //_instance.setUserData(GCHandle.ToIntPtr(timelineHandle));
> 
> _instance.setCallback(markerCallback, FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER);
> Debug.Log("Callback set for warden");
> //}
> 
> //emoteManager.QueueTimedEmotes(_data.emotes);
> 
> PrintEventPath(_instance);
> 
> _instance.start();
> StartCoroutine(WaitForSoundToFinish(_instance));
> }
> 
> private IEnumerator WaitForSoundToFinish(EventInstance instance)
> {
> instance.getPlaybackState(out PLAYBACK_STATE state);
> while (state != PLAYBACK_STATE.STOPPED)
> {
> yield return new WaitForSeconds(0.1f);
> instance.getPlaybackState(out state);
> }
> instance.setUserData(IntPtr.Zero);
> instance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
> instance.release();
> timelineHandle.Free();
> }
> 
> [AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
> static FMOD.RESULT HandleMarkerCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
> {
> FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);
> 
> // Retrieve the user data
> //IntPtr timelineInfoPtr;
> //instance.getUserData(out timelineInfoPtr);
> 
> //if (timelineInfoPtr != IntPtr.Zero)
> //{
> //	GCHandle timelineHandle = GCHandle.FromIntPtr(timelineInfoPtr);
> //	TimelineInfo timelineInfo = (TimelineInfo)timelineHandle.Target;
> 
> //	if (type == FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER)
> //	{
> // var data = (FMOD.Studio.TIMELINE_MARKER_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.TIMELINE_MARKER_PROPERTIES));
> // timelineInfo.LastMarker = data.name;
> 
> // if (timelineInfo.LastMarker == "WardenIn")
> // {
> // timelineInfo.warden.SpawnWarden();
> // Debug.Log("WardenIn");
> // }
> // else if (timelineInfo.LastMarker == "WardenOff")
> // {
> // timelineInfo.warden.DespawnWarden();
> // Debug.Log("WardenOff");
> // }
> 
> //	}
> //}
> 
> Debug.Log("Callback triggered"); // Add this line to check if the callback is being triggered
> return FMOD.RESULT.OK;
> }
> 
> private void PrintEventPath(EventInstance instance)
> {
> instance.getDescription(out EventDescription eventDescription);
> eventDescription.getPath(out string eventPath);
> Debug.Log("Event path: " + eventPath);
> }
> }
> 
> ```

I cannot see any issues with your code, would it be possible to see your FMOD Studio Event? I will link our Timeline Scripting Example here [Unity Integration | Scripting Examples - Timeline Callbacks](https://fmod.com/docs/2.02/unity/examples-timeline-callbacks.html). Hopefully, these will help.

---

<div class="post-metadata">

**Author:** ![ZizoMass](https://avatars.discourse-cdn.com/v4/letter/z/bc8723/32.png) [@ZizoMass](https://qa.fmod.com/u/ZizoMass)\
**Post date:** [April 12, 2023, 2:54am UTC](https://qa.fmod.com/t/setcallback-not-working/20087/3 "2023-04-12T02:54:47Z")

</div>

Hi Connor,

Thanks for your answer.

I used this exactly example to make my code. But, I coundn’t make it work or even figure out why it is not working

Here is the time line that I was doing my tests on. As you can I have the markers, and also the command instruments to try to change the global parameters. But unfortunately none of them worked.

 ![Captura de tela 2023-04-11 225320](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/e/e1747bdf33d088f73fb8242ee8a210f7c802f61f.png)

---

<div class="post-metadata">

**Author:** ![Connor\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/connor_fmod/32/3685_2.png) [@Connor\_FMOD](https://qa.fmod.com/u/Connor_FMOD)\
**Post date:** [April 12, 2023, 3:32am UTC](https://qa.fmod.com/t/setcallback-not-working/20087/4 "2023-04-12T03:32:18Z")

</div>

Hi,

On the line  
`_instance.setCallback(markerCallback, FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER);`  
Could we add some more `Callback Flags` to see if it is just not hitting the `Timeline Marker Callback`:  
`_instance.setCallback(markerCallback, FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER | EVENT_CALLBACK_TYPE.CREATED | EVENT_CALLBACK_TYPE.STARTING | EVENT_CALLBACK_TYPE.STARTED);`

Let me know how that goes.
