Does NOT Hash128.Parse() method return UNIQUE hash?
Hi Dev! For using Hash128 in my code, I tested some simple code. But result was a little weired. I guessed Hash128.Parse() method returns UNIQUE hash (Hash128), but it didn't.
Test code is below.
Hash128 a = Hash128.Parse("TestA");
Hash128 b = Hash128.Parse("TestB");
Debug.Log( "a: " + a.ToString() );
Debug.Log( "b: " + b.ToString() );
Debug.Log( "equal? " + a.Equals( b ) );
And here is result log.
a: 0e000000000000000000000000000000
b: 0e000000000000000000000000000000
equal? True
Do I use Hash128 wrong?
If do that, Please tell me how to use Hash128 correctly or hash function used for Hash128. Thx!
I know, that this question is old, but still, I'm encountering the exact results. Isn't Hash128.Parse unique?
Answer by tgrotte · Oct 08, 2020 at 09:49 PM
Here's an update. It looks like you can use Hash128's Compute method with one of the various overloads. @Bunny83 It appears that Unity is using the SpookyV2 hashing algorithm, also mentioned in the link I shared.
Great, so they finally added the actual Compute method for us to use and updated the documentation.
I recently came across documentation from Unity stating that the hash values Unity generates for asset bundles, as listed in the asset manifest, are not reliable and should not be used as version numbers to the Caching system. This is consistent with my experience- I've seen many times different content being assigned the same hash value from Unity. Do you use their hashes with the quirky behavior or make your own version number? I'm curious what experienced developers are using. I'm wondering if I could use this Hash128.Compute method after the build process is complete to make my bundle version numbers or if it will suffer from the same issue. I can certainly test that out. Thanks @Bunny83.
Answer by Bunny83 · Oct 21, 2017 at 02:24 PM
No Hash128 is just a struct to store an AssetBundle hash. It can't calculate a new hash. Parse is just the opposite of ToString. So all "Parse" does is convert the string representation of a hash back into the numeric struct representation. Again, it does not calculate a hash.
Just to make it more clear, here's an example. I just created an arbitary hash manually and let it convert to string:
var h = new Hash128(0x12345678,0xABCDABCD,0xDEADBEAF, 0x55AA55AA);
string str = h.ToString();
Debug.Log("str: " + str);
var h2 = Hash128.Parse(str);
Debug.Log("equal? " + (h == h2));
In the console you will see:
str: 78563412cdabcdabafbeaddeaa55aa55
and
equal? True
As you can see ToString simply converts the 4 uint values into hex and Parse simply does the inverse and converts the hexadecimal representation back to a hash.
In your case "TestA" is not a valid hex string. However it actually detected the "e" in your string as hex digit which is the only one it can read.
Apart from that it should be clear that any hashing algorithm can't create a "unique" hash for a message that is longer than the hash. It's simply impossible. Good hashing algorithms however should avoid collisions of similar messages. However there are always many many messages which will result in the same hash, but those messages are completely different. A 128 bit hash has as many digits as a GUID / UUID. So the probability that one hash is equal to another is very very small.
But again, Unity's Hash128 struct is just a numerical representation of a hash and does not allow to compute a hash. Unity uses this struct for internal asset management and to identify assetbundles. It's returned by methods like "UnityEditor.AssetDatabase.GetAssetDependencyHash". There is currently no method to manually calculate such a hash of arbitrary data. It's not even specified what algorithm Unity uses internally. If you need a hashing algorithm at runtime you should first look for a suitable hashing algorithm and then look for a .NET / $$anonymous$$ono implementation