I'm working on a custom ScriptedImporter
-- let's call it LmmsImporter
-- that loads project files from the LMMS sequencer as AudioClip
s. I don't parse the project file; instead, I expect users to install LMMS, configure its location, then store their project files inside their Assets
directory. After the asset settings are configured, the import process looks like this:
- Create command-line arguments based on the properties offered by
LmmsImporter
- Get a temporary path inside the project's
Temp
directory (not the OS's equivalent) - Spawn an LMMS process that renders the imported project file to the path given by (2), with the arguments given by (1).
- Wait for the process to complete.
- Load the
AudioClip
at "runtime" (i.e. in an editor script, not as an imported asset) withUnityWebRequestMultimedia.GetAudioClip
- Clone the
AudioClip
. - Set the cloned
AudioClip
to be the LMMS project asset's main object, as described here. - Save the imported asset, then delete the original audio file generated by (3).
Everything up to but not including step 7 works as expected. In fact, even step 7 appears to work as expected. But when I open up the imported AudioClip
, it has no samples. When I try to play the preview in the editor, I get this error in the editor console:
Error: Cannot create FMOD::Sound instance for resource , (Error loading file. ) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
What makes this weird is that:
- The sound is properly rendered by LMMS and saved to the filesystem. Nothing unusual happens here.
- Playing the
AudioClip
inside the importer script immediately after it's loaded (i.e. while still inOnImportAsset
) withAudioSource.PlayAtPoint
works as expected. - The data is properly cloned; I checked, the arrays are equal.
- I do not receive any errors or exceptions except those that I've already described, not even from LMMS.
This is an excerpt of my code with the parts I think are most relevant:
using System;
using System.Diagnostics;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEditor;
using UnityEditor.Experimental.AssetImporters;
[ScriptedImporter(1, new[] { "mmp", "mmpz" })]
public class LmmsImporter : ScriptedImporter
{
// Properties omitted for brevity
public override void OnImportAsset(AssetImportContext ctx)
{
var relativeTempPath = FileUtil.GetUniqueTempPathInProject();
var projectDir = Path.GetDirectoryName(Application.dataPath);
var absoluteAssetPath = Path.Combine(projectDir, assetPath);
var tempPath = Path.Combine(projectDir, relativeTempPath);
try
{
using (Process lmms = new Process())
{
// Process invocation details and error handling omitted for brevity
// ...one successfully rendered WAV, OGG, or MP3 file later...
using (var request = UnityWebRequestMultimedia.GetAudioClip(new Uri(tempPath), audioFormat))
{
var handler = request.downloadHandler as DownloadHandlerAudioClip;
handler.compressed = false;
handler.streamAudio = false;
request.timeout = LOAD_MEDIA_TIMEOUT;
var operation = request.SendWebRequest();
while (!(request.isHttpError || request.isNetworkError || handler.isDone)) ;
// Let the request finish, unless we get an error (possibly including a timeout)
var clip = DownloadHandlerAudioClip.GetContent(request);
clip.LoadAudioData();
var assetName = Path.GetFileNameWithoutExtension(assetPath);
var clone = AudioClip.Create("Clip", clip.samples, clip.channels, clip.frequency, false);
using (var so = new SerializedObject(clone))
{
var samples = new float[clip.samples * clip.channels];
clip.GetData(samples, 0);
clone.SetData(samples, 0);
// Everything above this line works fine
ctx.AddObjectToAsset("AudioClip", clone);
ctx.SetMainObject(clone);
so.ApplyModifiedProperties();
EditorUtility.SetDirty(clone);
}
}
}
}
catch (Exception e)
{
ctx.LogImportError($"Failed import with {e.GetType()}: {e.Message}");
}
}
private const int LOAD_MEDIA_TIMEOUT = 5; // seconds
}
I'm using Unity 2019.1.7f1 Personal, on Ubuntu 19.04. Is this a bug, or am I doing something wrong?