I’m developing a set of APIs that I plan to use on multiple projects, so I’m developing it as a UnityPackage. I have several testbed projects for it, and I’m testing how well it works when imported, and then make changes to it in-place to streamline it. One thing I have noted is that when I import the UnityPackage, it completely butchers the formatting of the code. For instance, this nicely-formatted section of code:
for (int i = 0; i < keywords.Length; i++) {
for (int j = 0; j < k.Length; j++) {
if (keywords[i] == k[j]) return true;
}
}
becomes this monstrosity:
for (int i = 0; i < keywords.Length; i++) for (int j = 0; j < k.Length; j++) if (keywords[i] == k[j]) return true;
That’s a copy/paste from my actual code - one from the original project, the other from the project I imported it into. This has happened at various places in my code. The first time I saw it, I assumed I had written it while drunk or something, and just went ahead fixed it. Then I started running across it more often, and it became clear that it wasn’t what I had written to begin with.
Why is it changing my code at all? Let alone turning it into this steaming mess? I’m very careful about keeping my code clean and readable.
I’m using the stock Visual Studio install, although it’s 2019. No plugins that don’t come with Unity.
That’s a good question. Let me test it. Not sure the permissions thing would work, because it’s basically doing the same as pulling it out of a zip file, although I can imagine some differences between zip format and unitypackage. Maybe if I can confirm that Unity is doing it, then I can try that.
Just tested it. I created a brand new URP project, imported the same package, and opened the exact same section of code in Notepad++ instead of Visual Studio. It is altered, so it has to be Unity. Not sure if it’s the import process or the export process.
Edit: just to clarify, that’s the stock URP project template downloaded from Unity, so if there’s a code obfuscator, then it’s in the stock template.
By UnityPackage, you mean you’re exporting it as a .unitypackage file and then pulling it into new projects? And not creating a Package that you add to your Packages folder?
Unity does have some code that modifies code as you pull in .unitypackages - the API updater. It tries it’s best to fix code that’s not valid anymore (like replacing .rigidbody with GetComponent), and things like that. Did you get a popup when you imported the .unitypackage into the project asking if you wanted to update the code?
No. I wrote the code less than three months ago, and I studiously avoid deprecated usages. At any rate, the code I listed doesn’t have any deprecated or obsolete API references to change.
It is interesting, though, that you bring up the API updater. Even if I’m not using deprecated code, it might be what’s modifying the formatting.
The other memory “chord” this strikes for me is a code decompiler… like it stood the code in question up from reading a DLL full of IL code, hence the removal of the braces. I assume if those for() loops had complex target actions (eg, more than one statement) it would NOT remove the braces??
I’ve run across a lot of places where my code formatting was changed, but I didn’t see any where the formatting changed the meaning. Other than places where I simply didn’t take something into account, the code works the same as before I exported/imported it. Not sure why it would extract it from IL code, though, since the actual code is right there. Then again, I’ve never delved into how the unity packages work.
I seem to have run across one where it actually changed the meaning of the code. This:
if (active) { // active
if (useTimeInState) {
if (weight < outWeight || timeInState > outTime) {
deactivate();
disp = ITrackedProp.Disposition.Destroyed;
}
} else {
if (weight < outWeight) {
deactivate();
disp = ITrackedProp.Disposition.Destroyed;
}
}
} else { // not active
if (useTimeInState) {
if (weight > inWeight && timeInState > inTime && timeInState < outTime) {
activate(anim);
disp = ITrackedProp.Disposition.Created;
}
} else {
if (weight > inWeight) {
activate(anim);
disp = ITrackedProp.Disposition.Created;
}
}
}
became this:
if (active) if (useTimeInState) {
if (weight < outWeight || timeInState > outTime) {
deactivate();
disp = ITrackedProp.Disposition.Destroyed;
} else if (weight < outWeight) {
deactivate();
disp = ITrackedProp.Disposition.Destroyed;
} else if (useTimeInState) {
if (weight > inWeight && timeInState > inTime && timeInState < outTime) {
activate(anim);
disp = ITrackedProp.Disposition.Created;
}
} else if (weight > inWeight) {
activate(anim);
disp = ITrackedProp.Disposition.Created;
}
}
Note the missing comments, but more importantly, the changed code does not work. The meaning changed altogether. I had to go back to the old project and copy/paste the original code, after which it worked again.