Feat : Wwise Integration
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Version 2020.1.0
|
||||
|
||||
- First official version as a package
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e53c4208d1bb76344b63835128764171
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54dbbf00c47566848857bba52bbb977c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "AK.Wwise.Unity.Timeline.Editor",
|
||||
"references": [
|
||||
"AK.Wwise.Unity.API",
|
||||
"AK.Wwise.Unity.Timeline",
|
||||
"Unity.Timeline",
|
||||
"AK.Wwise.Unity.API.Editor",
|
||||
"AK.Wwise.Unity.API.WwiseTypes",
|
||||
"AK.Wwise.Unity.ProjectDatabase",
|
||||
"AK.Wwise.Unity.Utilities"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [ "!UNITY_SERVER" ],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.timeline",
|
||||
"expression": "1.1.0",
|
||||
"define": "AK_ENABLE_TIMELINE"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afb7912e1ef1fdd4fa3c921dad99c7d2
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,212 @@
|
||||
#if UNITY_EDITOR
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
[UnityEditor.CustomEditor(typeof(AkEventPlayable))]
|
||||
public class AkEventPlayableInspector : UnityEditor.Editor
|
||||
{
|
||||
private AkEventPlayable m_AkEventPlayable;
|
||||
private UnityEditor.SerializedProperty akEvent;
|
||||
private UnityEditor.SerializedProperty emitterObjectRef;
|
||||
private UnityEditor.SerializedProperty retriggerEvent;
|
||||
private UnityEditor.SerializedProperty UseWwiseEventDuration;
|
||||
private UnityEditor.SerializedProperty StopEventAtClipEnd;
|
||||
private UnityEditor.SerializedProperty blendInCurve;
|
||||
private UnityEditor.SerializedProperty blendOutCurve;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
m_AkEventPlayable = target as AkEventPlayable;
|
||||
if (m_AkEventPlayable == null)
|
||||
return;
|
||||
|
||||
akEvent = serializedObject.FindProperty("akEvent");
|
||||
emitterObjectRef = serializedObject.FindProperty("emitterObjectRef");
|
||||
retriggerEvent = serializedObject.FindProperty("retriggerEvent");
|
||||
UseWwiseEventDuration = serializedObject.FindProperty("UseWwiseEventDuration");
|
||||
StopEventAtClipEnd = serializedObject.FindProperty("StopEventAtClipEnd");
|
||||
blendInCurve = serializedObject.FindProperty("blendInCurve");
|
||||
blendOutCurve = serializedObject.FindProperty("blendOutCurve");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
UnityEditor.EditorGUILayout.HelpBox(AkUnitySoundEngine.Deprecation_2019_2_0, UnityEditor.MessageType.Warning);
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(akEvent, new UnityEngine.GUIContent("Event: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(emitterObjectRef, new UnityEngine.GUIContent("Override Track Object: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(blendInCurve);
|
||||
UnityEditor.EditorGUILayout.PropertyField(blendOutCurve);
|
||||
}
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(UseWwiseEventDuration, new UnityEngine.GUIContent("Use Wwise Event Duration: ", "The clip duration is set to the duration of the Wwise Event"));
|
||||
|
||||
if (!UpdateClipInformation(m_AkEventPlayable.owningClip, m_AkEventPlayable.akEvent, serializedObject, UseWwiseEventDuration.boolValue))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.HelpBox(string.Format("The duration of the Wwise event \"{0}\" has not been determined. Playback for this event may be inconsistent. " +
|
||||
"Ensure that the event is associated with a generated SoundBank!", m_AkEventPlayable.akEvent.Name), UnityEditor.MessageType.Warning);
|
||||
}
|
||||
|
||||
if (!UseWwiseEventDuration.boolValue)
|
||||
{
|
||||
var StopEventAtClipEndValue = StopEventAtClipEnd.boolValue;
|
||||
var retriggerEventValue = retriggerEvent.boolValue;
|
||||
|
||||
UnityEditor.EditorGUILayout.PropertyField(StopEventAtClipEnd, new UnityEngine.GUIContent("Stop Event At End of clip: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(retriggerEvent, new UnityEngine.GUIContent("Loop: ", "When checked, an event will loop until the end of the clip."));
|
||||
|
||||
if (retriggerEvent.boolValue && !StopEventAtClipEnd.boolValue)
|
||||
{
|
||||
if (!retriggerEventValue)
|
||||
StopEventAtClipEnd.boolValue = true;
|
||||
else if (StopEventAtClipEndValue)
|
||||
retriggerEvent.boolValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private static void UpdateProgressBar(int index, int count)
|
||||
{
|
||||
float progress = (float)index / count;
|
||||
UnityEditor.EditorUtility.DisplayProgressBar("Wwise Integration", "Fixing clip durations of AkEventPlayables...", progress);
|
||||
}
|
||||
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
public static void SetupSoundbankSetting()
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string[] settingsToEnable = { "SoundBankGenerateEstimatedDuration" };
|
||||
AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToEnable, AkWwiseEditorSettings.WwiseProjectAbsolutePath, true);
|
||||
|
||||
UnityEditor.EditorApplication.delayCall += UpdateAllClips;
|
||||
WwiseProjectDatabase.SoundBankDirectoryUpdated += UpdateAllClips;
|
||||
}
|
||||
|
||||
private static void UpdateAllClips()
|
||||
{
|
||||
var guids = UnityEditor.AssetDatabase.FindAssets("t:AkEventPlayable", new[] { "Assets" });
|
||||
if (guids.Length < 1)
|
||||
return;
|
||||
|
||||
var processedGuids = new System.Collections.Generic.HashSet<string>();
|
||||
|
||||
for (var i = 0; i < guids.Length; i++)
|
||||
{
|
||||
UpdateProgressBar(i, guids.Length);
|
||||
|
||||
var guid = guids[i];
|
||||
if (processedGuids.Contains(guid))
|
||||
continue;
|
||||
|
||||
processedGuids.Add(guid);
|
||||
|
||||
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
|
||||
var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
|
||||
var instanceIds = new System.Collections.Generic.List<int>();
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
var id = obj.GetInstanceID();
|
||||
if (!instanceIds.Contains(id))
|
||||
instanceIds.Add(id);
|
||||
}
|
||||
|
||||
for (; instanceIds.Count > 0; instanceIds.RemoveAt(0))
|
||||
{
|
||||
var id = instanceIds[0];
|
||||
objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (obj && obj.GetInstanceID() == id)
|
||||
{
|
||||
var playable = obj as AkEventPlayable;
|
||||
if (playable)
|
||||
{
|
||||
var serializedObject = new UnityEditor.SerializedObject(playable);
|
||||
var setClipDuration = serializedObject.FindProperty("UseWwiseEventDuration").boolValue;
|
||||
UpdateClipInformation(playable.owningClip, playable.akEvent, serializedObject, setClipDuration);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnityEditor.EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The minimum clip duration. This value is set to 1/60 of a second which generally represents the time of 1 frame.
|
||||
/// </summary>
|
||||
private const double MinimumDurationInSeconds = 1.0 / 60;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the associated clip information and the event durations.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the Wwise event is found in the project data.</returns>
|
||||
private static bool UpdateClipInformation(UnityEngine.Timeline.TimelineClip clip, AK.Wwise.Event akEvent,
|
||||
UnityEditor.SerializedObject serializedObject, bool setClipDuration)
|
||||
{
|
||||
var clipDuration = MinimumDurationInSeconds;
|
||||
var eventInfo = AkWwiseProjectInfo.GetData().GetEventInfo(akEvent.Id);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
serializedObject.FindProperty("eventDurationMin").floatValue = eventInfo.minDuration;
|
||||
serializedObject.FindProperty("eventDurationMax").floatValue = eventInfo.maxDuration;
|
||||
|
||||
if (eventInfo.maxDuration > clipDuration)
|
||||
clipDuration = eventInfo.maxDuration;
|
||||
}
|
||||
|
||||
if (clip != null)
|
||||
{
|
||||
clip.displayName = akEvent.Name;
|
||||
if (setClipDuration)
|
||||
clip.duration = clipDuration;
|
||||
}
|
||||
|
||||
return eventInfo != null && eventInfo.maxDuration > 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif //#if UNITY_EDITOR
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff92923f2cfbd80408fa03c377c7b09c
|
||||
@@ -0,0 +1,87 @@
|
||||
#if UNITY_EDITOR
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
[UnityEditor.CustomEditor(typeof(AkRTPCPlayable))]
|
||||
public class AkRTPCPlayableInspector : UnityEditor.Editor
|
||||
{
|
||||
private UnityEditor.SerializedProperty Behaviour;
|
||||
private UnityEditor.SerializedProperty overrideTrackObject;
|
||||
private AkRTPCPlayable playable;
|
||||
private UnityEditor.SerializedProperty RTPCObject;
|
||||
private UnityEditor.SerializedProperty setRTPCGlobally;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
playable = target as AkRTPCPlayable;
|
||||
|
||||
setRTPCGlobally = serializedObject.FindProperty("setRTPCGlobally");
|
||||
overrideTrackObject = serializedObject.FindProperty("overrideTrackObject");
|
||||
RTPCObject = serializedObject.FindProperty("RTPCObject");
|
||||
Behaviour = serializedObject.FindProperty("template");
|
||||
|
||||
if (playable != null && playable.OwningClip != null)
|
||||
playable.OwningClip.displayName = playable.Parameter.Name;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
UnityEditor.EditorGUILayout.HelpBox(AkUnitySoundEngine.Deprecation_2019_2_0, UnityEditor.MessageType.Warning);
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
if (setRTPCGlobally != null)
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(setRTPCGlobally, new UnityEngine.GUIContent("Set RTPC Globally: "));
|
||||
if (!setRTPCGlobally.boolValue)
|
||||
{
|
||||
if (overrideTrackObject != null)
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(overrideTrackObject,
|
||||
new UnityEngine.GUIContent("Override Track Object: "));
|
||||
if (overrideTrackObject.boolValue)
|
||||
{
|
||||
if (RTPCObject != null)
|
||||
UnityEditor.EditorGUILayout.PropertyField(RTPCObject, new UnityEngine.GUIContent("RTPC Object: "));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Behaviour != null)
|
||||
UnityEditor.EditorGUILayout.PropertyField(Behaviour, new UnityEngine.GUIContent("Animated Value: "), true);
|
||||
|
||||
if (playable != null && playable.OwningClip != null)
|
||||
playable.OwningClip.displayName = playable.Parameter.Name;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif //#if UNITY_EDITOR
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c480664374816746acc2c215ab2e08e
|
||||
@@ -0,0 +1,47 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
[UnityEditor.CustomEditor(typeof(AkRTPCTrack))]
|
||||
public class AkRTPCTrackInspector : UnityEditor.Editor
|
||||
{
|
||||
private UnityEditor.SerializedProperty Parameter;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
Parameter = serializedObject.FindProperty("Parameter");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(Parameter, new UnityEngine.GUIContent("Parameter: "));
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif //AK_ENABLE_TIMELINE
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85c223b7c6c94ce4aa2a258525fd1244
|
||||
@@ -0,0 +1,16 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the AUDIOKINETIC
|
||||
Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity Terms of Service
|
||||
at https://unity3d.com/legal/terms-of-service.
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c552b3651c8ef942b0999e2af9f18af
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
# Unity Wwise Timeline
|
||||
|
||||
This package adds support for using Wwise Event and RTPC in the Unity Timeline.
|
||||
|
||||
## Usage
|
||||
|
||||
See [Unity Wwise Timeline Documentation](https://www.audiokinetic.com/library/edge/?source=Unity&id=unity_timeline.html) for more information about how to use the package.
|
||||
|
||||
## Requirements
|
||||
|
||||
* Unity.Timeline >= 1.1.0
|
||||
|
||||
## Legal
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the AUDIOKINETIC
|
||||
Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity Terms of Service
|
||||
at https://unity3d.com/legal/terms-of-service.
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright c <COPYRIGHTYEAR> Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 696874581aedac14199d2d88eb051982
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e946a5804ca181448258196fbbd7bab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "AK.Wwise.Unity.Timeline",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"AK.Wwise.Unity.API",
|
||||
"AK.Wwise.Unity.MonoBehavior",
|
||||
"Unity.Timeline",
|
||||
"AK.Wwise.Unity.API.WwiseTypes",
|
||||
"AK.Wwise.Unity.ProjectDatabase",
|
||||
"AK.Wwise.Unity.Utilities",
|
||||
"AK.Wwise.Unity.Logging"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [
|
||||
"Lumin",
|
||||
"Stadia"
|
||||
],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"!UNITY_SERVER"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.timeline",
|
||||
"expression": "1.1.0",
|
||||
"define": "AK_ENABLE_TIMELINE"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b873dcce1091413478e0fc02d6292b68
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
/// @brief A playable asset containing a Wwise event that can be placed within a \ref AkEventTrack in a timeline.
|
||||
/// @details Use this class to play Wwise events from a timeline and synchronise them to the animation. Events will be emitted from the GameObject that is bound to the AkEventTrack. Use the overrideTrackEmitterObject option to choose a different GameObject from which to emit the Wwise event.
|
||||
/// \sa
|
||||
/// - \ref AkEventTrack
|
||||
/// - \ref AkEventPlayableBehavior
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
public class AkEventPlayable : UnityEngine.Playables.PlayableAsset, UnityEngine.Timeline.ITimelineClipAsset
|
||||
{
|
||||
public AK.Wwise.Event akEvent = new AK.Wwise.Event();
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private AkCurveInterpolation blendInCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
|
||||
[UnityEngine.SerializeField]
|
||||
private AkCurveInterpolation blendOutCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private UnityEngine.ExposedReference<UnityEngine.GameObject> emitterObjectRef;
|
||||
|
||||
public float eventDurationMax = -1f;
|
||||
public float eventDurationMin = -1f;
|
||||
|
||||
[System.NonSerialized]
|
||||
public UnityEngine.Timeline.TimelineClip owningClip;
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private bool retriggerEvent = false;
|
||||
|
||||
public bool UseWwiseEventDuration = true;
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private bool StopEventAtClipEnd = true;
|
||||
|
||||
UnityEngine.Timeline.ClipCaps UnityEngine.Timeline.ITimelineClipAsset.clipCaps
|
||||
{
|
||||
get { return UnityEngine.Timeline.ClipCaps.Looping | UnityEngine.Timeline.ClipCaps.Blending; }
|
||||
}
|
||||
|
||||
public override UnityEngine.Playables.Playable CreatePlayable(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject owner)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkEventPlayableBehavior>.Create(graph);
|
||||
|
||||
var eventObject = emitterObjectRef.Resolve(graph.GetResolver());
|
||||
if (eventObject == null)
|
||||
eventObject = owner;
|
||||
|
||||
if (eventObject == null || akEvent == null)
|
||||
return playable;
|
||||
|
||||
var b = playable.GetBehaviour();
|
||||
b.akEvent = akEvent;
|
||||
b.blendInCurve = blendInCurve;
|
||||
b.blendOutCurve = blendOutCurve;
|
||||
|
||||
if (owningClip != null)
|
||||
{
|
||||
b.easeInDuration = (float)owningClip.easeInDuration;
|
||||
b.easeOutDuration = (float)owningClip.easeOutDuration;
|
||||
b.blendInDuration = (float)owningClip.blendInDuration;
|
||||
b.blendOutDuration = (float)owningClip.blendOutDuration;
|
||||
}
|
||||
else
|
||||
b.easeInDuration = b.easeOutDuration = b.blendInDuration = b.blendOutDuration = 0;
|
||||
|
||||
b.retriggerEvent = retriggerEvent;
|
||||
b.StopEventAtClipEnd = StopEventAtClipEnd;
|
||||
b.eventObject = eventObject;
|
||||
b.overrideTrackEmitterObject = eventObject != null;
|
||||
b.eventDurationMin = eventDurationMin;
|
||||
b.eventDurationMax = eventDurationMax;
|
||||
return playable;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb1a5ca4227cde649ba636e48b8ccd7b
|
||||
@@ -0,0 +1,435 @@
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
/// @brief Defines the behavior of a \ref AkEventPlayable within a \ref AkEventTrack.
|
||||
/// \sa
|
||||
/// - \ref AkEventTrack
|
||||
/// - \ref AkEventPlayable
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
public class AkEventPlayableBehavior : UnityEngine.Playables.PlayableBehaviour
|
||||
{
|
||||
private float currentDuration = -1f;
|
||||
private float currentDurationProportion = 1f;
|
||||
private bool eventIsPlaying;
|
||||
private bool fadeinTriggered;
|
||||
private bool fadeoutTriggered;
|
||||
private float previousEventStartTime;
|
||||
|
||||
private const uint CallbackFlags = (uint)(AkCallbackType.AK_EndOfEvent | AkCallbackType.AK_Duration);
|
||||
|
||||
private void CallbackHandler(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info)
|
||||
{
|
||||
if (in_type == AkCallbackType.AK_EndOfEvent)
|
||||
{
|
||||
eventIsPlaying = fadeinTriggered = fadeoutTriggered = false;
|
||||
}
|
||||
else if (in_type == AkCallbackType.AK_Duration)
|
||||
{
|
||||
var estimatedDuration = (in_info as AkDurationCallbackInfo).fEstimatedDuration;
|
||||
currentDuration = estimatedDuration * currentDurationProportion / 1000f;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static bool CanPostEvents
|
||||
{
|
||||
get { return UnityEditor.SessionState.GetBool("AkEventPlayableBehavior.CanPostEvents", true); }
|
||||
set { UnityEditor.SessionState.SetBool("AkEventPlayableBehavior.CanPostEvents", value); }
|
||||
}
|
||||
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
private static void DetermineCanPostEvents()
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnityEditor.Compilation.CompilationPipeline.assemblyCompilationFinished += (string text, UnityEditor.Compilation.CompilerMessage[] messages) =>
|
||||
{
|
||||
if (!UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
CanPostEvents = false;
|
||||
}
|
||||
};
|
||||
|
||||
UnityEditor.EditorApplication.playModeStateChanged += (UnityEditor.PlayModeStateChange playMode) =>
|
||||
{
|
||||
if (playMode == UnityEditor.PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
CanPostEvents = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
[System.Flags]
|
||||
private enum Actions
|
||||
{
|
||||
None = 0,
|
||||
Playback = 1 << 0,
|
||||
Retrigger = 1 << 1,
|
||||
DelayedStop = 1 << 2,
|
||||
Seek = 1 << 3,
|
||||
FadeIn = 1 << 4,
|
||||
FadeOut = 1 << 5
|
||||
}
|
||||
private Actions requiredActions;
|
||||
|
||||
private const int scrubPlaybackLengthMs = 100;
|
||||
|
||||
public AK.Wwise.Event akEvent;
|
||||
|
||||
public float eventDurationMax;
|
||||
public float eventDurationMin;
|
||||
|
||||
public float blendInDuration;
|
||||
public float blendOutDuration;
|
||||
public float easeInDuration;
|
||||
public float easeOutDuration;
|
||||
|
||||
public AkCurveInterpolation blendInCurve;
|
||||
public AkCurveInterpolation blendOutCurve;
|
||||
|
||||
public UnityEngine.GameObject eventObject;
|
||||
|
||||
public bool retriggerEvent;
|
||||
private bool wasScrubbingAndRequiresRetrigger;
|
||||
public bool StopEventAtClipEnd;
|
||||
|
||||
public bool overrideTrackEmitterObject;
|
||||
|
||||
private bool IsScrubbing(UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
#if !UNITY_2018_2_OR_NEWER
|
||||
// We disable scrubbing in edit mode, due to an issue with how FrameData.EvaluationType is handled in edit mode.
|
||||
// This is a known issue and Unity are aware of it: https://fogbugz.unity3d.com/default.asp?953109_kitf7pso0vmjm0m0
|
||||
if (!UnityEngine.Application.isPlaying)
|
||||
return false;
|
||||
#endif
|
||||
return info.evaluationType == UnityEngine.Playables.FrameData.EvaluationType.Evaluate;
|
||||
}
|
||||
|
||||
public override void PrepareFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
base.PrepareFrame(playable, info);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var shouldPlay = ShouldPlay(playable);
|
||||
if (IsScrubbing(info) && shouldPlay)
|
||||
{
|
||||
requiredActions |= Actions.Seek;
|
||||
|
||||
if (!eventIsPlaying)
|
||||
{
|
||||
requiredActions |= Actions.Playback | Actions.DelayedStop;
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
}
|
||||
else if (!eventIsPlaying && (requiredActions & Actions.Playback) == 0)
|
||||
{
|
||||
// The clip is playing but the event hasn't been triggered. We need to start the event and jump to the correct time.
|
||||
requiredActions |= Actions.Retrigger;
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckForFadeOut(playable, UnityEngine.Playables.PlayableExtensions.GetTime(playable));
|
||||
}
|
||||
}
|
||||
|
||||
private const float alph = 0.05f;
|
||||
|
||||
public override void OnBehaviourPlay(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
base.OnBehaviourPlay(playable, info);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var shouldPlay = ShouldPlay(playable);
|
||||
if (!shouldPlay)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
requiredActions |= Actions.Playback;
|
||||
|
||||
if (IsScrubbing(info))
|
||||
{
|
||||
wasScrubbingAndRequiresRetrigger = true;
|
||||
// If we've explicitly set the playhead, only play a small snippet.
|
||||
requiredActions |= Actions.DelayedStop;
|
||||
}
|
||||
else if (GetProportionalTime(playable) > alph)
|
||||
{
|
||||
// we need to jump to the correct position in the case where the event is played from some non-start position.
|
||||
requiredActions |= Actions.Seek;
|
||||
}
|
||||
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
|
||||
public override void OnBehaviourPause(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
wasScrubbingAndRequiresRetrigger = false;
|
||||
|
||||
base.OnBehaviourPause(playable, info);
|
||||
if (eventObject != null && akEvent != null && StopEventAtClipEnd)
|
||||
{
|
||||
StopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public override void ProcessFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info, object playerData)
|
||||
{
|
||||
base.ProcessFrame(playable, info, playerData);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!overrideTrackEmitterObject)
|
||||
{
|
||||
var obj = playerData as UnityEngine.GameObject;
|
||||
if (obj != null)
|
||||
{
|
||||
eventObject = obj;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.Playback) != 0)
|
||||
{
|
||||
PlayEvent();
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.Seek) != 0)
|
||||
{
|
||||
SeekToTime(playable);
|
||||
}
|
||||
|
||||
if ((retriggerEvent || wasScrubbingAndRequiresRetrigger) && (requiredActions & Actions.Retrigger) != 0)
|
||||
{
|
||||
RetriggerEvent(playable);
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.DelayedStop) != 0)
|
||||
{
|
||||
StopEvent(scrubPlaybackLengthMs);
|
||||
}
|
||||
|
||||
if (!fadeinTriggered && (requiredActions & Actions.FadeIn) != 0)
|
||||
{
|
||||
TriggerFadeIn(playable);
|
||||
}
|
||||
|
||||
if (!fadeoutTriggered && (requiredActions & Actions.FadeOut) != 0)
|
||||
{
|
||||
TriggerFadeOut(playable);
|
||||
}
|
||||
|
||||
requiredActions = Actions.None;
|
||||
}
|
||||
|
||||
/** Check the playable time against the Wwise event duration to see if playback should occur.
|
||||
*/
|
||||
private bool ShouldPlay(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
|
||||
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
if (previousTime == 0.0 && System.Math.Abs(currentTime - previousTime) > 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retriggerEvent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If max and min duration values from metadata are equal, we can assume a deterministic event.
|
||||
if (eventDurationMax == eventDurationMin && eventDurationMin != -1f)
|
||||
{
|
||||
return currentTime < eventDurationMax;
|
||||
}
|
||||
|
||||
currentTime -= previousEventStartTime;
|
||||
|
||||
var maxDuration = currentDuration == -1f ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
|
||||
return currentTime < maxDuration;
|
||||
}
|
||||
|
||||
private void CheckForFadeInFadeOut(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
if (blendInDuration > currentClipTime || easeInDuration > currentClipTime)
|
||||
{
|
||||
requiredActions |= Actions.FadeIn;
|
||||
}
|
||||
|
||||
CheckForFadeOut(playable, currentClipTime);
|
||||
}
|
||||
|
||||
private void CheckForFadeOut(UnityEngine.Playables.Playable playable, double currentClipTime)
|
||||
{
|
||||
var timeLeft = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - currentClipTime;
|
||||
if (blendOutDuration >= timeLeft || easeOutDuration >= timeLeft)
|
||||
{
|
||||
requiredActions |= Actions.FadeOut;
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerFadeIn(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
var fadeDuration = UnityEngine.Mathf.Max(easeInDuration, blendInDuration) - currentClipTime;
|
||||
if (fadeDuration > 0)
|
||||
{
|
||||
fadeinTriggered = true;
|
||||
akEvent.ExecuteAction(eventObject, AkActionOnEventType.AkActionOnEventType_Pause, 0, blendOutCurve);
|
||||
akEvent.ExecuteAction(eventObject, AkActionOnEventType.AkActionOnEventType_Resume, (int)(fadeDuration * 1000), blendInCurve);
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerFadeOut(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
fadeoutTriggered = true;
|
||||
|
||||
var fadeDuration = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
akEvent.ExecuteAction(eventObject, AkActionOnEventType.AkActionOnEventType_Stop, (int)(fadeDuration * 1000), blendOutCurve);
|
||||
}
|
||||
|
||||
private void StopEvent(int transition = 0)
|
||||
{
|
||||
if (!eventIsPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
akEvent.Stop(eventObject, transition);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
eventIsPlaying = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool PostEvent()
|
||||
{
|
||||
fadeinTriggered = fadeoutTriggered = false;
|
||||
|
||||
uint playingID;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!CanPostEvents)
|
||||
{
|
||||
playingID = AkUnitySoundEngine.AK_INVALID_PLAYING_ID;
|
||||
}
|
||||
else if (!UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
playingID = akEvent.Post(eventObject);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
playingID = akEvent.Post(eventObject, CallbackFlags, CallbackHandler, null);
|
||||
}
|
||||
|
||||
eventIsPlaying = playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID;
|
||||
return eventIsPlaying;
|
||||
}
|
||||
|
||||
private void PlayEvent()
|
||||
{
|
||||
if (!PostEvent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentDurationProportion = 1f;
|
||||
previousEventStartTime = 0f;
|
||||
}
|
||||
|
||||
private void RetriggerEvent(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
wasScrubbingAndRequiresRetrigger = false;
|
||||
|
||||
if (!PostEvent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentDurationProportion = 1f - SeekToTime(playable);
|
||||
previousEventStartTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
}
|
||||
|
||||
private float GetProportionalTime(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
// If max and min duration values from metadata are equal, we can assume a deterministic event.
|
||||
if (eventDurationMax == eventDurationMin && eventDurationMin != -1f)
|
||||
{
|
||||
// If the timeline clip has length greater than the event duration, we want to loop.
|
||||
return (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) % eventDurationMax / eventDurationMax;
|
||||
}
|
||||
|
||||
var currentTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) - previousEventStartTime;
|
||||
var maxDuration = currentDuration == -1f ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
|
||||
// If the timeline clip has length greater than the event duration, we want to loop.
|
||||
return currentTime % maxDuration / maxDuration;
|
||||
}
|
||||
|
||||
// Seek to the current time, taking looping into account.
|
||||
private float SeekToTime(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var proportionalTime = GetProportionalTime(playable);
|
||||
if (proportionalTime >= 1f) // Avoids Wwise "seeking beyond end of event: audio will stop" error.
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!CanPostEvents)
|
||||
{
|
||||
return proportionalTime;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eventIsPlaying)
|
||||
{
|
||||
AkUnitySoundEngine.SeekOnEvent(akEvent.Id, eventObject, proportionalTime);
|
||||
}
|
||||
|
||||
return proportionalTime;
|
||||
}
|
||||
}
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d58562fd2b969949be5aa151c9c4673
|
||||
@@ -0,0 +1,54 @@
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
[UnityEngine.Timeline.TrackColor(0.855f, 0.8623f, 0.870f)]
|
||||
[UnityEngine.Timeline.TrackClipType(typeof(AkEventPlayable))]
|
||||
[UnityEngine.Timeline.TrackBindingType(typeof(UnityEngine.GameObject))]
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
[UnityEngine.Timeline.HideInMenu]
|
||||
#endif
|
||||
/// @brief A track within timeline that holds \ref AkEventPlayable clips.
|
||||
/// @details AkEventTracks are bound to a specific GameObject, which is the default emitter for all of the \ref AkEventPlayable clips. There is an option to override this in /ref AkEventPlayable.
|
||||
/// \sa
|
||||
/// - \ref AkEventPlayable
|
||||
/// - \ref AkEventPlayableBehavior
|
||||
public class AkEventTrack : UnityEngine.Timeline.TrackAsset
|
||||
{
|
||||
public override UnityEngine.Playables.Playable CreateTrackMixer(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject go, int inputCount)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkEventPlayableBehavior>.Create(graph);
|
||||
UnityEngine.Playables.PlayableExtensions.SetInputCount(playable, inputCount);
|
||||
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var akEventPlayable = clip.asset as AkEventPlayable;
|
||||
akEventPlayable.owningClip = clip;
|
||||
}
|
||||
|
||||
return playable;
|
||||
}
|
||||
}
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1401ee1c5f480a64a9d63fe65dc35b44
|
||||
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// The representation of the Timeline Clip
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
[System.Serializable]
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
public class AkRTPCPlayable : UnityEngine.Playables.PlayableAsset, UnityEngine.Timeline.ITimelineClipAsset
|
||||
{
|
||||
public bool overrideTrackObject = false;
|
||||
public UnityEngine.ExposedReference<UnityEngine.GameObject> RTPCObject;
|
||||
|
||||
public bool setRTPCGlobally = false;
|
||||
public AkRTPCPlayableBehaviour template = new AkRTPCPlayableBehaviour();
|
||||
|
||||
public AK.Wwise.RTPC Parameter { get; set; }
|
||||
|
||||
public UnityEngine.Timeline.TimelineClip OwningClip { get; set; }
|
||||
|
||||
UnityEngine.Timeline.ClipCaps UnityEngine.Timeline.ITimelineClipAsset.clipCaps
|
||||
{
|
||||
get { return UnityEngine.Timeline.ClipCaps.Looping & UnityEngine.Timeline.ClipCaps.Extrapolation & UnityEngine.Timeline.ClipCaps.Blending; }
|
||||
}
|
||||
|
||||
public override UnityEngine.Playables.Playable CreatePlayable(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject go)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkRTPCPlayableBehaviour>.Create(graph, template);
|
||||
var b = playable.GetBehaviour();
|
||||
b.overrideTrackObject = overrideTrackObject;
|
||||
b.setRTPCGlobally = setRTPCGlobally;
|
||||
b.rtpcObject = overrideTrackObject ? RTPCObject.Resolve(graph.GetResolver()) : go;
|
||||
b.parameter = Parameter;
|
||||
return playable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// The behaviour template.
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
[System.Serializable]
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
public class AkRTPCPlayableBehaviour : UnityEngine.Playables.PlayableBehaviour
|
||||
{
|
||||
[UnityEngine.SerializeField]
|
||||
private float RTPCValue = 0.0f;
|
||||
|
||||
public bool setRTPCGlobally { set; private get; }
|
||||
|
||||
public bool overrideTrackObject { set; private get; }
|
||||
|
||||
public UnityEngine.GameObject rtpcObject { set; private get; }
|
||||
|
||||
public AK.Wwise.RTPC parameter { set; private get; }
|
||||
|
||||
public override void ProcessFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info,
|
||||
object playerData)
|
||||
{
|
||||
if (parameter != null)
|
||||
{
|
||||
// If we are overriding the track object, the rtpcObject will have been resolved in AkRTPCPlayable::CreatePlayable().
|
||||
if (!overrideTrackObject)
|
||||
{
|
||||
// At this point, rtpcObject will have been set to the timeline owner object in AkRTPCPlayable::CreatePlayable().
|
||||
// If the track object is null, we keep using the timeline owner object. Otherwise, we swap it for the track object.
|
||||
var obj = playerData as UnityEngine.GameObject;
|
||||
if (obj != null)
|
||||
rtpcObject = obj;
|
||||
}
|
||||
|
||||
if (setRTPCGlobally || rtpcObject == null)
|
||||
parameter.SetGlobalValue(RTPCValue);
|
||||
else
|
||||
parameter.SetValue(rtpcObject, RTPCValue);
|
||||
}
|
||||
|
||||
base.ProcessFrame(playable, info, playerData);
|
||||
}
|
||||
}
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e71af907a2d8e4a4d8b0e926af062cbe
|
||||
@@ -0,0 +1,69 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
[UnityEngine.Timeline.TrackColor(0.32f, 0.13f, 0.13f)]
|
||||
// Specifies the type of Playable Asset this track manages
|
||||
[UnityEngine.Timeline.TrackClipType(typeof(AkRTPCPlayable))]
|
||||
// Use if the track requires a binding to a scene object or asset
|
||||
[UnityEngine.Timeline.TrackBindingType(typeof(UnityEngine.GameObject))]
|
||||
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
[UnityEngine.Timeline.HideInMenu]
|
||||
#endif
|
||||
public class AkRTPCTrack : UnityEngine.Timeline.TrackAsset
|
||||
{
|
||||
public AK.Wwise.RTPC Parameter;
|
||||
|
||||
// override the type of mixer playable used by this track
|
||||
public override UnityEngine.Playables.Playable CreateTrackMixer(UnityEngine.Playables.PlayableGraph graph,
|
||||
UnityEngine.GameObject go, int inputCount)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkRTPCPlayableBehaviour>.Create(graph, inputCount);
|
||||
setPlayableProperties();
|
||||
return playable;
|
||||
}
|
||||
|
||||
public void setPlayableProperties()
|
||||
{
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var clipPlayable = (AkRTPCPlayable) clip.asset;
|
||||
clipPlayable.Parameter = Parameter;
|
||||
clipPlayable.OwningClip = clip;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var clipPlayable = (AkRTPCPlayable) clip.asset;
|
||||
clipPlayable.Parameter = Parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a2968b9015c3454d99f8188cfd9b949
|
||||
@@ -0,0 +1,773 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AK.Wwise.Unity.Logging;
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
/// @brief Defines the behavior of a \ref AkTimelineEventPlayable within a \ref AkTimelineEventTrack.
|
||||
/// \sa
|
||||
/// - \ref AkTimelineEventTrack
|
||||
/// - \ref AkTimelineEventPlayable
|
||||
public class AkTimelineEventPlayableBehavior : UnityEngine.Playables.PlayableBehaviour
|
||||
{
|
||||
private float currentDuration = -1f;
|
||||
private float currentDurationProportion = 1f;
|
||||
|
||||
private bool eventIsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
return playingId != 0;
|
||||
}
|
||||
}
|
||||
private float previousEventStartTime;
|
||||
private uint playingId = 0;
|
||||
|
||||
private const uint CallbackFlags = (uint)(AkCallbackType.AK_EndOfEvent | AkCallbackType.AK_Duration);
|
||||
|
||||
private void CallbackHandler(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info)
|
||||
{
|
||||
if (in_type == AkCallbackType.AK_EndOfEvent)
|
||||
{
|
||||
StopEvent();
|
||||
}
|
||||
else if (in_type == AkCallbackType.AK_Duration)
|
||||
{
|
||||
var estimatedDuration = (in_info as AkDurationCallbackInfo).fEstimatedDuration;
|
||||
currentDuration = estimatedDuration * currentDurationProportion / 1000f;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static bool CanPostEvents
|
||||
{
|
||||
get { return UnityEditor.SessionState.GetBool("AkTimelineEventPlayableBehavior.CanPostEvents", true); }
|
||||
set { UnityEditor.SessionState.SetBool("AkTimelineEventPlayableBehavior.CanPostEvents", value); }
|
||||
}
|
||||
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
private static void DetermineCanPostEvents()
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnityEditor.Compilation.CompilationPipeline.assemblyCompilationFinished += (string text, UnityEditor.Compilation.CompilerMessage[] messages) =>
|
||||
{
|
||||
if (!UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
CanPostEvents = true;
|
||||
}
|
||||
};
|
||||
|
||||
UnityEditor.EditorApplication.playModeStateChanged += (UnityEditor.PlayModeStateChange playMode) =>
|
||||
{
|
||||
if (playMode == UnityEditor.PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
CanPostEvents = true;
|
||||
}
|
||||
|
||||
if (playMode == UnityEditor.PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
CanPostEvents = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
[System.Flags]
|
||||
private enum Actions
|
||||
{
|
||||
None = 0,
|
||||
Playback = 1 << 0,
|
||||
Retrigger = 1 << 1,
|
||||
DelayedStop = 1 << 2,
|
||||
Seek = 1 << 3,
|
||||
FadeIn = 1 << 4,
|
||||
FadeOut = 1 << 5
|
||||
}
|
||||
private Actions requiredActions;
|
||||
|
||||
private const int scrubPlaybackLengthMs = 100;
|
||||
|
||||
public AK.Wwise.Event akEvent;
|
||||
|
||||
public float eventDurationMax;
|
||||
public float eventDurationMin;
|
||||
|
||||
public float blendInDuration;
|
||||
public float blendOutDuration;
|
||||
public float easeInDuration;
|
||||
public float easeOutDuration;
|
||||
|
||||
public AkCurveInterpolation blendInCurve;
|
||||
public AkCurveInterpolation blendOutCurve;
|
||||
|
||||
public UnityEngine.GameObject eventObject;
|
||||
|
||||
public bool retriggerEvent;
|
||||
public bool StopEventAtClipEnd;
|
||||
|
||||
public bool PrintDebugInformation = false;
|
||||
|
||||
private bool IsScrubbing(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!UnityEngine.Application.isPlaying)
|
||||
{
|
||||
return info.evaluationType == UnityEngine.Playables.FrameData.EvaluationType.Evaluate;
|
||||
}
|
||||
#endif
|
||||
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
|
||||
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
var computedDelta = System.Math.Abs(currentTime - previousTime);
|
||||
|
||||
// Unfortunately, we can't use info.seekOccurred, because it is always true.
|
||||
// When time is explicitely set using playable.time, deltaTime is zero, evaluationType is Evaluate, and
|
||||
// either previous time or current time is non-zero
|
||||
// However, if time is added to playable.time (for example, playable.time += 1;), evaluationType remains
|
||||
// Playing.
|
||||
return (info.deltaTime == 0 && (previousTime >= 0 || currentTime >= 0)) || (computedDelta > info.deltaTime);
|
||||
}
|
||||
|
||||
void PrintInfo(string FunctionName, UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
if (PrintDebugInformation)
|
||||
{
|
||||
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
|
||||
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
var computedDelta = System.Math.Abs(currentTime - previousTime);
|
||||
|
||||
WwiseLogger.Log($"{FunctionName}: prevTime={previousTime}; curTime={currentTime}; computedDelta={computedDelta}; evalType={info.evaluationType}; deltaTime={info.deltaTime}; playState={info.effectivePlayState}; timeHeld={info.timeHeld}; speed={info.effectiveSpeed}; parentSpeed={info.effectiveParentSpeed}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void PrepareFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
base.PrepareFrame(playable, info);
|
||||
PrintInfo("PrepareFrame", playable, info);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var shouldPlay = ShouldPlay(playable);
|
||||
if (IsScrubbing(playable, info) && shouldPlay)
|
||||
{
|
||||
requiredActions |= Actions.Seek;
|
||||
|
||||
if (playingId == 0)
|
||||
{
|
||||
requiredActions |= Actions.Playback;
|
||||
#if UNITY_EDITOR
|
||||
if (!UnityEngine.Application.isPlaying)
|
||||
{
|
||||
// If we've explicitly set the playhead, only play a small snippet.
|
||||
requiredActions |= Actions.DelayedStop;
|
||||
}
|
||||
#endif
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
}
|
||||
else if (shouldPlay && playingId == 0 && (requiredActions & Actions.Playback) == 0)
|
||||
{
|
||||
// The clip is playing but the event hasn't been triggered. We need to start the event and jump to the correct time.
|
||||
requiredActions |= Actions.Retrigger;
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckForFadeOut(playable, UnityEngine.Playables.PlayableExtensions.GetTime(playable));
|
||||
}
|
||||
}
|
||||
|
||||
private const float alph = 0.05f;
|
||||
|
||||
public override void OnBehaviourPlay(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
PrintInfo("OnBehaviourPlay", playable, info);
|
||||
base.OnBehaviourPlay(playable, info);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ShouldPlay(playable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
requiredActions |= Actions.Playback;
|
||||
|
||||
if (IsScrubbing(playable, info))
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!UnityEngine.Application.isPlaying)
|
||||
{
|
||||
// If we've explicitly set the playhead, only play a small snippet.
|
||||
requiredActions |= Actions.DelayedStop;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (GetProportionalTime(playable) > alph)
|
||||
{
|
||||
// we need to jump to the correct position in the case where the event is played from some non-start position.
|
||||
requiredActions |= Actions.Seek;
|
||||
}
|
||||
|
||||
CheckForFadeInFadeOut(playable);
|
||||
}
|
||||
|
||||
public override void OnBehaviourPause(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info)
|
||||
{
|
||||
PrintInfo("OnBehaviourPause", playable, info);
|
||||
|
||||
base.OnBehaviourPause(playable, info);
|
||||
if (eventObject != null && akEvent != null && StopEventAtClipEnd)
|
||||
{
|
||||
StopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public override void ProcessFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData info, object playerData)
|
||||
{
|
||||
PrintInfo("ProcessFrame", playable, info);
|
||||
base.ProcessFrame(playable, info, playerData);
|
||||
|
||||
if (akEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = playerData as UnityEngine.GameObject;
|
||||
if (obj != null)
|
||||
{
|
||||
eventObject = obj;
|
||||
}
|
||||
|
||||
if (eventObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.Playback) != 0)
|
||||
{
|
||||
PlayEvent();
|
||||
}
|
||||
else if ((requiredActions & Actions.Seek) != 0)
|
||||
{
|
||||
SeekToTime(playable);
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.Retrigger) != 0)
|
||||
{
|
||||
RetriggerEvent(playable);
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.DelayedStop) != 0)
|
||||
{
|
||||
StopEvent(scrubPlaybackLengthMs);
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.FadeOut) != 0)
|
||||
{
|
||||
TriggerFadeOut(playable);
|
||||
}
|
||||
|
||||
if ((requiredActions & Actions.FadeIn) != 0)
|
||||
{
|
||||
TriggerFadeIn(playable);
|
||||
}
|
||||
|
||||
requiredActions = Actions.None;
|
||||
}
|
||||
|
||||
/** Check the playable time against the Wwise event duration to see if playback should occur.
|
||||
*/
|
||||
private bool ShouldPlay(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var previousTime = UnityEngine.Playables.PlayableExtensions.GetPreviousTime(playable);
|
||||
var currentTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// In editor, do not automatically play the event if the cursor is already in the section.
|
||||
if (!UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
if (previousTime == 0.0 && System.Math.Abs(currentTime - previousTime) > 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (previousTime > currentTime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (retriggerEvent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If max and min duration values from metadata are equal, we can assume a deterministic event.
|
||||
if (eventDurationMax.Equals(eventDurationMin) && !eventDurationMin.Equals(-1f))
|
||||
{
|
||||
return currentTime < eventDurationMax;
|
||||
}
|
||||
|
||||
currentTime -= previousEventStartTime;
|
||||
|
||||
var maxDuration = currentDuration.Equals(-1f) ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
|
||||
return currentTime < maxDuration;
|
||||
}
|
||||
|
||||
private void CheckForFadeInFadeOut(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
if (blendInDuration > currentClipTime || easeInDuration > currentClipTime)
|
||||
{
|
||||
requiredActions |= Actions.FadeIn;
|
||||
}
|
||||
|
||||
CheckForFadeOut(playable, currentClipTime);
|
||||
}
|
||||
|
||||
private void CheckForFadeOut(UnityEngine.Playables.Playable playable, double currentClipTime)
|
||||
{
|
||||
var timeLeft = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - currentClipTime;
|
||||
if (blendOutDuration >= timeLeft || easeOutDuration >= timeLeft)
|
||||
{
|
||||
requiredActions |= Actions.FadeOut;
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerFadeIn(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var currentClipTime = UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
var fadeDuration = UnityEngine.Mathf.Max(easeInDuration, blendInDuration) - currentClipTime;
|
||||
if (fadeDuration > 0)
|
||||
{
|
||||
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Pause, playingId, 0, blendInCurve);
|
||||
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Resume, playingId, (int)(fadeDuration * 1000), blendInCurve);
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerFadeOut(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var fadeDuration = UnityEngine.Playables.PlayableExtensions.GetDuration(playable) - UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Stop, playingId, (int)(fadeDuration * 1000), blendOutCurve);
|
||||
}
|
||||
|
||||
private void StopEvent(int transition = 0)
|
||||
{
|
||||
if (playingId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Stop, playingId);
|
||||
playingId = 0;
|
||||
}
|
||||
|
||||
private bool PostEvent()
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!CanPostEvents)
|
||||
{
|
||||
playingId = AkUnitySoundEngine.AK_INVALID_PLAYING_ID;
|
||||
}
|
||||
#endif
|
||||
if(playingId == 0)
|
||||
{
|
||||
playingId = akEvent.Post(eventObject, CallbackFlags, CallbackHandler, null);
|
||||
return playingId != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void PlayEvent()
|
||||
{
|
||||
if (!PostEvent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentDurationProportion = 1f;
|
||||
previousEventStartTime = 0f;
|
||||
}
|
||||
|
||||
private void RetriggerEvent(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
|
||||
if (!PostEvent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentDurationProportion = 1f - SeekToTime(playable);
|
||||
previousEventStartTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable);
|
||||
}
|
||||
|
||||
private float GetProportionalTime(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
// If max and min duration values from metadata are equal, we can assume a deterministic event.
|
||||
if (eventDurationMax == eventDurationMin && eventDurationMin != -1f)
|
||||
{
|
||||
// If the timeline clip has length greater than the event duration, we want to loop.
|
||||
return (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) % eventDurationMax / eventDurationMax;
|
||||
}
|
||||
|
||||
var currentTime = (float)UnityEngine.Playables.PlayableExtensions.GetTime(playable) - previousEventStartTime;
|
||||
if (currentTime < 0)
|
||||
{
|
||||
return -1f;
|
||||
}
|
||||
var maxDuration = currentDuration == -1f ? (float)UnityEngine.Playables.PlayableExtensions.GetDuration(playable) : currentDuration;
|
||||
// If the timeline clip has length greater than the event duration, we want to loop.
|
||||
return currentTime % maxDuration / maxDuration;
|
||||
}
|
||||
|
||||
// Seek to the current time, taking looping into account.
|
||||
private float SeekToTime(UnityEngine.Playables.Playable playable)
|
||||
{
|
||||
var proportionalTime = GetProportionalTime(playable);
|
||||
if (proportionalTime >= 1f) // Avoids Wwise "seeking beyond end of event: audio will stop" error.
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
if (proportionalTime < 0f)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!CanPostEvents)
|
||||
{
|
||||
return proportionalTime;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (playingId != 0)
|
||||
{
|
||||
AkUnitySoundEngine.SeekOnEvent(akEvent.Id, eventObject, proportionalTime, false, playingId);
|
||||
}
|
||||
|
||||
return proportionalTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief A playable asset containing a Wwise event that can be placed within a \ref AkTimelineEventTrack in a timeline.
|
||||
/// @details Use this class to play Wwise events from a timeline and synchronize them to the animation. Events will be emitted from the GameObject that is bound to the AkTimelineEventTrack.
|
||||
/// \sa
|
||||
/// - \ref AkTimelineEventTrack
|
||||
/// - \ref AkTimelineEventPlayableBehavior
|
||||
public class AkTimelineEventPlayable : UnityEngine.Playables.PlayableAsset, UnityEngine.Timeline.ITimelineClipAsset
|
||||
{
|
||||
public AK.Wwise.Event akEvent = new AK.Wwise.Event();
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private AkCurveInterpolation blendInCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
|
||||
[UnityEngine.SerializeField]
|
||||
private AkCurveInterpolation blendOutCurve = AkCurveInterpolation.AkCurveInterpolation_Linear;
|
||||
|
||||
public float eventDurationMax = -1f;
|
||||
public float eventDurationMin = -1f;
|
||||
|
||||
[System.NonSerialized]
|
||||
public UnityEngine.Timeline.TimelineClip owningClip;
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private bool retriggerEvent = false;
|
||||
|
||||
public bool UseWwiseEventDuration = true;
|
||||
public bool PrintDebugInformation = false;
|
||||
|
||||
[UnityEngine.SerializeField]
|
||||
private bool StopEventAtClipEnd = true;
|
||||
|
||||
UnityEngine.Timeline.ClipCaps UnityEngine.Timeline.ITimelineClipAsset.clipCaps
|
||||
{
|
||||
get { return UnityEngine.Timeline.ClipCaps.Looping | UnityEngine.Timeline.ClipCaps.Blending; }
|
||||
}
|
||||
|
||||
public override UnityEngine.Playables.Playable CreatePlayable(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject owner)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkTimelineEventPlayableBehavior>.Create(graph);
|
||||
if (akEvent == null)
|
||||
{
|
||||
return playable;
|
||||
}
|
||||
|
||||
var b = playable.GetBehaviour();
|
||||
b.akEvent = akEvent;
|
||||
b.blendInCurve = blendInCurve;
|
||||
b.blendOutCurve = blendOutCurve;
|
||||
b.PrintDebugInformation = PrintDebugInformation;
|
||||
|
||||
if (owningClip != null)
|
||||
{
|
||||
b.easeInDuration = (float)owningClip.easeInDuration;
|
||||
b.easeOutDuration = (float)owningClip.easeOutDuration;
|
||||
b.blendInDuration = (float)owningClip.blendInDuration;
|
||||
b.blendOutDuration = (float)owningClip.blendOutDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
b.easeInDuration = b.easeOutDuration = b.blendInDuration = b.blendOutDuration = 0;
|
||||
}
|
||||
|
||||
b.retriggerEvent = retriggerEvent;
|
||||
b.StopEventAtClipEnd = StopEventAtClipEnd;
|
||||
b.eventObject = owner;
|
||||
b.eventDurationMin = eventDurationMin;
|
||||
b.eventDurationMax = eventDurationMax;
|
||||
if (eventDurationMin.Equals(eventDurationMax) && eventDurationMax.Equals(0f))
|
||||
{
|
||||
b.eventDurationMin = -1f;
|
||||
b.eventDurationMax = -1f;
|
||||
eventDurationMin = -1f;
|
||||
eventDurationMax = -1f;
|
||||
}
|
||||
return playable;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.CustomEditor(typeof(AkTimelineEventPlayable), true)]
|
||||
public class Editor : UnityEditor.Editor
|
||||
{
|
||||
private AkTimelineEventPlayable m_AkTimelineEventPlayable;
|
||||
private UnityEditor.SerializedProperty akEvent;
|
||||
private UnityEditor.SerializedProperty retriggerEvent;
|
||||
private UnityEditor.SerializedProperty UseWwiseEventDuration;
|
||||
private UnityEditor.SerializedProperty PrintDebugInformation;
|
||||
private UnityEditor.SerializedProperty StopEventAtClipEnd;
|
||||
private UnityEditor.SerializedProperty blendInCurve;
|
||||
private UnityEditor.SerializedProperty blendOutCurve;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
m_AkTimelineEventPlayable = target as AkTimelineEventPlayable;
|
||||
if (m_AkTimelineEventPlayable == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
akEvent = serializedObject.FindProperty("akEvent");
|
||||
retriggerEvent = serializedObject.FindProperty("retriggerEvent");
|
||||
UseWwiseEventDuration = serializedObject.FindProperty("UseWwiseEventDuration");
|
||||
PrintDebugInformation = serializedObject.FindProperty("PrintDebugInformation");
|
||||
StopEventAtClipEnd = serializedObject.FindProperty("StopEventAtClipEnd");
|
||||
blendInCurve = serializedObject.FindProperty("blendInCurve");
|
||||
blendOutCurve = serializedObject.FindProperty("blendOutCurve");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(akEvent, new UnityEngine.GUIContent("Event: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(blendInCurve);
|
||||
UnityEditor.EditorGUILayout.PropertyField(blendOutCurve);
|
||||
}
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(UseWwiseEventDuration, new UnityEngine.GUIContent("Use Wwise Event Duration: ", "The clip duration is set to the duration of the Wwise Event"));
|
||||
|
||||
if (!UpdateClipInformation(m_AkTimelineEventPlayable.owningClip, m_AkTimelineEventPlayable.akEvent, serializedObject, UseWwiseEventDuration.boolValue))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.HelpBox(string.Format("The duration of the Wwise event \"{0}\" has not been determined. Playback for this event may be inconsistent. " +
|
||||
"Ensure that the event is associated with a generated SoundBank!", m_AkTimelineEventPlayable.akEvent.Name), UnityEditor.MessageType.Warning);
|
||||
}
|
||||
|
||||
if (!UseWwiseEventDuration.boolValue)
|
||||
{
|
||||
var StopEventAtClipEndValue = StopEventAtClipEnd.boolValue;
|
||||
var retriggerEventValue = retriggerEvent.boolValue;
|
||||
|
||||
UnityEditor.EditorGUILayout.PropertyField(StopEventAtClipEnd, new UnityEngine.GUIContent("Stop Event At End Of Clip: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(retriggerEvent, new UnityEngine.GUIContent("Loop: ", "When checked, an event will loop until the end of the clip."));
|
||||
|
||||
if (retriggerEvent.boolValue && !StopEventAtClipEnd.boolValue)
|
||||
{
|
||||
if (!retriggerEventValue)
|
||||
{
|
||||
StopEventAtClipEnd.boolValue = true;
|
||||
}
|
||||
else if (StopEventAtClipEndValue)
|
||||
{
|
||||
retriggerEvent.boolValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(PrintDebugInformation);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private static void UpdateProgressBar(int index, int count)
|
||||
{
|
||||
float progress = (float)index / count;
|
||||
UnityEditor.EditorUtility.DisplayProgressBar("Wwise Integration", "Fixing clip durations of AkTimelineEventPlayables...", progress);
|
||||
}
|
||||
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
public static void SetupSoundbankSetting()
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string[] settingsToEnable = {"SoundBankGenerateEstimatedDuration"};
|
||||
AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToEnable, AkWwiseEditorSettings.WwiseProjectAbsolutePath, true);
|
||||
|
||||
UnityEditor.EditorApplication.delayCall += UpdateAllClips;
|
||||
WwiseProjectDatabase.SoundBankDirectoryUpdated += UpdateAllClips;
|
||||
}
|
||||
|
||||
private static void UpdateAllClips()
|
||||
{
|
||||
var guids = UnityEditor.AssetDatabase.FindAssets("t:AkTimelineEventPlayable", new[] { "Assets" });
|
||||
if (guids.Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var processedGuids = new System.Collections.Generic.HashSet<string>();
|
||||
|
||||
for (var i = 0; i < guids.Length; i++)
|
||||
{
|
||||
UpdateProgressBar(i, guids.Length);
|
||||
|
||||
var guid = guids[i];
|
||||
if (processedGuids.Contains(guid))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processedGuids.Add(guid);
|
||||
|
||||
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
|
||||
var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
|
||||
var instanceIds = new System.Collections.Generic.List<int>();
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var id = obj.GetInstanceID();
|
||||
if (!instanceIds.Contains(id))
|
||||
{
|
||||
instanceIds.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (; instanceIds.Count > 0; instanceIds.RemoveAt(0))
|
||||
{
|
||||
var id = instanceIds[0];
|
||||
objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (obj && obj.GetInstanceID() == id)
|
||||
{
|
||||
var playable = obj as AkTimelineEventPlayable;
|
||||
if (playable)
|
||||
{
|
||||
var serializedObject = new UnityEditor.SerializedObject(playable);
|
||||
var setClipDuration = serializedObject.FindProperty("UseWwiseEventDuration").boolValue;
|
||||
UpdateClipInformation(playable.owningClip, playable.akEvent, serializedObject, setClipDuration);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnityEditor.EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The minimum clip duration. This value is set to 1/60 of a second which generally represents the time of 1 frame.
|
||||
/// </summary>
|
||||
private const double MinimumDurationInSeconds = 1.0 / 60;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the associated clip information and the event durations.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the Wwise event is found in the project data.</returns>
|
||||
private static bool UpdateClipInformation(UnityEngine.Timeline.TimelineClip clip, AK.Wwise.Event akEvent,
|
||||
UnityEditor.SerializedObject serializedObject, bool setClipDuration)
|
||||
{
|
||||
var clipDuration = MinimumDurationInSeconds;
|
||||
var maxDuration = -1.0f;
|
||||
var minDuration = -1.0f;
|
||||
|
||||
AkUtilities.GetEventDurations(akEvent.Id, ref maxDuration, ref minDuration);
|
||||
if (maxDuration != -1.0f)
|
||||
{
|
||||
serializedObject.FindProperty("eventDurationMin").floatValue = minDuration;
|
||||
serializedObject.FindProperty("eventDurationMax").floatValue = maxDuration;
|
||||
|
||||
if (maxDuration > clipDuration)
|
||||
{
|
||||
clipDuration = maxDuration;
|
||||
}
|
||||
}
|
||||
|
||||
if (clip != null)
|
||||
{
|
||||
clip.displayName = akEvent.Name;
|
||||
if (setClipDuration)
|
||||
{
|
||||
clip.duration = clipDuration;
|
||||
}
|
||||
}
|
||||
|
||||
return maxDuration != -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //#if UNITY_EDITOR
|
||||
}
|
||||
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57bbeec52009f2a458212892791a6070
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
[UnityEngine.Timeline.TrackColor(0.855f, 0.8623f, 0.870f)]
|
||||
[UnityEngine.Timeline.TrackClipType(typeof(AkTimelineEventPlayable))]
|
||||
[UnityEngine.Timeline.TrackBindingType(typeof(UnityEngine.GameObject))]
|
||||
/// @brief A track within timeline that holds \ref AkTimelineEventPlayable clips.
|
||||
/// @details AkTimelineEventTracks are bound to specific GameObjects, which are the default emitters for all of the associated \ref AkTimelineEventPlayable clips.
|
||||
/// \sa
|
||||
/// - \ref AkTimelineEventPlayable
|
||||
/// - \ref AkTimelineEventPlayableBehavior
|
||||
public class AkTimelineEventTrack : UnityEngine.Timeline.TrackAsset
|
||||
{
|
||||
public override UnityEngine.Playables.Playable CreateTrackMixer(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject go, int inputCount)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkTimelineEventPlayableBehavior>.Create(graph);
|
||||
UnityEngine.Playables.PlayableExtensions.SetInputCount(playable, inputCount);
|
||||
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var eventPlayable = clip.asset as AkTimelineEventPlayable;
|
||||
eventPlayable.owningClip = clip;
|
||||
}
|
||||
|
||||
return playable;
|
||||
}
|
||||
public List<WwiseEventReference> GetEventReferences()
|
||||
{
|
||||
List<WwiseEventReference> returnValue = new List<WwiseEventReference>();
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var timelineEventPlayable = clip.asset as AkTimelineEventPlayable;
|
||||
if (timelineEventPlayable)
|
||||
{
|
||||
returnValue.Add(timelineEventPlayable.akEvent.WwiseObjectReference);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53bb3a6574697934196427498eea116f
|
||||
@@ -0,0 +1,127 @@
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
[System.Serializable]
|
||||
public class AkTimelineRtpcPlayableBehaviour : UnityEngine.Playables.PlayableBehaviour
|
||||
{
|
||||
[UnityEngine.SerializeField]
|
||||
private float value = 0.0f;
|
||||
|
||||
public AK.Wwise.RTPC RTPC { set; get; }
|
||||
public bool setGlobally { set; get; }
|
||||
public UnityEngine.GameObject gameObject { set; get; }
|
||||
|
||||
public override void ProcessFrame(UnityEngine.Playables.Playable playable, UnityEngine.Playables.FrameData frameData, object playerData)
|
||||
{
|
||||
base.ProcessFrame(playable, frameData, playerData);
|
||||
if (RTPC == null)
|
||||
return;
|
||||
|
||||
var obj = playerData as UnityEngine.GameObject;
|
||||
if (obj != null)
|
||||
gameObject = obj;
|
||||
|
||||
if (setGlobally)
|
||||
RTPC.SetGlobalValue(value);
|
||||
else if (gameObject)
|
||||
RTPC.SetValue(gameObject, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class AkTimelineRtpcPlayable : UnityEngine.Playables.PlayableAsset, UnityEngine.Timeline.ITimelineClipAsset
|
||||
{
|
||||
public AK.Wwise.RTPC RTPC = new AK.Wwise.RTPC();
|
||||
public bool setGlobally = false;
|
||||
public AkTimelineRtpcPlayableBehaviour template = new AkTimelineRtpcPlayableBehaviour();
|
||||
|
||||
public void SetupClipDisplay()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (owningClip != null)
|
||||
owningClip.displayName = RTPC.Name;
|
||||
#endif
|
||||
}
|
||||
|
||||
public UnityEngine.Timeline.TimelineClip owningClip { get; set; }
|
||||
|
||||
UnityEngine.Timeline.ClipCaps UnityEngine.Timeline.ITimelineClipAsset.clipCaps
|
||||
{
|
||||
get { return UnityEngine.Timeline.ClipCaps.Looping & UnityEngine.Timeline.ClipCaps.Extrapolation & UnityEngine.Timeline.ClipCaps.Blending; }
|
||||
}
|
||||
|
||||
public override UnityEngine.Playables.Playable CreatePlayable(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject gameObject)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkTimelineRtpcPlayableBehaviour>.Create(graph, template);
|
||||
var b = playable.GetBehaviour();
|
||||
b.RTPC = RTPC;
|
||||
b.setGlobally = setGlobally;
|
||||
b.gameObject = gameObject;
|
||||
return playable;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.CustomEditor(typeof(AkTimelineRtpcPlayable), true)]
|
||||
public class Editor : UnityEditor.Editor
|
||||
{
|
||||
private AkTimelineRtpcPlayable playable;
|
||||
private UnityEditor.SerializedProperty RTPC;
|
||||
private UnityEditor.SerializedProperty setGlobally;
|
||||
private UnityEditor.SerializedProperty Behaviour;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
playable = target as AkTimelineRtpcPlayable;
|
||||
if (playable)
|
||||
playable.SetupClipDisplay();
|
||||
|
||||
RTPC = serializedObject.FindProperty("RTPC");
|
||||
setGlobally = serializedObject.FindProperty("setGlobally");
|
||||
Behaviour = serializedObject.FindProperty("template");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
|
||||
|
||||
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
|
||||
{
|
||||
UnityEditor.EditorGUILayout.PropertyField(RTPC, new UnityEngine.GUIContent("RTPC: "));
|
||||
UnityEditor.EditorGUILayout.PropertyField(setGlobally, new UnityEngine.GUIContent("Set Globally: "));
|
||||
}
|
||||
|
||||
if (Behaviour != null)
|
||||
UnityEditor.EditorGUILayout.PropertyField(Behaviour, new UnityEngine.GUIContent("Animated Value: "), true);
|
||||
|
||||
if (playable)
|
||||
playable.SetupClipDisplay();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //#if UNITY_EDITOR
|
||||
}
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f7c50b2d75b1b64b9fa3557b1c37612
|
||||
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
|
||||
Technology released in source code form as part of the game integration package.
|
||||
The content of this file may not be used without valid licenses to the
|
||||
AUDIOKINETIC Wwise Technology.
|
||||
Note that the use of the game engine is subject to the Unity(R) Terms of
|
||||
Service at https://unity3d.com/legal/terms-of-service
|
||||
|
||||
License Usage
|
||||
|
||||
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
|
||||
this file in accordance with the end user license agreement provided with the
|
||||
software or, alternatively, in accordance with the terms contained
|
||||
in a written agreement between you and Audiokinetic Inc.
|
||||
Copyright (c) 2026 Audiokinetic Inc.
|
||||
*******************************************************************************/
|
||||
|
||||
#if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
#define AK_ENABLE_TIMELINE
|
||||
#endif
|
||||
#if AK_ENABLE_TIMELINE
|
||||
|
||||
[UnityEngine.Timeline.TrackColor(0.32f, 0.13f, 0.13f)]
|
||||
// Specifies the type of Playable Asset this track manages
|
||||
[UnityEngine.Timeline.TrackClipType(typeof(AkTimelineRtpcPlayable))]
|
||||
// Use if the track requires a binding to a scene object or asset
|
||||
[UnityEngine.Timeline.TrackBindingType(typeof(UnityEngine.GameObject))]
|
||||
public class AkTimelineRtpcTrack : UnityEngine.Timeline.TrackAsset
|
||||
{
|
||||
public override UnityEngine.Playables.Playable CreateTrackMixer(UnityEngine.Playables.PlayableGraph graph, UnityEngine.GameObject gameObject, int inputCount)
|
||||
{
|
||||
var playable = UnityEngine.Playables.ScriptPlayable<AkTimelineRtpcPlayableBehaviour>.Create(graph, inputCount);
|
||||
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
{
|
||||
var rtpcPlayable = (clip.asset as AkTimelineRtpcPlayable);
|
||||
rtpcPlayable.owningClip = clip;
|
||||
rtpcPlayable.SetupClipDisplay();
|
||||
}
|
||||
|
||||
return playable;
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
var clips = GetClips();
|
||||
foreach (var clip in clips)
|
||||
(clip.asset as AkTimelineRtpcPlayable).SetupClipDisplay();
|
||||
}
|
||||
}
|
||||
#endif // AK_ENABLE_TIMELINE
|
||||
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3d4756340f38734286b39038ecc7df9
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "com.audiokinetic.wwise.timeline",
|
||||
"version": "2024.1.0",
|
||||
"displayName": "Wwise Unity Timeline",
|
||||
"description": "Wwise support for Unity timeline",
|
||||
"unity": "2021.3",
|
||||
"unityRelease": "32f1",
|
||||
"dependencies": {
|
||||
"com.unity.timeline": "1.1.0"
|
||||
},
|
||||
"keywords": [
|
||||
"Wwise",
|
||||
"wwise",
|
||||
"timeline",
|
||||
"audiokinetic",
|
||||
"ak",
|
||||
"Audiokinetic",
|
||||
"Timeline"
|
||||
],
|
||||
"author": {
|
||||
"name": "Audiokinetic Inc.",
|
||||
"email": "info@audiokinetic.com",
|
||||
"url": "https://www.audiokinetic.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc16cb2f77bdd4748afec160fb79503d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user