Jump to content
  • Advertisement

Recommended Posts

I am developing a cross platform game for which I needs to generate unique identifier (User ID) for each user. I known some platform (Android or iOS) specific approaches to get device related identifiers but I am looking for a solution independent of the device identifiers.

User ID Requirements:

 1. Independent of the device's platform
 2. Offline implementation (no communication with any servers)
 3. Without sign-up process

I have implemented one approach to create User IDs where I store the system time when the game was launched for the first time on the device.

I have following questions:

 1. Are there any other approaches to generate User IDs (which will meet the above requirements)?
 2. What are the common approaches to create unique identifiers with taking any information from the user?
 3. Are there any third party plug-ins to implement User IDs?

I would appreciate any suggestions and thoughts on this topic.

EDIT:

There are lot of responses to use UUID/GUID. Generally, this approach looks fine but I am looking for a solution which can generate same User ID even if the user reinstall the game.

Edited by Octane_Test
more information

Share this post


Link to post
Share on other sites
Advertisement

Guids are one thing you could look into.

So they have to be able to get an ID while they are offline and not signed up. If they are offline then it won't really matter what their ID is until they come online. Once they are online you can assign them a new ID that is unique throughout everyone else that is online.

I'd use an integer as their ID. when they sign up, give them the next available integer. that can be their user ID, so even when they are offline they will use that ID. If they need to get an ID without signing up, maybe do something like a session ID, so once someone connects online, they will get the next available session ID. again if they are offline the ID won't matter what it is, only when they come online.

One last thing you can do is get device specific information, like the hard drive serial number plus mac address plus some other hardware serial. This would of course go into your platform dependent section of code, since each platform is going to have different ways of getting this information. once you have that string of serials, just md5 hash it or something to get a normalized string so everyone uses the same string size for their ID.

I wouldn't use the time they started the app with, because it would be possible for multiple people to have started the app at the same time in their local machines time

Share this post


Link to post
Share on other sites

Generate a random 128-bit integer in some way. As iedoc said, you can do that by computing the md5sum of some machine-specific details, but you can also throw the timestamp of when the program was started in there, or some hardware-generated random numbers. You can also ask the user to take a picture (do you need a profile picture?) and take the md5sum of the image.

If you do a decent job of making the numbers random, 128 bits is enough to not expect any collisions ever. For instance, if you have 26 billion users, the probability of a collision is 10^-18. If for some reason you want to use 64 bits only, it might be OK, depending on how many users you expect: With 6 million users, the probability of a collision would be about 10^-6. I wouldn't go lower than 64 bits. See https://en.wikipedia.org/wiki/Birthday_problem

 

Share this post


Link to post
Share on other sites

UUID is what you are looking for. There are plenty open source implementations for all kinds of languages.

Share this post


Link to post
Share on other sites

Some things to also consider:

1) Will the game keep scores online for others to see?

2) Are there achievements?

3) Are there levels/progress points/character(s) stats?

If yes, you will have to support them using multiple devices with the same ID or to transfer their profiles to a new device without losing all their progress too.  So having them type 64-128 bit integer is likely not a great idea.  You might have to make a database that assigns IDs.

Share this post


Link to post
Share on other sites
15 hours ago, iedoc said:

Guids are one thing you could look into.

So they have to be able to get an ID while they are offline and not signed up. If they are offline then it won't really matter what their ID is until they come online. Once they are online you can assign them a new ID that is unique throughout everyone else that is online.

I'd use an integer as their ID. when they sign up, give them the next available integer. that can be their user ID, so even when they are offline they will use that ID. If they need to get an ID without signing up, maybe do something like a session ID, so once someone connects online, they will get the next available session ID. again if they are offline the ID won't matter what it is, only when they come online.

One last thing you can do is get device specific information, like the hard drive serial number plus mac address plus some other hardware serial. This would of course go into your platform dependent section of code, since each platform is going to have different ways of getting this information. once you have that string of serials, just md5 hash it or something to get a normalized string so everyone uses the same string size for their ID.

I wouldn't use the time they started the app with, because it would be possible for multiple people to have started the app at the same time in their local machines time

Thank you for the reply. I agree with your suggestion of using GUID (UUID) as User ID. I don't want to generate any identifier based device's hardware so that I don't violate Apple's or Google's guidelines.

Given I am fetching local machine's time in milliseconds, what are the chances of collision?

8 hours ago, Mike2343 said:

Some things to also consider:

1) Will the game keep scores online for others to see?

2) Are there achievements?

3) Are there levels/progress points/character(s) stats?

If yes, you will have to support them using multiple devices with the same ID or to transfer their profiles to a new device without losing all their progress too.  So having them type 64-128 bit integer is likely not a great idea.  You might have to make a database that assigns IDs.

Answers matching your questions:

  1. No
  2. No
  3. No

I am fine with if a new User ID is generated when a  player play the game on other device.

Share this post


Link to post
Share on other sites
19 hours ago, Octane_Test said:

There are lot of responses to use UUID/GUID. Generally, this approach looks fine but I am looking for a solution which can generate same User ID even if the user reinstall the game

If you want some kind of staticness you should take a look at Bitcoin. Some wallets give the feature to ressemble an Id by getting some kind of personal information into the generator process, a password for example or PIN. So even if a user would loose his wallet for some reason, chances are there to restore it from those informations.

But you know when going for Android there is a little chance that those data will be keeped for you even if a user uninstalles your app. We have had (even on newer Android versions) the problem that old game data was still there when we did not hard uninstall the app from ADB, an uninstall on the device gave those zombie data

Share this post


Link to post
Share on other sites
On 2/1/2018 at 6:43 AM, Octane_Test said:

There are lot of responses to use UUID/GUID. Generally, this approach looks fine but I am looking for a solution which can generate same User ID even if the user reinstall the game.

You definitely don't want to use the time. I just reread your original post and you said you keep track of the first time the user opens the app. there's only around 80 million milliseconds in a day, so it's highly likely that you will eventually have multiple people with the same id, especially since apps are open most often during certain times of day. I suppose you could use the datetime or epoch, that would be better, but still could result in duplicate id's if you were to say promote your game, and a bunch of people started playing your game that day. Also, where would you store that id? when they reinstall the app, or clear the app data, you'll probably lose that id unless you save it somewhere else on the phone

Could you clarify what you plan to do with the ID? Does the ID have to be the same every time the user comes online? or do you expect the ID to change every time they open the app? You don't want the user to get a new ID when they reinstall the app, but what if they change phones? can they get a new ID then?

Maybe a simple login system with username and password when they come online would do the trick, that way they will have the same ID no matter what, and you won't have to get information about their device or anything like that.

Share this post


Link to post
Share on other sites

For a mobile game i have been involved in, we used a server generated UUID and the mobiles unique device id to identify a user, then if they put in their email, later on which was optional, we could restore their account in case they reinstalled the app or changed their phone. 

Edited by flodihn

Share this post


Link to post
Share on other sites

Use the device's mac address?  If the user changes hardware, yeah, it'll change, but that's not super often.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
  • Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By Atwo Studios
      Hello everyone this is Anthony from Atwo Studios, as small indie company we have published 2 indie games using Game maker, one being ROY - Color Matching and the other being Solar Switch. Both can be found on iOS and the Google play store.

      For our third indie game we are wanting to make a golf puzzle based game, this would be on mobile too.

      Our current team consists of a designer,programmer and artist. I would like to add a person who is interested in making sounds effects/ music for our game.

      If you are interested in creating a game for portfolio work or just as a hobby, 
      please send me an email at : anthony@atwostudios.com

      PLEASE do attach any audio work so that my team and I can review it and determine if you are qualified for what we are looking for.

      Please check out our website for more information about us and the types of games we have made so far.
      atwostudios.com
      DOWN BELOW CAN BE FOUND VERY EARLY SNIPPET OF THE GAME TO GIVE YOU AN IDEA OF WHAT WE ARE MAKING.
      p.s. I am not a website designer
      2018-05-01_04-58-04.mp4
    • By mapmip
      Hi, I am fresh to database design, recently trying building my mobile multiplayer game, it will be something like pokemonGo.
      I have experience on MySQL, and I know some NoSQL engines like redis.
      I saw some existing game projects which store their data on both SQL database and noSQL database.
      Could anyone give some advice that what kind of data should store in SQL and what kind of data is better to be in noSQL.
      It would be nice if giving some real scenario examples.
      My understanding is data like user profile, purchase transactions should be in SQL.
      Field map information, enemy status can be NoSQL.  
    • By Nikita Sidorenko
      I'm making render just for fun (c++, opengl)
      Want to add decals support. Here what I found
      A couple of slides from doom
      http://advances.realtimerendering.com/s2016/Siggraph2016_idTech6.pdf Decals but deferred 
      http://martindevans.me/game-development/2015/02/27/Drawing-Stuff-… space-Decals/
      No implementation details here
      https://turanszkij.wordpress.com/2017/10/12/forward-decal-rendering/
      As I see there should be a list of decals for each tile same as for light sources. But what to do next?
      Let assume that all decals are packed into a spritesheet. Decal will substitute diffuse and normal.
      - What data should be stored for each decal on the GPU? 
      - Articles above describe decals as OBB. Why OBB if decals seem to be flat?
      - How to actually render a decal during object render pass (since it's forward)? Is it projected somehow? Don't understand this part completely.
      Are there any papers for this topic?
    • By Ming-Lun "Allen" Chou
      Here is the original blog post.
      Edit: Sorry, I can't get embedded LaTeX to display properly.
      The pinned tutorial post says I have to do it in plain HTML without embedded images?
      I actually tried embedding pre-rendered equations and they seemed fine when editing, 
      but once I submit the post it just turned into a huge mess.
      So...until I can find a proper way to fix this, please refer to the original blog post for formatted formulas.
      I've replaced the original LaTex mess in this post with something at least more readable.
      Any advice on fixing this is appreciated.
      This post is part of my Game Math Series.
      Source files are on GitHub.
      Shortcut to sterp implementation.
      Shortcut to code used to generate animations in this post.
      An Alternative to Slerp
      Slerp, spherical linear interpolation, is an operation that interpolates from one orientation to another, using a rotational axis paired with the smallest angle possible.
      Quick note: Jonathan Blow explains here how you should avoid using slerp, if normalized quaternion linear interpolation (nlerp) suffices. Long store short, nlerp is faster but does not maintain constant angular velocity, while slerp is slower but maintains constant angular velocity; use nlerp if you’re interpolating across small angles or you don’t care about constant angular velocity; use slerp if you’re interpolating across large angles and you care about constant angular velocity. But for the sake of using a more commonly known and used building block, the remaining post will only mention slerp. Replacing all following occurrences of slerp with nlerp would not change the validity of this post.
      In general, slerp is considered superior over interpolating individual components of Euler angles, as the latter method usually yields orientational sways.
      But, sometimes slerp might not be ideal. Look at the image below showing two different orientations of a rod. On the left is one orientation, and on the right is the resulting orientation of rotating around the axis shown as a cyan arrow, where the pivot is at one end of the rod.

      If we slerp between the two orientations, this is what we get:

      Mathematically, slerp takes the “shortest rotational path”. The quaternion representing the rod’s orientation travels along the shortest arc on a 4D hyper sphere. But, given the rod’s elongated appearance, the rod’s moving end seems to be deviating from the shortest arc on a 3D sphere.
      My intended effect here is for the rod’s moving end to travel along the shortest arc in 3D, like this:

      The difference is more obvious if we compare them side-by-side:

      This is where swing-twist decomposition comes in.
       
      Swing-Twist Decomposition
      Swing-Twist decomposition is an operation that splits a rotation into two concatenated rotations, swing and twist. Given a twist axis, we would like to separate out the portion of a rotation that contributes to the twist around this axis, and what’s left behind is the remaining swing portion.
      There are multiple ways to derive the formulas, but this particular one by Michaele Norel seems to be the most elegant and efficient, and it’s the only one I’ve come across that does not involve any use of trigonometry functions. I will first show the formulas now and then paraphrase his proof later:
      Given a rotation represented by a quaternion R = [W_R, vec{V_R}] and a twist axis vec{V_T}, combine the scalar part from R the projection of vec{V_R} onto vec{V_T} to form a new quaternion: T = [W_R, proj_{vec{V_T}}(vec{V_R})]. We want to decompose R into a swing component and a twist component. Let the S denote the swing component, so we can write R = ST. The swing component is then calculated by multiplying R with the inverse (conjugate) of T: S= R T^{-1} Beware that S and T are not yet normalized at this point. It's a good idea to normalize them before use, as unit quaternions are just cuter. Below is my code implementation of swing-twist decomposition. Note that it also takes care of the singularity that occurs when the rotation to be decomposed represents a 180-degree rotation. public static void DecomposeSwingTwist ( Quaternion q, Vector3 twistAxis, out Quaternion swing, out Quaternion twist ) { Vector3 r = new Vector3(q.x, q.y, q.z); // singularity: rotation by 180 degree if (r.sqrMagnitude < MathUtil.Epsilon) { Vector3 rotatedTwistAxis = q * twistAxis; Vector3 swingAxis = Vector3.Cross(twistAxis, rotatedTwistAxis); if (swingAxis.sqrMagnitude > MathUtil.Epsilon) { float swingAngle = Vector3.Angle(twistAxis, rotatedTwistAxis); swing = Quaternion.AngleAxis(swingAngle, swingAxis); } else { // more singularity: // rotation axis parallel to twist axis swing = Quaternion.identity; // no swing } // always twist 180 degree on singularity twist = Quaternion.AngleAxis(180.0f, twistAxis); return; } // meat of swing-twist decomposition Vector3 p = Vector3.Project(r, twistAxis); twist = new Quaternion(p.x, p.y, p.z, q.w); twist = Normalize(twist); swing = q * Quaternion.Inverse(twist); } Now that we have the means to decompose a rotation into swing and twist components, we need a way to use them to interpolate the rod’s orientation, replacing slerp.
      Swing-Twist Interpolation
      Replacing slerp with the swing and twist components is actually pretty straightforward. Let the Q_0 and Q_1 denote the quaternions representing the rod's two orientations we are interpolating between. Given the interpolation parameter t, we use it to find "fractions" of swing and twist components and combine them together. Such fractiona can be obtained by performing slerp from the identity quaternion, Q_I, to the individual components. So we replace: Slerp(Q_0, Q_1, t) with: Slerp(Q_I, S, t) Slerp(Q_I, T, t) From the rod example, we choose the twist axis to align with the rod's longest side. Let's look at the effect of the individual components Slerp(Q_I, S, t) and Slerp(Q_I, T, t) as t varies over time below, swing on left and twist on right:
      And as we concatenate these two components together, we get a swing-twist interpolation that rotates the rod such that its moving end travels in the shortest arc in 3D. Again, here is a side-by-side comparison of slerp (left) and swing-twist interpolation (right):

      I decided to name my swing-twist interpolation function sterp. I think it’s cool because it sounds like it belongs to the function family of lerp and slerp. Here’s to hoping that this name catches on.
      And here’s my code implementation:
      public static Quaternion Sterp ( Quaternion a, Quaternion b, Vector3 twistAxis, float t ) { Quaternion deltaRotation = b * Quaternion.Inverse(a); Quaternion swingFull; Quaternion twistFull; QuaternionUtil.DecomposeSwingTwist ( deltaRotation, twistAxis, out swingFull, out twistFull ); Quaternion swing = Quaternion.Slerp(Quaternion.identity, swingFull, t); Quaternion twist = Quaternion.Slerp(Quaternion.identity, twistFull, t); return twist * swing; } Proof
      Lastly, let’s look at the proof for the swing-twist decomposition formulas. All that needs to be proven is that the swing component S does not contribute to any rotation around the twist axis, i.e. the rotational axis of S is orthogonal to the twist axis. Let vec{V_{R_para}} denote the parallel component of vec{V_R} to vec{V_T}, which can be obtained by projecting vec{V_R} onto vec{V_T}: vec{V_{R_para}} = proj_{vec{V_T}}(vec{V_R}) Let vec{V_{R_perp}} denote the orthogonal component of vec{V_R} to vec{V_T}: vec{V_{R_perp}} = vec{V_R} - vec{V_{R_para}} So the scalar-vector form of T becomes: T = [W_R, proj_{vec{V_T}}(vec{V_R})] = [W_R, vec{V_{R_para}}] Using the quaternion multiplication formula, here is the scalar-vector form of the swing quaternion: S = R T^{-1} = [W_R, vec{V_R}] [W_R, -vec{V_{R_para}}] = [W_R^2 - vec{V_R} ‧ (-vec{V_{R_para}}), vec{V_R} X (-vec{V_{R_para}}) + W_R vec{V_R} + W_R (-vec{V_{R_para}})] = [W_R^2 - vec{V_R} ‧ (-vec{V_{R_para}}), vec{V_R} X (-vec{V_{R_para}}) + W_R (vec{V_R} -vec{V_{R_para}})] = [W_R^2 - vec{V_R} ‧ (-vec{V_{R_para}}), vec{V_R} X (-vec{V_{R_para}}) + W_R vec{V_{R_perp}}] Take notice of the vector part of the result: vec{V_R} X (-vec{V_{R_para}}) + W_R vec{V_{R_perp}} This is a vector parallel to the rotational axis of S. Both vec{V_R} X(-vec{V_{R_para}}) and vec{V_{R_perp}} are orthogonal to the twist axis vec{V_T}, so we have shown that the rotational axis of S is orthogonal to the twist axis. Hence, we have proven that the formulas for S and T are valid for swing-twist decomposition. Conclusion
      That’s all.
      Given a twist axis, I have shown how to decompose a rotation into a swing component and a twist component.
      Such decomposition can be used for swing-twist interpolation, an alternative to slerp that interpolates between two orientations, which can be useful if you’d like some point on a rotating object to travel along the shortest arc.
      I like to call such interpolation sterp.
      Sterp is merely an alternative to slerp, not a replacement. Also, slerp is definitely more efficient than sterp. Most of the time slerp should work just fine, but if you find unwanted orientational sway on an object’s moving end, you might want to give sterp a try.
    • By Final Flames
      Hi everyone I am newbie got some ideas , but don't know how the whole things work out .
       I want to learn how things work with a developer from start to finish.
      So ideally looking to team up with android developer to complete some simple fun games.
      So either reply me here or mail at palani650@gmail.com 
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!