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:
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);
}