Automatic Version Increment Script

I’ve searched the forums for something to allow me to do version numbering on my game, but I couldn’t find anything specific. Does anyone have a nice solution for version numbering?

I’ve been programming a little Android game lately but I’ve been having problems knowing which version my other team mates are commenting on. I added a simple version number string to help, but I kept forgetting to increment it before pushing out a build for others to try so made a little script to do it automagically.

The logic is pretty simple. I have it read, increment and then save a text file that has a string in the format “0.0.0.text”. I control the “0.0” values by modifying the text file, but the last number is incremented any time the game code is compiled, or the game is run in the editor.

Let me know what you think.

Put this in an Editor folder (copy text below or download attached C# file).

//inspired by http://answers.unity3d.com/questions/45186/can-i-auto-run-a-script-when-editor-launches-or-a.html

using UnityEngine;
using UnityEditor;
using System.IO;
        
[InitializeOnLoad]
public class VersionIncrementor
{
    static VersionIncrementor()    {
        //If you want the scene to be fully loaded before your startup operation, 
        // for example to be able to use Object.FindObjectsOfType, you can defer your 
        // logic until the first editor update, like this:
        EditorApplication.update += RunOnce;
    }

    static void RunOnce()    {
        EditorApplication.update -= RunOnce;
        ReadVersionAndIncrement();
    }

    static void ReadVersionAndIncrement()    {
        //the file name and path.  No path is the base of the Unity project directory (same level as Assets folder)
        string versionTextFileNameAndPath = "version.txt";

        string versionText = CommonUtils.ReadTextFile(versionTextFileNameAndPath);

        if (versionText != null)        {
            versionText = versionText.Trim(); //clean up whitespace if necessary
            string[] lines = versionText.Split('.');

            int MajorVersion = int.Parse(lines[0]);
            int MinorVersion = int.Parse(lines[1]);
            int SubMinorVersion = int.Parse(lines[2]) + 1; //increment here
            string SubVersionText = lines[3].Trim();

            Debug.Log("Major, Minor, SubMinor, SubVerLetter: " + MajorVersion + " " + MinorVersion + " " + SubMinorVersion + " " + SubVersionText);

            versionText = MajorVersion.ToString("0") + "." +
                          MinorVersion.ToString("0") + "." +
                          SubMinorVersion.ToString("000") + "." +
                          SubVersionText;

            Debug.Log("Version Incremented " + versionText);

            //save the file (overwrite the original) with the new version number
            CommonUtils.WriteTextFile(versionTextFileNameAndPath, versionText);
            //save the file to the Resources directory so it can be used by Game code
            CommonUtils.WriteTextFile("Assets/Resources/version.txt", versionText);

            //tell unity the file changed (important if the versionTextFileNameAndPath is in the Assets folder)
            AssetDatabase.Refresh();
        }
        else {
            //no file at that path, make it
            CommonUtils.WriteTextFile(versionTextFileNameAndPath, "0.0.0.a");
        }
    }
}

It uses some simple read/write text file logic which I have in a Scripts/Common directory. I’ve simplified it for this and called it CommonUtils.cs

using UnityEngine;
using System.Collections;
using System.IO;

public class CommonUtils
{
    public static string ReadTextFile(string sFileName)
    {
        //Debug.Log("Reading " + sFileName);

        //Check to see if the filename specified exists, if not try adding '.txt', otherwise fail
        string sFileNameFound = "";
        if (File.Exists(sFileName))
        {
            //Debug.Log("Reading '" + sFileName + "'.");
            sFileNameFound = sFileName; //file found
        }
        else if (File.Exists(sFileName + ".txt"))
        {
            sFileNameFound = sFileName + ".txt";
        }
        else
        {
            Debug.Log("Could not find file '" + sFileName + "'.");
            return null;
        }

        StreamReader sr;
        try
        {
            sr = new StreamReader(sFileNameFound);
        }
        catch (System.Exception e)
        {
            Debug.LogWarning("Something went wrong with read.  " + e.Message);
            return null;
        }

        string fileContents = sr.ReadToEnd();
        sr.Close();

        return fileContents;
    }

    public static void WriteTextFile(string sFilePathAndName, string sTextContents)
    {
        StreamWriter sw = new StreamWriter(sFilePathAndName);
        sw.WriteLine(sTextContents);
        sw.Flush();
        sw.Close();
    }
}

991658–36711–$VersionIncrementor.cs (2.58 KB)
991658–36712–$CommonUtils.cs (1.37 KB)

1 Like

the idea is solid and useful, except incrementing when building. If you use svn, it would be awesome to parse the .svn files for a version #. Also, why make a version.txt? There’s a bundle version and bundle version code attached to andriod and iOS builds anyway that you could be updating in the PlayerEditor (or something like that?)

        PlayerSettings.bundleVersion = "1.0.22";

If you’re using C#, can’t you use the assembly versioning system? I don’t have Unity for Android, so I really don’t know if this ports. But I don’t know why it wouldn’t.

[assembly: System.Reflection.AssemblyVersion("1.0.*.*")] 
class MyClass
{
    .... blah blah blah ....

The assembly builder generates a timestamp for each assembly object. You don’t have a lot of choice over the format, but you can, at least, prepend a fixed (manually entered) version number followed by the automatically generated timestamp. In the format string, the last two numbers can be replaced by asterisks. The first asterix will be replaced by the number of days since Feburary 1st, 2000. The second asterix will be replaced with the number of seconds from 12:00AM divided by 2. For example:

You can access the version info of the executable at runtime through the Assembly namespace.

Debug.Log(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());

Pretty simple. Here’s the full MSDN doc…

6 Likes

This sounds useful indeed.

I think it’s good that you’re using your own versioning number instead of using an iOS/Android one, as it’ll keep your build numbers consistent across platforms.

However, as it’s a text file, how does it work if multiple people are working on the project?

Awesome, thanks all!

I didn’t know about BundleVersion or the assembly versioning system, I’ll give them a look. I want something that will work on stand alone and web builds too, but I imagine they could.

The good thing about the text file is that I have control of it, and I can increment the minor version number when I want.

I simplified my code for posting here for a single developer approach, but my actual code is made for working with multiple people. My situation puts me in charge of the published builds generally so I’m the master in charge of the version #, and others are more artists and level designers who have little to no impact on major code changes. We’re using SVN.

So for me, I don’t check in the ‘version.txt’ file in the project folder, but the ‘version.txt’ file in the resources folder is in source control, and its what is referenced by other code. I’ve removed the else statement so that in the absence of ‘version.txt’ in the project folder, nothing happens. Thinking about it now, the whole VersionIncrementor.cs file could be excluded from source control and no one but me would have automagic updating.

For a short time I was using something like this, but I didn’t really like it and decided to use two text files instead.

     string programmerName = PlayerPrefs.GetString("name", "none");
     if(programmerName != "masterofthecode")
         return;

Thx man, very helpful

: The name `PlayerSettings’ does not exist in the current context

It must be an editor script so you’ll need a using UnityEditor at the top.

I also found this one:

It’s based on [PostProcessBuild]

This is Awesome.
Thank you. I often feel like learning .net is like trying to memorize Britannica. This is one of those gems.

…and it only took me 3 years to find…

Hey, thanks for that script! I made it non-automatic (put it into the menu, so the version number only goes up every time I click “Increase Bundle Version”), made it change the actual Bundle Version and tweaked it to my liking. Thought I’d share it just in case anyone wants it:

    [MenuItem("Build/Increase Bundle Version", false, 800)]
    private static void BundleVersionPP() {

        int incrementUpAt = 9; //if this is set to 9, then 1.0.9 will become 1.1.0

        string versionText = PlayerSettings.bundleVersion;
        if ( string.IsNullOrEmpty( versionText ) ) {
            versionText = "0.0.1";
        } else {
            versionText = versionText.Trim(); //clean up whitespace if necessary
            string[] lines = versionText.Split('.');
           
            int majorVersion = 0;
            int minorVersion = 0;
            int subMinorVersion = 0;

            if( lines.Length > 0 ) majorVersion = int.Parse( lines[0] );
            if( lines.Length > 1 ) minorVersion = int.Parse( lines[1] );
            if( lines.Length > 2 ) subMinorVersion = int.Parse( lines[2] );

            subMinorVersion++;
            if( subMinorVersion > incrementUpAt ) {
                minorVersion++;
                subMinorVersion = 0;
            }
            if( minorVersion > incrementUpAt ) {
                majorVersion++;
                minorVersion = 0;
            }

            versionText = majorVersion.ToString("0") + "." + minorVersion.ToString("0") + "." +    subMinorVersion.ToString("0");
           
        }
        Debug.Log( "Version Incremented to " + versionText );
        PlayerSettings.bundleVersion = versionText;
    }
2 Likes

Thanks for the scripts! I reworked the code in order to have an automatic increment on every build and menu items for manually incrementing the major and minor versions.

Edit: I forgot to mention that this script is tailored for Android builds and Major.Minor.Build versioning scheme. Happy coding!

// Version Incrementor Script for Unity by Francesco Forno (Fornetto Games)
// Inspired by http://forum.unity3d.com/threads/automatic-version-increment-script.144917/

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

[InitializeOnLoad]
public class VersionIncrementor
{
    [PostProcessBuildAttribute(1)]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    {
        Debug.Log("Build v" + PlayerSettings.bundleVersion + " (" + PlayerSettings.Android.bundleVersionCode + ")");
        IncreaseBuild();
    }

    static void IncrementVersion(int majorIncr, int minorIncr, int buildIncr)
    {
        string[] lines = PlayerSettings.bundleVersion.Split('.');

        int MajorVersion = int.Parse(lines[0]) + majorIncr;
        int MinorVersion = int.Parse(lines[1]) + minorIncr;
        int Build = int.Parse(lines[2]) + buildIncr;

        PlayerSettings.bundleVersion = MajorVersion.ToString("0") + "." +
                                        MinorVersion.ToString("0") + "." +
                                        Build.ToString("0");
        PlayerSettings.Android.bundleVersionCode = MajorVersion * 10000 + MinorVersion * 1000 + Build;
    }

    [MenuItem("Build/Increase Minor Version")]
    private static void IncreaseMinor()
    {
        IncrementVersion(0, 1, 0);
    }

    [MenuItem("Build/Increase Major Version")]
    private static void IncreaseMajor()
    {
        IncrementVersion(1, 0, 0);
    }

    private static void IncreaseBuild()
    {
        IncrementVersion(0, 0, 1);
    }
}
4 Likes

My Procedural Asset Framework (Unity Asset Store - The Best Assets for Game Making) has an AppDetails script which gives you automatic build numbering (as an int), as well as a build time stamp (as a DateTime). It also gives you runtime access to the product name and company name you specify in the player settings.

As of the latest version most applications above no longer work.

Wrote and tested a script that does it for you for Android and iOS (free). Leave a star if it works :slight_smile:

Thanks that is great, I edited your script to make use of a ScriptableObject. Haven’t tested it a lot but works so far. It uses the ResourceSingleton class that I used a lot. I edited it here so that it works out of the box.

The logic changed so that each time you increase a version then the sub-versions are set to zero.

// Inspired by http://forum.unity3d.com/threads/automatic-version-increment-script.144917/

using UnityEngine;
using System.IO;
using UnityEditor;
using UnityEditor.Callbacks;
using System;

[InitializeOnLoad]
public class VersionIncrementor : ResourceSingleton<VersionIncrementor>
{
   public int MajorVersion;
   public int MinorVersion = 1;
   public int BuildVersion;
   public string CurrentVersion;

   [PostProcessBuild(1)]
   public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
   {
       Debug.Log("Build v" + Instance.CurrentVersion);
       IncreaseBuild();
   }

   void IncrementVersion(int majorIncr, int minorIncr, int buildIncr)
   {
       MajorVersion += majorIncr;
       MinorVersion += minorIncr;
       BuildVersion += buildIncr;

       UpdateVersionNumber();
   }


   [MenuItem("Build/Create Version File")]
   private static void Create()
   {
       Instance.Make();
   }

   [MenuItem("Build/Increase Major Version")]
   private static void IncreaseMajor()
   {
       Instance.MajorVersion++;
       Instance.MinorVersion = 0;
       Instance.BuildVersion = 0;
       Instance.UpdateVersionNumber();
   }
   [MenuItem("Build/Increase Minor Version")]
   private static void IncreaseMinor()
   {
       Instance.MinorVersion++;
       Instance.BuildVersion = 0;
       Instance.UpdateVersionNumber();
   }

   private static void IncreaseBuild()
   {
       Instance.BuildVersion++;
       Instance.UpdateVersionNumber();
   }

   void UpdateVersionNumber()
   {
       //Make your custom version layout here.
       CurrentVersion = MajorVersion.ToString("0") + "." + MinorVersion.ToString("00") + "." + BuildVersion.ToString("000");

       PlayerSettings.Android.bundleVersionCode = MajorVersion * 10000 + MinorVersion * 1000 + BuildVersion;
       PlayerSettings.bundleVersion = CurrentVersion;
   }
}

public abstract class ResourceSingleton<T> : ScriptableObject
       where T : ScriptableObject
{
   private static T m_Instance;
   const string AssetPath = "Assets/Resources";

   public static T Instance
   {
       get
       {
           if (ReferenceEquals(m_Instance, null))
           {
               m_Instance = Resources.Load<T>(AssetPath + typeof(T).Name);
#if UNITY_EDITOR
               if (m_Instance == null)
               {
                   //Debug.LogError("ResourceSingleton Error: Fail load at " + "Singletons/" + typeof(T).Name);
                   CreateAsset();
               }
               else
               {
                   //Debug.Log("ResourceSingleton Loaded: " + typeof (T).Name);
               }
#endif
               var inst = m_Instance as ResourceSingleton<T>;
               if (inst != null)
               {
                   inst.OnInstanceLoaded();
               }
           }
           return m_Instance;
       }
   }

   public void Make() { }
   static void CreateAsset()
   {
       m_Instance = ScriptableObject.CreateInstance<T>();
       string path = Path.Combine(AssetPath, typeof(T).ToString() + ".asset");
       path = AssetDatabase.GenerateUniqueAssetPath(path);
       AssetDatabase.CreateAsset(m_Instance, path);

       AssetDatabase.SaveAssets();
       AssetDatabase.Refresh();
       EditorUtility.FocusProjectWindow();
       Selection.activeObject = m_Instance;
   }

   protected virtual void OnInstanceLoaded()
   {
   }
}
1 Like

Not adding much, I like this version the most and wanted to make sure it run smoothly for any one like me.

You need to put this Script in an Editor Folder and it only works for Android but I’m sure somehow it can work for PC as well.

// Minor adjustments by Arshd
// Version Incrementor Script for Unity by Francesco Forno (Fornetto Games)
// Inspired by http://forum.unity3d.com/threads/automatic-version-increment-script.144917/

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

[InitializeOnLoad]
public class VersionIncrementor
{
    [PostProcessBuild(1)]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    {
#if UNITY_ANDROID
        Debug.Log("Build v" + PlayerSettings.bundleVersion + " (" + PlayerSettings.Android.bundleVersionCode + ")");
        IncreaseBuild();
#endif
    }

    static void IncrementVersion(int majorIncr, int minorIncr, int buildIncr)
    {
        string[] lines = PlayerSettings.bundleVersion.Split('.');

        int MajorVersion = int.Parse(lines[0]) + majorIncr;
        int MinorVersion = int.Parse(lines[1]) + minorIncr;
        int Build = 0;
        if (lines.Length > 2)
        {
            Build = int.Parse(lines[2]) + buildIncr;
        }

        PlayerSettings.bundleVersion = MajorVersion.ToString("0") + "." +
                                        MinorVersion.ToString("0") + "." +
                                        Build.ToString("0");
        PlayerSettings.Android.bundleVersionCode = MajorVersion * 10000 + MinorVersion * 1000 + Build;
    }

    [MenuItem("Build/Increase Minor Version")]
    private static void IncreaseMinor()
    {
        IncrementVersion(0, 1, 0);
    }

    [MenuItem("Build/Increase Major Version")]
    private static void IncreaseMajor()
    {
        IncrementVersion(1, 0, 0);
    }

    private static void IncreaseBuild()
    {
        IncrementVersion(0, 0, 1);
    }
}
1 Like
// Minor adjustments by Arshd and then tsny
// Version Incrementor Script for Unity by Francesco Forno (Fornetto Games)
// Inspired by http://forum.unity3d.com/threads/automatic-version-increment-script.144917/

using System.IO;
using UnityEditor;
using UnityEditor.Build;

[InitializeOnLoad]
public class VersionIncrementor : IPreprocessBuild
{
    public int callbackOrder
    {
        get
        {
            return 1;
        }
    }

    [MenuItem("Build/Build Current")]
    public static void BuildCurrent()
    {
        IncreaseBuild();
        BuildPlayerWindow.ShowBuildPlayerWindow();
    }

    static void IncrementVersion(int majorIncr, int minorIncr, int buildIncr)
    {
        string[] lines = PlayerSettings.bundleVersion.Split('.');

        int MajorVersion = int.Parse(lines[0]) + majorIncr;
        int MinorVersion = int.Parse(lines[1]) + minorIncr;
        int Build = 0;
        if (lines.Length > 2)
        {
            Build = int.Parse(lines[2]) + buildIncr;
        }

        PlayerSettings.bundleVersion = MajorVersion.ToString("0") + "." +
                                        MinorVersion.ToString("0") + "." +
                                        Build.ToString("0");

        var buildVersionPath = @"buildversion.txt";

        File.WriteAllText(buildVersionPath, PlayerSettings.bundleVersion);
    }

    public static string GetLocalVersion()
    {
        return PlayerSettings.bundleVersion.ToString();
    }

    [MenuItem("Build/Increase Minor Version")]
    private static void IncreaseMinor()
    {
        IncrementVersion(0, 1, 0);
    }

    [MenuItem("Build/Increase Major Version")]
    private static void IncreaseMajor()
    {
        IncrementVersion(1, 0, 0);
    }

    [MenuItem("Build/Increase Current Build Version")]
    private static void IncreaseBuild()
    {
        IncrementVersion(0, 0, 1);
    }

    public void OnPreprocessBuild(BuildTarget target, string path)
    {
        IncreaseBuild();
    }
}

This is my implementation changed a bit from Arshd.
This should increment your version before every build automatically.

2 Likes
// Minor adjustments by Arshd and then tsny and finaly RKar
// Version Incrementor Script for Unity by Francesco Forno (Fornetto Games)
// Inspired by http://forum.unity3d.com/threads/automatic-version-increment-script.144917/

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Build;

[InitializeOnLoad]
class VersionIncrementor: IPreprocessBuild
{
    [MenuItem("Build/Increase Current Build Version")]
    private static void IncreaseBuild()
    {
        IncrementVersion(new int[] { 0, 0, 1 });
    }

    [MenuItem("Build/Increase Minor Version")]
    private static void IncreaseMinor()
    {
        IncrementVersion(new int[] { 0, 1, 0 });
    }

    [MenuItem("Build/Increase Major Version")]
    private static void IncreaseMajor()
    {
        IncrementVersion(new int[] { 1, 0, 0 });
    }

    static void IncrementVersion(int[] versionIncr)
    {
        string[] lines = PlayerSettings.bundleVersion.Split('.');

        for (int i = lines.Length - 1; i >= 0; i--)
        {
            bool isNumber = int.TryParse(lines[i], out int numberValue);

            if (isNumber && versionIncr.Length - 1 >= i)
            {
                if (i > 0 && versionIncr[i] + numberValue > 9)
                {
                    versionIncr[i - 1]++;

                    versionIncr[i] = 0;
                }
                else
                {
                    versionIncr[i] += numberValue;
                }
            }
        }

        PlayerSettings.bundleVersion = versionIncr[0] + "." + versionIncr[1] + "." + versionIncr[2];
    }

    public static string GetLocalVersion()
    {
        return PlayerSettings.bundleVersion.ToString();
    }

    public void OnPreprocessBuild(BuildTarget target, string path)
    {
        IncreaseBuild();
    }

    public int callbackOrder { get { return 0; } }
}
#endif

I added protection against an incorrect version string.

2 Likes

When I build sometimes I need to increment the version and sometimes I don’t (and sometimes I forget to do it!)

My implementation shows a dialog window during the build process and I can choose what to do.

The code related to the increment is pretty rough, but you get the idea.

public void OnPreprocessBuild(BuildReport report)
    {

        bool shouldIncrement = EditorUtility.DisplayDialog("Incrementer", "Applying increment? Current: v" + PlayerSettings.bundleVersion, "Yes", "No");

        if (shouldIncrement)
        {
            string[] numbers = PlayerSettings.bundleVersion.Split('.');
            string major = numbers[0];
            int minor = Convert.ToInt32(numbers[1]);
            minor++;
            PlayerSettings.bundleVersion = major+"."+minor;
        }
}
5 Likes