Wednesday, September 15, 2021

Flynn: Son of Crimson!

A charming and beautiful platform game built on GameMaker, Flynn is now available on Switch, PS4, Xbox, and Steam!  We worked with Humble and Studio Thunderhorse to bring the title to all three console platforms.  Explore Rosantica with your trusty dog, Dex, by your side.  Push back the scourge and discover the truth behind what threatens your home!


Friday, September 3, 2021

Fixing Invalid Frameworks Folder in iOS App Store Upload

Upon moving a couple of recent projects to 2020.4, we learned that recent versions of Unity apparently have problems when exporting iOS applications.  They’ll run and test fine, but upon uploading to the App Store, you’ll get an error.  This reads:

Invalid Bundle. The bundle at 'my.app/Frameworks/UnityFramework.framework' contains disallowed file 'Frameworks'.

We spent a long while trying suggestions on forum threads and reviewing the build behavior before we came up with a solution that works for us.  This also handles a further error we got after submitting the iOS app, which reads:

Invalid Swift Support - The SwiftSupport folder is empty. Rebuild your app using the current public (GM) version of Xcode and resubmit it.

You can use the solution we created by saving the below code out to a file called UpdateXcodeBuildSystemPostProcessor.cs and putting it in your project’s assets/editor folder.

using System.IO;

using UnityEngine;

using UnityEditor;

using UnityEditor.Callbacks;

using UnityEditor.iOS.Xcode;


#if UNITY_IOS || UNITY_TVOS

// Create specific aliases for iOS.Xcode imports.

// Unity Editor on macOS can report a conflict with other plugins

using PlistDocument = UnityEditor.iOS.Xcode.PlistDocument;

using PlistElementDict = UnityEditor.iOS.Xcode.PlistElementDict;

#endif


public class UpdateXcodeBuildSystemPostProcessor : MonoBehaviour

{

    [PostProcessBuild(999)]

    public static void OnPostProcessBuild(BuildTarget buildTarget, string path)

    {

        if (buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.tvOS)

        {

            UpdateXcodeBuildSystem(path);

        }

    }


    private static void UpdateXcodeBuildSystem(string projectPath)

    {

        string workspaceSettingsPath = Path.Combine(projectPath,

            "Unity-iPhone.xcodeproj/project.xcworkspace/xcshareddata/" +

            "WorkspaceSettings.xcsettings");


        if (File.Exists(workspaceSettingsPath))

        {

            // Read the plist document, and find the root element

            PlistDocument workspaceSettings = new PlistDocument();

            workspaceSettings.ReadFromFile(workspaceSettingsPath);

            PlistElementDict root = workspaceSettings.root;


            // Modify the document as necessary.

            bool workspaceSettingsChanged = false;

            // Remove the BuildSystemType entry because it specifies the

            // legacy Xcode build system, which is deprecated


            if (root.values.ContainsKey("BuildSystemType"))

            {

                root.values.Remove("BuildSystemType");

                workspaceSettingsChanged = true;

            }


            // If actual changes to the document occurred, write the result

            // back to disk.

            if (workspaceSettingsChanged)

            {

                Debug.Log("UpdateXcodeBuildSystem: Writing updated " +

                    "workspace settings to disk.");


                try

                {

                    workspaceSettings.WriteToFile(workspaceSettingsPath);

                }

                catch (System.Exception e)

                {

                    Debug.LogError(string.Format("UpdateXcodeBuildSystem: " +

                        "Exception occurred writing workspace settings to " +

                        "disk: \n{0}",

                        e.Message));

                    throw;

                }

            }

            else

            {

                Debug.Log("UpdateXcodeBuildSystem: workspace settings did " +

                    "not require modifications.");

            }

        }

        else

        {

            Debug.LogWarningFormat("UpdateXcodeBuildSystem: could not find " +

                "workspace settings files [{0}]",

                workspaceSettingsPath);

        }


        // Get the path to the Xcode project

        string pbxProjectPath = PBXProject.GetPBXProjectPath(projectPath);

        var pbxProject = new PBXProject();


        // Open the Xcode project

        pbxProject.ReadFromFile(pbxProjectPath);


        // Get the UnityFramework target GUID

        string unityFrameworkTargetGuid =

            pbxProject.GetUnityFrameworkTargetGuid();


        // Modify the Swift version in the UnityFramework target to a

        // compatible string

        pbxProject.SetBuildProperty(unityFrameworkTargetGuid,

            "SWIFT_VERSION", "5.0");


        // Write out the Xcode project

        pbxProject.WriteToFile(pbxProjectPath);


        Debug.Log("UpdateXcodeBuildSystem: update Swift version in Xcode " +

            "project.");

    }

}

We do two things here:

  1. Unity writes out the Xcode project using Xcode’s “Legacy Build System”, which is currently deprecated in Xcode 12.5.1 where this was tested.  We remove the “BuildSystemType” key from the Xcode workspace settings so that Xcode uses the default build system.
  2. Once Xcode is using the default build system, it no longer recognizes the format of the Swift version that Unity writes out in the Xcode project.  Unity writes something like “5 0 5 1”, but Xcode expects “5.0”.  So we forcibly set the Swift version to a value Xcode currently understands.
You could do this manually.  After making a Unity build for iOS, you would open the Xcode project, go to the File menu, select Project Settings, and change the Build System in the drop-down menu there.  Changing this through Xcode will automatically fix the Swift version value.

Thanks to everyone on the various Unity forum threads who have been wrestling with this problem.

Thanks also to user uannoymejo on this forum thread for bringing up the Xcode build system.

Wednesday, September 1, 2021

Apsulov: End of Gods

Apsulov is a stunning action-horror exploration of Norse mythology, now available on the PS4 and Switch as either physical disk or digital download.  Creep through dark sci-fi hallways as you explore the worlds of Yggdrasil, evade horrific creatures, and understand what brought you to this place.  We worked with Digerati to bring this Unreal-based title to all three consoles.