SolidAlloy / GenericUnityObjects

Generic UnityEngine.Objects
Other
166 stars 15 forks source link

[DidReloadScripts] Argument Exception: assemblyString cannot have zero length #39

Open FahrenheitKid opened 10 months ago

FahrenheitKid commented 10 months ago

I've just installed this through the package manager and it shows this error when I Try to use the Creatable attribute or [CreateGenericAssetMenu]. It doesn't let me create anything, my Create dropdown menu doesn't show the generic scriptable objects

Screenshot_11

orkuncinfer commented 7 months ago

also having this issue

JevinLevin commented 1 month ago

Same here, I assume its broken in recent versions sadly

12Acorns commented 4 days ago

This seems to be caused by the following function:

/// <summary>Returns the assembly name of the class implemented by this script.</summary>
/// <param name="script">The script to search for assembly in.</param>
/// <returns>
/// The assembly name without the .dll extension, or an empty string if the assembly was not found.
/// </returns>
[PublicAPI, NotNull] public static string GetAssemblyName(this MonoScript script)
{
        string assemblyName = script.Internal_GetAssemblyName();
        int lastDotIndex = assemblyName.LastIndexOf('.');
        return /* Here >> */ lastDotIndex == -1 /* << */ ? string.Empty : assemblyName.Substring(0, lastDotIndex);
}

I think it needs to be:

[PublicAPI, NotNull] public static string GetAssemblyName(this MonoScript script)
{
        string assemblyName = script.Internal_GetAssemblyName();
        int lastDotIndex = assemblyName.LastIndexOf('.');
        if(assemblyName == null || assemblyName == string.Empty)
        {
                return string.Empty;
        }
        return lastDotIndex == -1 ? assemblyName : assemblyName.Substring(0, lastDotIndex);
}

It seems the author assumed that if the dot index is -1 then the assembly is null.

12Acorns commented 4 days ago

##Temporary fix##

Follow this: https://docs.unity3d.com/Manual/upm-embed.html

Copy 'Library\PackageCache\com.solidalloy.util@[VERSION HERE]' to 'Packages\' and remove the '@[VERSION HERE]' Using the one moved to Packages, edit 'MonoScriptExtensions.cs' replacing the original 'GetAssemblyName(...)' with the fix below:

[PublicAPI, NotNull] public static string GetAssemblyName(this MonoScript script)
{
        string assemblyName = script.Internal_GetAssemblyName();
        int lastDotIndex = assemblyName.LastIndexOf('.');
        if(assemblyName == null || assemblyName == string.Empty)
        {
                return string.Empty;
        }
        return lastDotIndex == -1 ? assemblyName : assemblyName.Substring(0, lastDotIndex);
}

Repeat the above of moving the package to 'Packages' for 'com.solidalloy.type-references@[VERSION HERE]' and 'com.solidalloy.generic-unity-objects@[VERSION HERE]', make sure to remove '@[VERSION HERE]' once moved.

Next, to fix an error with the popup menu, change '_closeButtonStyle' value, from 'GUIHelper.cs' in 'com.solidalloy.util', to 'EditorStyles.toolbarTextField' and reference UnityEditor. (See #10)

Go to 'MonoScriptExtensions.cs' and change 'GetClassType' to:

[PublicAPI, CanBeNull] public static Type GetClassType(this MonoScript script, Type _type, string className = null)
{
    Type simpleType = script.GetClass();
    if (simpleType != null)
        return simpleType;

    string foundClassName = string.IsNullOrEmpty(className) ? GetFirstClassFromText(script.text) : GetFirstClassWithName(script.text, className);

    if (string.IsNullOrEmpty(foundClassName))
        return null;

    //string assemblyName = script.GetAssemblyName();
    string assemblyName = _type.GetShortAssemblyName();
Assembly assembly;

    try
    {
        assembly = Assembly.Load(assemblyName);
    }
    catch (Exception e)
    {
        // Whatever caused this exception, the type cannot be loaded, so disregard it as null.
        if (e is FileNotFoundException || e is FileLoadException)
            return null;

        throw;
    }

    string namespaceName = script.GetNamespaceName();
    string fullTypeName = namespaceName == string.Empty ? foundClassName : $"{namespaceName}.{foundClassName}";

    Type type = assembly.GetType(fullTypeName);
    return type;
}

After, in 'TypeReferenceEditor.cs' in ''TryUpdatingTypeUsingGUID' add Type classType = AssetDatabase.GetMainAssetTypeFromGUID(new GUID(GUID)); before var type = script.GetClassType(); and in 'script.GetClassType' ass to the args 'classType' Will look like: var type = script.GetClassType(classType);

In 'AssetHelper.cs' at 'GetAssetDetails' replace with:

public static bool GetAssetDetails(Type type, [CanBeNull] out string GUID, out MonoScript monoScript)
{
    GUID = string.Empty;
    monoScript = null;

    if (type == null)
        return false;

    if (type.IsGenericType)
        type = type.GetGenericTypeDefinition();

    string typeNameWithoutSuffix = type.Name.StripGenericSuffix();

    foreach (string guid in AssetDatabase.FindAssets($"t:MonoScript {typeNameWithoutSuffix}"))
    {
        string assetPath = AssetDatabase.GUIDToAssetPath(guid);
        var asset = AssetDatabase.LoadAssetAtPath<MonoScript>(assetPath);

        if (asset == null || asset.GetClassType(type, typeNameWithoutSuffix) != type)
            continue;

        GUID = guid;
        monoScript = asset;
        return true;
    }

    return false;
}

In 'TypeInfo.cs' replace 'TypeAtGUIDSame' with:

private bool TypeAtGUIDIsSame()
{
    string path = AssetDatabase.GUIDToAssetPath(GUID);
    if (path.Length == 0)
        return false;

    var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
    if (monoScript == null)
        return false;
return Type == monoScript.GetClassType(Type);
}

That should be it.