0
\$\begingroup\$

I have a huge FBX file which contains make animations. I want to split these into different takes by using a C# script file.

It worked, but it happened often that I messed up the FBX file because my script was just not perfect yet.

What I did in such a case was to restore a backup manually.

However, after having to do that over 30 times already, I thought that I could simply copy the original FBX and its meta data and work with the copy.

This way I would not have to backup / restore the original fbx each time.

I would create the copy at the start of my script.

And then I would call my usual code like this:

ModelImporter nModelImporter = (ModelImporter)AssetImporter.GetAtPath(sCopyOfFBXFile);

if (nModelImporter == null)
{
    Debug.LogError("Doh!!!!");
}

To my surprise, the ModelImporter of the newly created copy is "Null".

The next thing that came to my mind was that perhaps Unity misses the ".fbx.meta" file, so I copied the .meta file, too.

The problem would still persist: The ModelImporter was still Null.

The next thing I tried to call

AssetDatabase.SaveAssets();

Still didn't help.

The solution was to stop the script after the creation of the Unity.

In other words: Unity needed some time on its own without the script still running.

Then Unity would work hard and show a progress bar which indicates that it's now processing the newly created .fbx file.

Then I could run another script which would then do the ModelImporter work on the new copy.

However, I don't want to wait that long until Unity has processed the copy, and I don't want to use 2 steps for a process of which I feel could be done in a single script.

I wanted to provide Unity a perfect copy of which it would automatically know that it doesn't have to do any more work on. I thought that providing the .meta file would do this job.

Does anybody know why that is not the case and what I would have to do in order to work without interrupting my script intentionally?

Thank you!

ps: Here is my current file for completeness:

using UnityEngine;
using UnityEditor;
using UnityEditor.VersionControl;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System;
using System.Collections.Generic;

public class NewBehaviourScript : AssetPostprocessor
{
    private static void pCreateNewCopy(string uOrig, string uDest)
    {
        if (File.Exists(uDest))
        {
            File.Delete(uDest);
        }
        File.Copy(uOrig, uDest);
    }

    public static bool pathsFromObject(UnityEngine.Object uAny, out string uAssetFile, out string uAbsolute)
    {
        uAssetFile = "";
        uAbsolute = "";

        try
        {
            string sPathOfFBXInAssetDir = AssetDatabase.GetAssetPath(uAny);
            string sRealPathFromAsset = Application.dataPath + sPathOfFBXInAssetDir.Substring(6);//Remove first 6 chars because they are "Assets" (same as the end of the Application.dataPath)

            uAssetFile = sPathOfFBXInAssetDir;
            uAbsolute = sRealPathFromAsset;

            return true;
        }
        catch (Exception x)
        {
            return false;
        }
    }

    [MenuItem("Tools/FBX/Split")]
    private static void SplitFBX()
    {
        var nSelectedFBXFile = Selection.activeObject;

        string sRelativePath = "";
        string sAbsolutePath = "";

        bool b = pathsFromObject(nSelectedFBXFile, out sRelativePath, out sAbsolutePath);

        string sAbsolutePathCopy = sAbsolutePath.Replace(".fbx", "_split.fbx");
        pCreateNewCopy(sAbsolutePath, sAbsolutePathCopy);

        string sRelativePathCopy = sRelativePath.Replace(".fbx", "_split.fbx");
        AssetDatabase.ImportAsset(sRelativePathCopy, ImportAssetOptions.ForceSynchronousImport);
        //AssetDatabase.SaveAssets(); //not necessary
        ModelImporter nModelImporter = (ModelImporter)AssetImporter.GetAtPath(sRelativePathCopy);
        if (nModelImporter == null)
        {
            Debug.LogError("Doh!!!");
        }
        else
        {
            Debug.Log("All is good!");
        }
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Did you call ImportAsset for your newly copied file, so that Unity would generate a meta file for it with a unique GUID and a ModelImporter with the data you want to access? \$\endgroup\$
    – DMGregory
    Commented Jun 12, 2021 at 22:18
  • \$\begingroup\$ I thought it would automatically do that when I call AssetDatabase.SaveAssets(). However, I did that explicitely now. However, it didn't change anything. ModelImporter is still Null. \$\endgroup\$
    – tmighty
    Commented Jun 12, 2021 at 22:59

1 Answer 1

1
\$\begingroup\$

I found the solution.

The following is wrong:

ModelImporter nModelImporter = (ModelImporter)AssetImporter.GetAtPath(sAbsolutePath);

The following is correct:

ModelImporter nModelImporter = (ModelImporter)AssetImporter.GetAtPath(sRelativePath);

As one can see, AssetImporter.GetPath expects a relative path.

Also, as DMGregory pointed out, the following call is necessary to make Unity aware of a newly created file:

AssetDatabase.ImportAsset(sRelativePathCopy, ImportAssetOptions.ForceSynchronousImport);
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .