Search Unity

Not compiling files during development, but using them during Resource.Load()?

Discussion in 'Editor & General Support' started by EnsurdFrndship, Sep 16, 2017.

  1. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    Hello,
    I have many files with extensions that I renamed to .inf that still kind of 'tie up' my development time (I guess because of the amount of files), so, I added a '~' to the end of my folder, but now, when I use Resource.Load(), those files aren't recognized. I would like for Unity to not compile these files WHILE, at the same time, allow Resource.Load() to use them, and then when I publish my project, those files get published into my project. How would I do this?

    Thank you,
    Michael S. Lowe
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
    What do you mean with "compile"? I guess you're not talking about source code, but assets?

    I assume you just want to by-pass Unity's import pipeline for these type assets?! If that's the case, you might want to take a look at StreamingAssets. Resources.Load won't work with StreamingAssets, but if you by-pass the import pipeline, Unity can't load any of those assets anyway. Files in StreamingAssets can be loaded using the System.IO API for example.
     
  3. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    Yes. If my .inf files contain custom data that is not of any programming language, there would be no point IN them compiling or taking up unnecessary development time IF it is not code that should effect my program. What command would I use to load streaming assets, and when the project publishes can those files be accessed the same way?
     
  4. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    You don't need to put a '~' at the end of the filenames if your file extension was `.inf`. If Unity doesn't recognise the file extension then it won't do anything with the file. So just put the files in your `Resources` directory and use `Resources.Load`.

    edit: actually my bad, Unity does still seem to attempt to reimport the file. But it seems a lot faster when it doesn't know what the file is.

    -sam
     
    Last edited: Sep 17, 2017
  5. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    Thank you, but is there a way to work around that?
     
  6. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    No I don't think there's any easy way around that. The '~' tells Unity to ignore the file, so therefore it won't end up in your build.

    You could leave the '~' there and then write a post-build process that copies the ignore files into your final build.

    -sam
     
  7. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    How do I do that? What is a post-build process? Wouldn't that cause me to have to wait a very long time every time I run my program, instead of during development?
     
  8. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    You use the `PostProcessBuild` attribute to write a method that is called after the build has finished. There's more info here. For example:

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using UnityEditor.Callbacks;
    4.  
    5. public class MyBuildPostprocessor
    6. {
    7.    [PostProcessBuild]
    8.    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    9.    {
    10.        Debug.Log( pathToBuiltProject );
    11.    }
    12. }
    -sam
     
  9. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    If there is a way to copy large amounts of files into my build, and I am dealing with over 31,000 files in a folder with the '~' in front of it, wouldn't I have to wait about 5 or 10 minutes every time I would like my program to run?
     
  10. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    I guess that depends on a few things - the speed of your hard disk and the size of the files in particular. But Unity would be doing that anyway if you weren't doing it yourself.

    You can speed up the process a bit by doing some simple checks to determine if the files should be copied. For example, for a given file, if the file already exists in the destination directory and its timestamp is the same or newer than the file in the project directory, you don't have to copy the file.

    -sam
     
  11. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    It would be nice if there was a way to not ignore certain folders while not having any changes of data in any files in these folders cause Unity to have to update any meta data, and just use those files for opening and reading purposes. Then, when the project gets published is when the data in those files get 'considered' (IF it is important to pass that data along to the published version). It would save development time. Perhaps (upon the developer's request), he/she could have Unity set up so that files in those folders would have Unity make up the meta data file only on the files that are wanted to be opened upon demand (if Resource.Load() and other file opening commands look to the meta data files for its data collection), which MAY slow down the program at runtime, but not during development time, and then deletes itself when the program stops running. Isn't that a good idea for the next version of Unity or for a patch?
     
    Last edited: Sep 18, 2017
  12. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    Unity can't be everything to everyone. It doesn't sound like it would be a high priority issue unfortunately, and it can be solved easily by writing a build post-processor.

    -sam
     
  13. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    I have never wrote a 'build post-processor program' before, and am unfamiliar about how to construct the coding in order to do such an operation. Is that a program that 'tells' Unity how to handle the meta data before it writes the meta files, or what files to pay attention to? If the files in the '~' folder are 'ignored', CAN a post-processor program still work with those files?... and how would I write the code to 'un-ignore' them, and then 're-ignore' them when I stop my program from running?... and wouldn't that cost a lot of processor time?
     
  14. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    No a build post-processor is a method that runs after your build has finished being created. So if you kick off a standalone Windows player build of your game from the build settings menu (or even from the command-line), when that finishes, your post-processor method is run. Then you can do whatever else you need to do to (e.g. copy files around). It's pretty easy. I wrote an example for you here (I haven't tested it though!).

    edit: and in case the gist disappears here's the code itself:
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using UnityEditor.Callbacks;
    4. using System;
    5. using System.IO;
    6.  
    7. public static class CopyFilesBuildPostProcessor
    8. {
    9.     private const string PathToCopy = "PathToFiles";
    10.  
    11.     [PostProcessBuild]
    12.     public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
    13.     {
    14.         // Copy all files from the Unity Assets/{PathToCopy} directory to a directory
    15.         // called {PathToCopy} under the build's output directory.
    16.         var sourceFullPath = Path.Combine(Application.dataPath, PathToCopy);
    17.         var destinationFullPath = Path.Combine(pathToBuiltProject, PathToCopy);
    18.         CopyFiles(sourceFullPath, destinationFullPath);
    19.     }
    20.  
    21.     private static void CopyFiles(string source, string destination)
    22.     {
    23.         var files = Directory.GetFiles(source);
    24.         foreach (var sourceFile in files)
    25.         {
    26.             // Get just the filename for the file, so we can determine whether the file
    27.             // exists in the destination.
    28.             var filename = Path.GetFileName(sourceFile);
    29.             var destinationFile = Path.Combine(destination, filename);
    30.             var exists = File.Exists(destinationFile);
    31.             var doCopy = !exists; // If the file doesn't exist, we definitely need to copy it!
    32.  
    33.             if (exists)
    34.             {
    35.                 // If the file exists at the destination and the source has been modified more
    36.                 // recently than the destination file, we will copy the source file again.
    37.                 var sourceTimestamp = File.GetLastWriteTime(sourceFile);
    38.                 var destinationTimestamp = File.GetLastWriteTime(destinationFile);
    39.                 doCopy = sourceTimestamp > destinationTimestamp;
    40.             }
    41.  
    42.             if (doCopy)
    43.             {
    44.                 try
    45.                 {
    46.                     File.Copy(sourceFile, destinationFile);
    47.                 }
    48.                 catch (Exception e)
    49.                 {
    50.                     Debug.Log("Failed to copy file: " + e.Message);
    51.                 }
    52.             }
    53.         }
    54.     }
    55. }
    -sam
     
  15. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
  16. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    @Peter77 Unity still seems to try to import the files in StreamingAssets though, which I think he was trying to avoid.

    -sam
     
  17. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    I had an interesting solution. The function that is set up to read the files uses Resource.Load(), but I used File.ReadAllText() and noticed that the '~' is a bad symbol, BUT Unity also ignores files that have .tmp as extensions, SO, I got rid of the '~' in my folder and renamed all my .inf extensions to .tmp and changed all the references to open .tmp. Then, I used an 'if' statement for a variable named 'isDeveloping' (to determine weather or not to use Resources.Load(), or File.ReadAllText()), and before I publish everything, I can change the extensions from .tmp to .txt (since TextAssets through Resources.Load() need to have .txt extensions, and the argument that gets passed to Resources.Load() must not have the extension in them).