com.unity.cloud.gltfast icon indicating copy to clipboard operation
com.unity.cloud.gltfast copied to clipboard

GameObjectExport SaveToFileAndDispose does not catch exceptions - expected?

Open andypoly opened this issue 11 months ago • 4 comments

Describe the bug If I run (GameObjectExport).SaveToFileAndDispose I need to wrap it in try catch statements to catch any errors such as "Access to the path "xxx" is denied" (which can occur in GltfWriter->SaveToFileAndDispose on "var outStream = new FileStream(path, FileMode.Create);" for example)

Not sure if this is expected or the code should catch these itself?! The export example does not catch such exceptions so it seems wrong: https://docs.unity3d.com/Packages/[email protected]/manual/ExportRuntime.html

To Reproduce Try to export a gltf file to a path with access denied

Expected behavior catch exceptions in API?

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • glTFast version Latest 6.10
  • Unity Editor version [e.g. 2021.2.1f1] NA 2022 LTS
  • Render Pipeline and version [e.g. Universal Render Pipeline 12.0] NA
  • Platform: [e.g. Editor, Windows Player, iOS] Editor

andypoly avatar Jan 07 '25 09:01 andypoly

Could it be that it's related to this issue? https://discussions.unity.com/t/async-and-uncaught-exceptions/824272

(I.e. are you calling it directly or indirectly from a method like async Task Start(), async Task Awake(), i.e. an async Task of a method called by Unity instead of an async void one?)

RichardWepnerPD avatar Jan 22 '25 16:01 RichardWepnerPD

it's called from an async void function which is called from a synchronous function. I'm not clear why we can't just have void GoAwayAndExportOrImport(Action callback) instead of this forced async workflow which is out of sync (pun intended) with usual Unity code it seems, but to explore it:

You (certainly I) need to tell the program (as a whole) an import or export has finished, so what is the best path. Can you have:

async void ExportSomething(GameObject obj, someDelegate result)
{
  //build the GameObjectExport export;
  await export.SaveToFileAndDispose(name);//run on any thread?!
  result?.Invoke(success);//call on main thread
}

void StandardFunction()
{
  ExportSomething(obj,delegate);
}

The async idea is kind of all or nothing, it is out of step with delegates isn't it?

I think that thread seems to show the issues with introducing async into the Unity programming world

andypoly avatar Jan 22 '25 17:01 andypoly

async can be daunting at first (to me it was), but it's actually quite powerful.

I deliberately don't offer non-async overloads, as that is bad practice (according to the Microsoft Framework design guidelines, IIRC).

In this case I probably did not take good care of handling exceptions. Moreover today I fixed a bug where exports (when started from menu entries) potentially made the Editor unresponsive.

I'll have a look at your error soon.

atteneder avatar Jan 24 '25 21:01 atteneder

Those seem to work just fine:

try
            {
                var outStream = new FileStream(destinationFilePath, FileMode.Create);
                
                // Async glTF export
                var success = await export.SaveToStreamAndDispose(outStream);

                if (!success)
                {
                    Debug.LogError("Something went wrong exporting a glTF");
                }
            }
            catch (DirectoryNotFoundException e)
            {
                Debug.LogException(e);
            }

or

            try
            {
                // Async glTF export
                var success = await export.SaveToFileAndDispose(destinationFilePath);

                if (!success)
                {
                    Debug.LogError("Something went wrong exporting a glTF");
                }
            }
            catch (DirectoryNotFoundException e)
            {
                Debug.LogException(e);
            }

Those are working in playmode, but I also tested it in the editor export.

Could you provide an example that reproduces the error?

atteneder avatar Mar 14 '25 12:03 atteneder