Search Unity

Automatic Optimizations (Free Editor Code)

Discussion in 'Scripting' started by image28, Feb 17, 2017.

  1. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Wrote some scripts to auto optimize code, would like it if some people tested them out, just don't get mad if they break your code a bit ( backup first ). Place all files in the editor folder. Plan to turn them into a store asset once I develop and test them a bit more.

    First one replaces string in update function with hardcoded string set in start to remove garbage collection

    header.txt
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class stringManager : MonoBehaviour
    7. {
    8.      private static stringManager instance = null;
    9.  
    10.      // Game Instance Singleton
    11.      public static stringManager Instance
    12.      {
    13.          get
    14.          {
    15.              return instance;
    16.          }
    17.      }
    18.  
    19.      private void Awake()
    20.      {
    21.          // if the singleton hasn't been initialized yet
    22.          if (instance != null && instance != this)
    23.          {
    24.              Destroy(this.gameObject);
    25.          }
    26.          instance = this;
    27.          DontDestroyOnLoad( this.gameObject );
    28.      }
    29.  
    30.      // Strings DB ( Reduces Garbage Collection )
    31.  
    footer.txt
    Code (csharp):
    1.  
    2.  
    3. }
    4.  
    stringOptimizer.cs
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Reflection;
    6. using System.IO;
    7. using UnityEngine;
    8. using UnityEditor;
    9.  
    10. public class stringOptimizer
    11. {
    12.  
    13.     private static StreamWriter managerOutput;
    14.     private static string line;
    15.     private static int bracketCount;
    16.     private static bool bracketRead = false;
    17.  
    18.     [MenuItem ("Window/Optimize/Optimize Strings", false)]
    19.     static void FindAssetsUsingSearchFilter ()
    20.     {
    21.         // Find all code assets
    22.         string[] guids = AssetDatabase.FindAssets ("t:MonoScript");
    23.         bool inUpdate;
    24.         bool inFixedUpdate;
    25.         bool inLateUpdate;
    26.  
    27.         if (File.Exists ("Assets/stringManager.cs")) {
    28.             File.Copy ("Assets/stringManager.cs", "Assets/stringManager.cs" + ".undo");
    29.         }
    30.         managerOutput = new StreamWriter ("Assets/stringManager.cs");
    31.  
    32.         stringManagerHeadFoot ("Assets/Editor/header.txt");
    33.  
    34.         Debug.LogError (guids.Length + " Strings found");
    35.         foreach (string guid in guids) {
    36.             int stringCount = 0;
    37.  
    38.             Debug.Log (AssetDatabase.GUIDToAssetPath (guid));
    39.             if (!AssetDatabase.GUIDToAssetPath (guid).Contains ("Editor")) {
    40.                 saveUndoFile (AssetDatabase.GUIDToAssetPath (guid));
    41.                 StreamReader input = new StreamReader (AssetDatabase.GUIDToAssetPath (guid));
    42.                 StreamWriter output = new StreamWriter ("Assets/temp.txt");
    43.                 bracketCount = 0;
    44.                 inUpdate = false;
    45.                 inLateUpdate = false;
    46.                 inFixedUpdate = false;
    47.  
    48.  
    49.                 while ((line = input.ReadLine ()) != null) {
    50.                     Debug.LogError ("Read line " + line);
    51.  
    52.                     bracketRead = false;
    53.  
    54.                     inUpdate = inFunction ("Update(", "Update (", inUpdate, 0);
    55.                     inLateUpdate = inFunction ("LateUpdate(", "LateUpdate (", inUpdate, 0);
    56.                     inFixedUpdate = inFunction ("FixedUpdate(", "FixedUpdate (", inUpdate, 0);
    57.  
    58.                     if (((inUpdate) || (inFixedUpdate) || (inLateUpdate)) && (line.Contains ("\"") && (!line.Contains ("case") && (!line.Contains ("[ContextMenu"))))) {
    59.  
    60.                         line = line.Replace ("\\\"", "DOUBLESTRING");
    61.                         Debug.LogError ("String found");
    62.                         string[] temp = line.Split ('"');
    63.                         if (temp.Length >= 3) {
    64.                             Debug.LogError (temp [0] + temp [1] + temp [2]);
    65.  
    66.                             int count = 1;
    67.                             while (count < temp.Length) {
    68.                            
    69.    
    70.                                 Debug.LogError ("String number " + count);
    71.            
    72.                                 Debug.LogError ("Match");
    73.                                 // write string to string manager
    74.                                 managerOutput.Write ("\tpublic string " + Path.GetFileNameWithoutExtension (AssetDatabase.GUIDToAssetPath (guid)) + stringCount + " = \"" + temp [count] + "\";");
    75.                                 managerOutput.WriteLine ();
    76.                                 // replace string with stringManager.Instance.classnameStringcount
    77.                                 string originalString = '"' + temp [count] + '"';
    78.                                 string replaceString = "stringManager.Instance." + Path.GetFileNameWithoutExtension (AssetDatabase.GUIDToAssetPath (guid)) + stringCount;
    79.            
    80.                                 line = line.Replace (originalString, replaceString);
    81.  
    82.                                 //line.Replace (originalString, replaceString);
    83.                                 Debug.LogError ("Writing line " + line + " replaced " + originalString + " with " + replaceString);
    84.                                
    85.                                 stringCount++;
    86.                        
    87.  
    88.                                 count = count + 2;
    89.                             }
    90.                         }
    91.  
    92.                         line = line.Replace ("DOUBLESTRING", "\\\"");
    93.                     }
    94.  
    95.  
    96.  
    97.                     // Write the current line
    98.                     output.Write (line);
    99.                     output.WriteLine ();
    100.                 }
    101.  
    102.                 output.Close ();
    103.                 input.Close ();
    104.  
    105.                 File.Delete (AssetDatabase.GUIDToAssetPath (guid));
    106.                 File.Move ("Assets/temp.txt", AssetDatabase.GUIDToAssetPath (guid));
    107.             }
    108.  
    109.  
    110.         }
    111.  
    112.         stringManagerHeadFoot ("Assets/Editor/footer.txt");
    113.         managerOutput.Close ();
    114.     }
    115.  
    116.     static void stringManagerHeadFoot (string headerPath)
    117.     {
    118.         string headerLine;
    119.         StreamReader input = new StreamReader (headerPath);
    120.  
    121.         while ((headerLine = input.ReadLine ()) != null) {
    122.             managerOutput.Write (headerLine);
    123.             managerOutput.WriteLine ();
    124.  
    125.         }
    126.  
    127.         input.Close ();
    128.     }
    129.  
    130.     static bool inFunction (string search1, string search2, bool testCondition, int braceMatch)
    131.     {
    132.         if ((line.Contains (search1)) || (line.Contains (search2))) {
    133.             testCondition = true;
    134.             if ((line.Contains ("{")) && (!bracketRead)) {
    135.                 bracketRead = true;
    136.                 bracketCount++;
    137.             }
    138.             Debug.LogError ("In Function " + search1);
    139.             Debug.LogError (bracketCount);
    140.         } else {
    141.  
    142.             if (testCondition) {
    143.                 if ((line.Contains ("{")) && (!bracketRead)) {
    144.                     bracketRead = true;
    145.                     bracketCount++;
    146.                     Debug.LogError ("Open function " + bracketCount);
    147.                 }
    148.  
    149.                 if ((line.Contains ("}")) && (!bracketRead)) {
    150.                     bracketRead = true;
    151.                     bracketCount--;
    152.                     Debug.LogError ("Close function " + bracketCount);
    153.                 }
    154.  
    155.                 if ((bracketCount == braceMatch)) {
    156.                     testCondition = false;
    157.                     Debug.LogError (bracketCount);
    158.                     Debug.LogError ("Exit Function");
    159.                 }
    160.             }
    161.  
    162.  
    163.         }
    164.  
    165.         return(testCondition);
    166.     }
    167.  
    168.     static void saveUndoFile (string path)
    169.     {
    170.         if (File.Exists (path + ".undo")) {
    171.             File.Delete (path + ".undo");
    172.         }
    173.         File.Copy (path, path + ".undo");
    174.     }
    175. }
    176.  
    177.  
    The second optimizes GetComponent calls in Update on the local gameobject

    optimizeComponents.cs
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Reflection;
    6. using System.IO;
    7. using UnityEngine;
    8. using UnityEditor;
    9. using System.Text.RegularExpressions;
    10.  
    11. public class componentOptimizer
    12. {
    13.  
    14.     private static string line;
    15.     private static int bracketCount;
    16.     private static bool bracketRead = false;
    17.  
    18.     [MenuItem ("Window/Optimize/Optimize Components", false)]
    19.     static void FindAssetsUsingSearchFilter ()
    20.     {
    21.         // Find all code assets
    22.         string[] guids = AssetDatabase.FindAssets ("t:MonoScript");
    23.         Debug.LogError (guids.Length + " Strings found");
    24.         bool inUpdate = false;
    25.         bool inAwake = false;
    26.         bool inStart = false;
    27.         bool inClass = false;
    28.         bool writtenVars = false;
    29.         bool written = false;
    30.  
    31.  
    32.         foreach (string guid in guids) {
    33.             int stringCount = 0;
    34.             bracketCount = 0;
    35.             inUpdate = false;
    36.             inAwake = false;
    37.             inStart = false;
    38.             inClass = false;
    39.             written = false;
    40.             bracketRead = false;
    41.             writtenVars = false;
    42.             written = false;
    43.             Debug.Log (AssetDatabase.GUIDToAssetPath (guid));
    44.             if (!AssetDatabase.GUIDToAssetPath (guid).Contains ("Editor")) {
    45.                 saveUndoFile (AssetDatabase.GUIDToAssetPath (guid));
    46.                 StreamReader input = new StreamReader (AssetDatabase.GUIDToAssetPath (guid));
    47.                 StreamWriter output = new StreamWriter ("Assets/temp.txt");
    48.                 List<string> newVariables = new List<string> ();
    49.                 List<string> newInitializer = new List<string> ();
    50.                 int componentCount = 0;
    51.  
    52.  
    53.                 while ((line = input.ReadLine ()) != null) {
    54.                     //Debug.LogError ("Read line " + line);
    55.                     bracketRead = false;
    56.  
    57.                     inUpdate = inFunction ("Update(", "Update (", inUpdate, 0);
    58.  
    59.                     if ((inUpdate) && ((line.Contains ("gameObject.GetComponent")) || (line.Contains ("\tGetComponent")) || (line.Contains (" GetComponent")))) {
    60.                         Debug.LogError ("String found");
    61.                         Regex expression = new Regex (@"GetComponent<.*?>");
    62.                         MatchCollection results = expression.Matches (line);
    63.  
    64.                         foreach (Match result in results) {
    65.                             Debug.LogError (result);
    66.                             string compName = result.Value.Substring (13, result.Value.Length - 14);
    67.                             newVariables.Add (compName);
    68.                             newInitializer.Add (compName + "Cache" + (newVariables.Count - 1).ToString () + "=GetComponent<" + compName + ">();");
    69.                             //Debug.LogError (newVariables [newVariables.Count - 1]);
    70.                         }
    71.                     }
    72.  
    73.  
    74.  
    75.                 }
    76.  
    77.                 input.BaseStream.Seek (0L, SeekOrigin.Begin);
    78.                 bracketCount = 0;
    79.                 inUpdate = false;
    80.                 inAwake = false;
    81.                 inStart = false;
    82.                 inClass = false;
    83.                 written = false;
    84.                 bracketRead = false;
    85.                 writtenVars = false;
    86.                 written = false;
    87.  
    88.                 while ((line = input.ReadLine ()) != null) {
    89.                     //Debug.LogError ("Read line " + line);
    90.  
    91.                     bracketRead = false;
    92.  
    93.                     inUpdate = inFunction ("Update(", "Update (", inUpdate, 1);
    94.                     inStart = inFunction ("Start(", "Start (", inStart, 1);
    95.                     inAwake = inFunction ("Awake(", "Awake (", inAwake, 1);
    96.                     inClass = inFunction ("class " + Path.GetFileNameWithoutExtension (AssetDatabase.GUIDToAssetPath (guid)), "class " + Path.GetFileNameWithoutExtension (AssetDatabase.GUIDToAssetPath (guid)), inClass, 0);
    97.  
    98.                     if ((inUpdate) && ((line.Contains ("gameObject.GetComponent")) || (line.Contains ("\tGetComponent")) || (line.Contains (" GetComponent")))) {
    99.                         Debug.LogError ("String found");
    100.                         Regex expression = new Regex (@"GetComponent<.*?>");
    101.                         MatchCollection results = expression.Matches (line);
    102.  
    103.                         foreach (Match result in results) {
    104.                             Debug.LogError (result);
    105.                             string compName = result.Value.Substring (13, result.Value.Length - 14);
    106.                             line = line.Replace ("GetComponent<" + compName + ">()", compName + "Cache" + componentCount);
    107.                             line = line.Replace ("GetComponent<" + compName + "> ()", compName + "Cache" + componentCount);
    108.                             componentCount++;
    109.                         }
    110.  
    111.                     }
    112.  
    113.                     // Write the current line
    114.                     output.Write (line);
    115.                     output.WriteLine ();
    116.  
    117.                     if ((inClass) && (!writtenVars) && (bracketCount == 1)) {
    118.                         output.WriteLine ();
    119.                         int componentCount2 = 0;
    120.                         foreach (string vars in newVariables) {
    121.                             output.Write (vars + " " + vars + "Cache" + componentCount2 + ";");
    122.                             output.WriteLine ();
    123.                             componentCount2++;
    124.                         }
    125.  
    126.                         output.WriteLine ();
    127.                         writtenVars = true;
    128.                     }
    129.  
    130.                     if ((inStart) && (!written) && (bracketCount == 2)) {
    131.                         output.WriteLine ();
    132.  
    133.                         foreach (string vars in newInitializer) {
    134.                             output.Write (vars);
    135.                             output.WriteLine ();
    136.                         }
    137.  
    138.                         output.WriteLine ();
    139.                         written = true;
    140.                     }
    141.  
    142.                     if ((inAwake) && (!written) && (bracketCount == 2)) {
    143.                         output.WriteLine ();
    144.  
    145.                         foreach (string vars in newInitializer) {
    146.                             output.Write (vars);
    147.                             output.WriteLine ();
    148.                         }
    149.  
    150.                         output.WriteLine ();
    151.  
    152.                         written = true;
    153.                     }
    154.                 }
    155.  
    156.  
    157.                 output.Close ();
    158.                 input.Close ();
    159.  
    160.                 if (written) {
    161.                     File.Delete (AssetDatabase.GUIDToAssetPath (guid));
    162.                     File.Move ("Assets/temp.txt", AssetDatabase.GUIDToAssetPath (guid));
    163.                 } else {
    164.                     File.Delete ("Assets/temp.txt");
    165.                 }
    166.             }
    167.  
    168.  
    169.         }
    170.        
    171.     }
    172.  
    173.     static bool inFunction (string search1, string search2, bool testCondition, int braceMatch)
    174.     {
    175.         if ((line.Contains (search1)) || (line.Contains (search2))) {
    176.             testCondition = true;
    177.             if ((line.Contains ("{")) && (!bracketRead)) {
    178.                 bracketRead = true;
    179.                 bracketCount++;
    180.             }
    181.             Debug.LogError ("In Function " + search1);
    182.             Debug.LogError (bracketCount);
    183.         } else {
    184.        
    185.             if (testCondition) {
    186.                 if ((line.Contains ("{")) && (!bracketRead)) {
    187.                     bracketRead = true;
    188.                     bracketCount++;
    189.                     Debug.LogError ("Open function " + bracketCount);
    190.                 }
    191.  
    192.                 if ((line.Contains ("}")) && (!bracketRead)) {
    193.                     bracketRead = true;
    194.                     bracketCount--;
    195.                     Debug.LogError ("Close function " + bracketCount);
    196.                 }
    197.  
    198.                 if ((bracketCount == braceMatch)) {
    199.                     testCondition = false;
    200.                     Debug.LogError (bracketCount);
    201.                     Debug.LogError ("Exit Function");
    202.                 }
    203.             }
    204.  
    205.  
    206.         }
    207.  
    208.         return(testCondition);
    209.     }
    210.  
    211.     static void saveUndoFile (string path)
    212.     {
    213.         if (File.Exists (path + ".undo")) {
    214.             File.Delete (path + ".undo");
    215.         }
    216.         File.Copy (path, path + ".undo");
    217.     }
    218. }
    219.  
    220.  
     
    Last edited: Feb 17, 2017
    mgear likes this.
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Huh?

    Could you show an example of what it's SUPPOSED to be doing here? How would I even know what 'unoptimized' code I would have to be optimized and run this on.

    Especially since I have no idea what this even means...

    This one is kind of clearer.... I'm assuming you mean it moves any 'GetComponent' calls done in Update to be done in Start/Awake?

    Is there any safe guards put in for if my Start/Awake method is an override or anything?

    Also, what about variable name collisions, does it safeguard against that?
     
    image28 likes this.
  3. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    All valid points. The first program find strings in code ( it actually should only do it in Update and Fixed update which it doesn't, will fix that ) and generates a string manager singleton to store all stings in, rather than creating garbage for the strings every frame.

    For the component optimizer it takes the component name and creates a variable appending Cache to the component name, but there could be variable collisions, will have to look into it further

    Thanks for the feedback,
    I'm aware automatic code modification can be dangerous stuff.
     
  4. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Wrote it more for improving old finished projects in a hurry, but haven't tested much yet.
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Still don't understand what you mean...

    Show me an example of unoptimized code, and then what it would look like after this script was ran.
     
    image28 likes this.
  6. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Something like this. It's a real micro optimization, but in mobile development thats important.
    Another improvement would be to replace string concatenations with string.Format for less garbage.

    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.   textScript.text = "Frames: " + framecount;
    5. }
    6.  
    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.   textScript.text = stringManager.Instance.filename1 + framecount;
    5. }
    6.  
     
  7. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    @lordofduct thanks for replying, I consider anyone with over 1000 post a unity legend. Appreciate the time you gave to respond.
     
  8. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    I'm not sure why you'd want to create a singleton for the strings though? Why not make it a static class with constants in it as it seems there is no management being done by the class in the firsts place? In general I am against using Singletons altogether, though I can see some uses for them for specific management classes that you might want some control over, but in this case if it's just for holding a bunch of strings, I'd go with a simple static class.

    I can see some usefulness in this tool for sure for new developers, though I might assume most experienced devs don't need it, as such, might I suggest also putting a message in it reminding anyone using it that using hardcoded strings and GetComponent<T> all over the place is a bad idea ^.^
     
    image28 likes this.
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    OK... I had a sneaking suspicion that's what you were shooting for.

    Just so you know, string literals are treated as constants. They don't generate garbage. They are literally part of your program code.

    The string generated from the literal "Frames: " and 'framecount', that will generate garbage, because it's a brand new string that can't be optimized at compile time... since it's runtime dependant... it's variable based on what framecount is at the moment of creation.

    Case in point...

    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.     textScript.text = "Frames: ";
    5. }
    6.  
    Creates NO garbage whatsoever. (if any garbage does appear... it's not the literal, and maybe implementation behind the 'text' property.... no idea what you're actually referencing here)


    ....

    With that said, lets pretend that it did for the sake of critique of another aspect of the the example code.

    The Singleton 'StringManager' doesn't have to be a Singleton. And is actually a bit overkill. Why not just make is a static class, with static readonly fields (or better... constants).

    ...

    But again... C# takes care of all this for you.

    string literals/constants are well managed by the compiler. So much so that duplicate literals are actually pooled identically. (note, the compiler used by unity might not have this duplicate optimization built in... but even if it doesn't, no garbage is generated, only the programs memory footprint would be slightly larger).

    More literals does mean more memory used. But used memory isn't the same as garbage.... garbage is used memory that is available to be recycled. A constant/literal takes up a block of memory that is constantly used.... never being recycled for anything but what it is, for the life of the program.
     
    Last edited: Feb 17, 2017
    Kiwasi and Timelog like this.
  10. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    After looking at 6 released games for steam I though some optimization coulding help. I'm a bit the opposite, I use one or two singletons in a game and avoid statics.

    Agree with the message about using GetComponent, although I find a lot of pc developers still do it

     
  11. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    I'll have to look into this, ( weekend been drinking ), maybe I have been misinformed.

     
  12. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Running the code on something larger than a test project. Using the code I wrote for the indievspewdiepie gamejam (PickleRunner) as a testing bed. Have run into some bugs, fixes coming soon.
     
  13. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    There were some variable collisions among other things
     
  14. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Some background about the project. I'm working on building a backpack computer system, but I want to be able to play games on it and currently a lot of games run just slightly too slow on the 5w micro intel board I have for the system. So looking into various different ways of improving the games performance.
     
  15. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    825
    While I cant vouch for its usefulness in its current state I can definitely see this becoming a "thing" especially as Unity is supposed to be a "newbie" friendly engine.
     
    image28 likes this.
  16. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    It's also referred to as "interning strings".

    You can also manually intern strings.e.g some that you've created during runtime, some which are read from other resources and might be used alot.

    There are quite a few benefits, especially for the literals that are used in source code. You could compare 2 literals lots of times, it wouldn't take as long as comparing strings that are generated / not interned due to the fact that interned strings can be compared by reference. A modern compiler does quite a lot of optimizations.
    ____________________

    So while this isn't actually an issue, the general idea improves other qualities of source code. Maintainability in the first place.
    You can often find source code that uses literals explicitly written throughout a whole project. Once a literal changes you'll be busy replacing all those.
    That's a nice opportunity to implement something similar to that idea which you have in mind, even though it's often a good idea to seperate the different domains. In regards to Unity, you might want to define something like a static Tag class, which provides all the tags via constant variables.
    If you need to change a tag, it can be done in that one specific place (and ofc in the editor).

    For existing projects, that can be done in a similar fashion to your approach.
    _______________________

    Last but not least, one thing that you might also want to take care of when processing source files are documentations, comments, regions (and other preprocessor directives / symbols). These should (I'd say must) be left out when you process the files.
    Remember that comments can start anywhere in a line, can span over several lines, can even be inserted in between like
    Code (csharp):
    1.  
    2. if( a && b /* && c */ ...)
    3.  
    While the above also counts for GetComponent, you'd actually have to analize if the return value is directly used or if it's already an assignment to a cached variable and so on.

    You'd literally have to cover every single clase, otherwise you could rather quickly mess up clean code.

    It's quite some work to do...
     
    Last edited: Feb 17, 2017
    Timelog, Kiwasi and image28 like this.
  17. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Yeah was aware of the comment issue. Another way to do it would to be to use Reflection in some way, but haven't looked into using reflection that way yet ( but it would avoid the comment issue )
     
  18. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Updated the componentOptimizer still has a few issues, got 8 compile errors on Pickle Runner for rare code formating conditions. But works a lot better now.
     
  19. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Thanks I'll keep working on it during the weekends. Eventually it might become something
     
  20. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Will work on the stringOptimizer for a bit before calling it a morning. Make sure it runs on a larger project
     
  21. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    stringOptimizer has been updated. Still gets errors with Pickle Runner. Will Update it again soon
     
  22. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Working in the alpha linux editor that has some annoying workflow bugs, think they have been fixed, just downloaded the latest version, will test it soon.
     
  23. Trinary

    Trinary

    Joined:
    Jul 26, 2013
    Posts:
    395
    If you're interested in optimization you might enjoy MEC. If nothing else, try watching the videos.
     
  24. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    stringOptimizer has been updated. Now runs and generates only 3 compile errors to do with [System.Obsolete( in Pickle Runner code
     
  25. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Did use those for a little while in my current project, but removed them because they broke support for Net 2.0 Subset builds and code stripping, which increased build size a little.
     
  26. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Might fix Pickle Runner up so it works with unity 5.6 and do some before after performance comparisons tomorrow
     
  27. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Both optimizers have a few issues I still need to fix. They try modify UnityScript .js files. They don't optimize code in functions out of Update,FixedUpdate and LateUpdate even if those functions are called from one of the previously mentioned functions, and both still produced a few compile errors in rare situations.
     
  28. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    I'm happy for ya bro... you making stuff and having a good time.

    Is there a reason you're letting us know every time you fart though?
     
    Kiwasi likes this.
  29. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Nice asset by the way
     
    Trinary likes this.
  30. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Don't watch the thread if you don't want to listen. Just sharing the journey
     
  31. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Also if anyone does risk trying the code on their project you might want to do a find and replace of all the Debug.Logs commenting them out, they slow the program down a lot.

    Would love to hear any feedback, errors that it produced, to help find issues that may come up with your coding style/techniques.
     
  32. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    It does save undo files of everything it changes. I use a bash script to restore the files if something goes wrong. If this ever gets complete enough for the asset store i will add things like full undo support, progress bars, more optimizers, maybe asset(textures,sound,mesh) setting optimizers ( if that's possible, haven't looked into it ), file filters ( only optimize these files/folders ), etc...
     
  33. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Probably more appropriate for the WIP forum over the scripting forum. Either way no need to post every time you make a commit. Just post when you have a significant update.

    On the tool itself it might be more productive to focus on detecting the code problems and flagging them. This will probably be more useful and less prone to breaking then changing the scripts directly.
     
    lordofduct and image28 like this.
  34. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    Thanks, wasn't really sure where to post something like this. Will keep the posts to a minimum from now on.
    Flagging possible optimizations does sound like a good idea as well, but was writing this asset for multiple reasons, one of which being to quickly update my old projects with new coding techniques/optimizations as i learn them.