Issues with the C4D to Unity Import python plugin - missing some types of objects



  • Hi Maxime! Thanks for the info about Poly Reduction and ideas with ExecutePasses 😄 I will try that immediately

    I am currently on the latest, R21.115. However I tested this same stuff happening on R20 as well.

    Cloners are usually okay as long as they don't reference a spline (which now makes sense knowing about the cache thing).

    However, I am right now getting a very strange thing where a cloner and a null with dynamics tag (applied to many children) go from importing normally to not.. depending on how many children are in the Fracture.1 null. But perhaps this is a separate issue. When testing with the manual FBX export, it takes some time.. I am assuming it has to animate the dynamics tag to it's current position before exporting... Perhaps unity does not know how to wait for this operation unless it is very fast. Perplexing why it would have anything to do with the cloner, though, as it is not in any way connected to the Fracture.1 null or the dynamics system. Removing one or the other object results in a successful import into unity. The attached scene fails import into unity unless you delete the cloner, the dynamics tag attached to the null, or at least 10-50 more children of the null.fbxtest_v03.c4d. This is different than the original issue I posted about, where the scene import does not fail, but merely comes in with missing objects.

    I will try the ExecutePasses thing now! Thanks again!

    Leah



  • ExecutePasses worked for Polygon Reduction objects! That is a huge benefit to LOD versioning in Unity 👍 👍 👍

    Added here:

    #
    #SNIPPET FROM MAIN CODE
    #
    
    class ExportThread(threading.C4DThread):
    
        def __init__(self, doc, exportPath):
            self.doc = doc
            self.status = False
            self.exportPath = exportPath
            #ADDED THE LINE BELOW
            doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_EXPORT)
    
        def Main(self):
            # Export document to FBX
            self.status = documents.SaveDocument(self.doc, self.exportPath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, FBX_EXPORTER_ID)
    
        def GetStatus(self):
            return self.status
    
    #
    #SNIPPET FROM MAIN CODE
    #
    

    Cloners are still not working if they reference a spline. Any ideas why that is still giving us trouble?

    Leah



  • Sometime its needed to call it multiple time. So try to call ExcecutePass multiple time (maximum 3 is enough).

    Cheers,
    Maxime



  • @m_adam Shoot, tried calling it 3X and still nothing on the cloner (spline mode) object.

    (failing) test file attached
    fbxtest_v04.c4d



  • Currently the Spline Deformer breaks other objects in the scene, while the Bevel Deformer and Cloner Object in Spline Object mode only break themselves.

    GetContour? SetOptimizeCache? Anything else worth investigating? Maybe this is happening because it's being called via Unity automatically?



  • If I understand correctly, the issue is that the spline are not saved in the fbx?

    If yes make sure to set fbxExport[c4d.FBXEXPORT_SPLINES] = True

    At least here is working correctly, loading the saved fbx give me back the same result than previously.
    Cheers,
    Maxime.



  • @m_adam Then maybe the issue is that the command line fbx export is being executed from within Unity and not through C4D itself?

    Is there some kind of document referencing error that could happen if another program (other than C4D) were to call this script? Would caches behave differently?

    To answer your question, yes, I have FBXEXPORT_SPLINES set to True



  • I forgot to mention, Instances also fail to cache into Unity as well.

    I am thinking these are all related and to do with the cache being unavailable unless the script is being run within the C4D gui



  • Hi @jenandesign sorry for the delay and to not have spotted the issue earlier.

    But SaveDocument needs to be called in the main thread. So one solution for you is to send a CoreMessage with c4d.SendCoreMessage to catch it in a MessageData and process it.

    import c4d
    
    FBX_EXPORTER_ID = 1026370
    
    FBXEXPORT_TEXTURES = True
    FBXEXPORT_EMBED_TEXTURES = False
    FBXEXPORT_SAVE_NORMALS = True
    FBXEXPORT_ASCII = False
    
    
    
    # Main function
    def main():
        sourcePath = r"C:\Users\graphos\Downloads\fbxtest_v04.c4d"
        destinationPath = r"C:\Users\graphos\Documents\test.fbx"
        
        plug = c4d.plugins.FindPlugin(FBX_EXPORTER_ID, c4d.PLUGINTYPE_SCENESAVER)
        if plug is None:
            logger.appendMessage("FBX Export plugin not found")
            return False
    
        op = {}
        # Retrieve FBX Eporter settings object
        if plug.Message(c4d.MSG_RETRIEVEPRIVATEDATA, op) :
            if "imexporter" not in op:
                return False
    
            # BaseList2D object stored in "imexporter" key hold the settings
            fbxExport = op["imexporter"]
            if fbxExport is None :
                return False
    
            # Change export settings
            
            #THE FOLLOWING TWO LINES OF CODE WERE ADDED TO FIX SDS OBJECT IMPORT
            fbxExport[c4d.FBXEXPORT_SDS_SUBDIVISION] = True
            fbxExport[c4d.FBXEXPORT_SDS] = False
            fbxExport[c4d.FBXEXPORT_TEXTURES] = FBXEXPORT_TEXTURES
            fbxExport[c4d.FBXEXPORT_EMBED_TEXTURES] = FBXEXPORT_EMBED_TEXTURES
            fbxExport[c4d.FBXEXPORT_SAVE_NORMALS] = FBXEXPORT_SAVE_NORMALS
            fbxExport[c4d.FBXEXPORT_ASCII] = FBXEXPORT_ASCII
    
            doc = c4d.documents.LoadDocument(sourcePath, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS, None)
            status = False
            doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_EXPORT)
    
            # Export document to FBX
            status = c4d.documents.SaveDocument(doc, destinationPath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, FBX_EXPORTER_ID)
            c4d.documents.KillDocument(doc)
    
            # Retrieve export status and return it
            print status
    
    
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    Cheers,
    Maxime.



  • Hi Maxime! Thanks for the suggestion, though I don't quite understand what you mean by your example... I don't see any use of SendCoreMessage in your snippet?

    SaveDocument is already present in the original code in the extended threading class "ExportThread" under definition Main(). How are you suggesting I change this?

    Thank you for the continued help ☺



  • SaveDocument is already present in the original code in the extended threading class "ExportThread"

    TO not make it happens in a thread.
    So to directly execute it in ExecuteConversion.

    The use of SendCoreMessage is a way, from a thread (and it's the case for you in ExportThread::Main) to send a message, that Cinema 4D will process on the Main thread (I didn't use in my code because in my case I'm in the main thread).
    So you can react to this message and do something (in your case SaveDocument). It was just for your information, regarding what's your thread is doing (only calling SaveDocument) I would say that using a thread here make no sense, and you should directly call SaveDocument in your ExecuteConversion function.

    Hope it's more clear.
    Cheers,
    Maxime.