1

in Unity I simply have a file, afile.ts, sitting in Assets/

enter image description here

In the built Xcode, I simply want it to be sitting in the project folder (really, anywhere is fine) included in the project.

enter image description here

You do this using

    project.AddFileToBuild(g, something something something);

But I plain can not figure it out.

(Obviously it is totally undocumented at Unity.)

How is it done? Just the one simple file - actually copy it from Assets/filename to the Xcode project (and it will have target membership and be in the main bundle).

Here is a perfect Unity build post script BuildPostProcessor.cs, which is amazing and does everything else:

https://stackoverflow.com/a/54370793/294884

but I cannot copy over a damned file! How to?


Note - alternative

Note. If you very simply put a file in Unity's badly-named magic folder:

/StreamingAssets

in fact it does exactly what is under discussion in this QA.

  1. Unity .. have a file music.mp4 or mesh.txt in /StreamingAssets
  2. build to Xcode
  3. you'll have music.mp4 or mesh.txt, in the Xcode project, included in the Target
  4. and the iOS location will be ...

the folder name on iOS for whatever reason becomes: /Data/Raw

Thus your low-level iOS side code would be:

instead of, for example:

CFURLRef imageURL = CFBundleCopyResourceURL(
  mainBundle, CFSTR("music"), CFSTR("mp4"), NULL);

you will have:

CFURLRef imageURL = CFBundleCopyResourceURL(
  mainBundle, CFSTR("Data/Raw/music"), CFSTR("mp4"), NULL);

That works fine. But surely we can learn how to use '.AddFileToBuild` which seems to exist for the purpose.

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • 1
    Never used this before, so just out of curiousity. Is there a reason to use the project.AddFiletoBuild() method? (its indeed poorly documented and you seem to use it properly...) instead of just copying the file using `System.Io.File.Copy` directly? At first sight it looks like it just makes a straight copy, and doesn't modify it? For sanity's sake did you ascertain all values are set properly? only other "docs" i could find was this example https://gist.github.com/sanukin39/997d8364d16c5c27dae75a3bc1f1f045 . It may be of some use (if you hadn't seen it yet). – Remy Jan 10 '19 at 23:05
  • here's some random I found with AddFileToBuild .. https://github.com/OneSignal/OneSignal-Unity-SDK/blob/master/OneSignalExample/Assets/OneSignal/Editor/PostProcessBuildPlayer_iOS.cs .. https://gist.github.com/suakig/ffb64f48c800e9dea545 – Fattie Jan 11 '19 at 11:10
  • (confusingly some people seem to use it for frameworks - in fact "AddFrameworkToProject" does that perfectly ...) – Fattie Jan 11 '19 at 11:11
  • or .. https://forum.unity.com/threads/postprocessbuild-failed-to-copy-file.413001/ ... nobody knows how to use it! :) .. https://forum.unity.com/threads/postprocess-build-scripts-adding-files-to-the-xcode-project.266247/ – Fattie Jan 11 '19 at 11:12
  • 1
    just BTW @remy_rm it looks like you can use StreamingAssets for this issue .. I edited in a few words on that :O – Fattie Jan 11 '19 at 14:42

2 Answers2

4

FTR I did stumble on to some Unity example code (in an unrelated example project) which may help ..

public class MyBuildPostprocessor
{
    // Build postprocessor. Currently only needed on:
    // - iOS: no dynamic libraries, so plugin source files have to be copied into Xcode project
    [PostProcessBuild]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    {
        if (target == BuildTarget.iOS)
            OnPostprocessBuildIOS(pathToBuiltProject);
    }

    private static void OnPostprocessBuildIOS(string pathToBuiltProject)
    {
        // We use UnityEditor.iOS.Xcode API which only exists in iOS editor module
        #if UNITY_IOS

        string projPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";

        UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject();
        proj.ReadFromString(File.ReadAllText(projPath));
        string target = proj.TargetGuidByName("Unity-iPhone");

        Directory.CreateDirectory(Path.Combine(pathToBuiltProject, "Libraries/Unity"));

        string[] filesToCopy = new string[]
        {
            "PlatformBase.h",
            "RenderAPI_Metal.mm",
            "RenderAPI_OpenGLCoreES.cpp",
            "RenderAPI.cpp",
            "RenderAPI.h",
            "RenderingPlugin.cpp",
        };

        for(int i = 0 ; i < filesToCopy.Length ; ++i)
        {
            var srcPath = Path.Combine("../PluginSource/source", filesToCopy[i]);
            var dstLocalPath = "Libraries/" + filesToCopy[i];
            var dstPath = Path.Combine(pathToBuiltProject, dstLocalPath);
            File.Copy(srcPath, dstPath, true);
            proj.AddFileToBuild(target, proj.AddFile(dstLocalPath, dstLocalPath));
        }

        File.WriteAllText(projPath, proj.WriteToString());
        #endif // #if UNITY_IOS
    }
}
Fattie
  • 27,874
  • 70
  • 431
  • 719
3

I got it to kinda work ( still Xcode highlights folder in red ) but my plugin recognize this file correctly

You have to add your file to /StreamingAssets folder this will make your file actually appear in "Data/Raw/" path in Xcode project. Then just ad this code to your [PostProcessBuild] function

    PBXProject project = new PBXProject();
    string sPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
    project.ReadFromFile(sPath);
    string tn = PBXProject.GetUnityTargetName();
    string g = project.TargetGuidByName(tn);

    project.AddFileToBuild(g, project.AddFile("Data/Raw/<YourFile.png>", "<YourPathInXcodeProject>/<YourFile.png>"));

    File.WriteAllText(sPath, project.WriteToString());

this will add your file to desired path in "yellow" folders not "blue" like /StreamingAssets dose.

[I am not an expert on Xcode but i noticed that in "blue" folders functions for changing apps icon couldn't find them there, only after adding my alternative icons to yellow folder Xcode gladly recognized then as files]

Kuba Jurek
  • 61
  • 3
  • actually yes Kuba - notice I mention down the bottom that as an alternative, you can just use the "StreamingAssets/" folder! thanks! – Fattie Jan 15 '19 at 12:07
  • That's true. But adding file just to StreamingAssets folder was not enough in my case. Because for some reason your file has to be in "yellow" folder if you want to use function to change apps icon. And that function happens to do so. I hope it will help some1 – Kuba Jurek Jan 15 '19 at 14:42
  • hi kuba ! Right, if you DO want to use StreamingAssets/ . One possibility is note that in Xcode the file ends up in: /Data/Raw . So it's like: .. main bundle .. /Data/Raw/filename.txt. You can in fact access it then in iOS from that location, main-bundle/Data/Raw/. YES it is indeed already added to the target, but the location to find it is that weird location, /Data/Raw. – Fattie Jan 15 '19 at 14:46
  • Hi Fattie, Yes location is weird, and you can "change it" (add reference) with this function, first argument is a relative path from the project to the location of your file, and the second is a relative path where you want to add reference in project generated by Unity. Therefore if you don't want to add same weird relative paths specific to your place of building, is easier to add this file to Data/Raw using functionality of StreamingAssets Note : you can change name of the file that you what to be added. – Kuba Jurek Jan 15 '19 at 14:59
  • BTW, do note the answer I put in. that is another way (using a different command) to "actually copy a file to somewhere". it may help! :) – Fattie Jan 15 '19 at 15:00