Recording Player Time Ghosts

Hello, I am currently trying to see if it is feasible to add a ghost system to my game that can record a player’s best times on levels.

Right now, my current system samples the following values from the player:

  • Player’s position as a Vector3
  • Player’s rotation (the LookVector of their HumanoidRootPart) as a Vector3
  • Player’s currently playing animation track (if there are multiple, it chooses the first) as an integer
  • The time position of the animation track as a float
  • The speed of the animation track as a float

I believe I can serialize each sample in about 80 characters. If I record the player’s performance at a frequency of 15 Hz on a level that takes around 90 seconds to complete, the number of characters required to save the ghost would be about 80 * 15 * 90 = 108,000 characters.

The game will have several dozen levels, so for each level a player plays, a new key will probably be needed. (If M players play N levels, I’ll need MN keys.) I’m going to use a DataStore separate from where the player’s profile is saved to record all these ghosts.

I’ve never had a situation where I needed to use several dozen keys for a single player (with each using about 40% of their data limit). Do I have anything to worry about with my approach? And is there some better way to save the player’s performance than the way I listed?

3 Likes

I suppose you could do it that way, although as you say it’s kind of daunting to start using numerous keys for the same player.

I’ve been taking a numerical analysis course at uni and I just recently learned how to do linear interpolation/approximating functions given large datasets. It’s basically how vector graphics works internally (assuming bezier curves aren’t the only internals at play).

The issue is that you might not have a good data set to work with. You could end up using a Fourier series as a function approximation but those are a lot harder to deal with, especially for saving something like player positions and such. However it should technically be feasible.

So there’s basically two challenges if you take this approach:

  1. Learning how the math works and implementing a good algorithm
  2. Approximations and how lenient you can be with them

Since this method is based on approximating, you have to have a tolerance for error margin (which is usually defined, again this is part of the learning :slight_smile: ) so in theory it seems safe to use. Yet some data sets will be ill-conditioned (fancy word for “doesn’t approximate well”), so you would need to account for this in case it produces a function that is much larger than saving the raw data itself.

Not sure if anyone has tried implementing something like this, and like I said it’s still new for me so even I’m not sure if it is necessarily going to work the way I am describing it. But I thought I might chip in, hopefully it amounts to something :rofl:

2 Likes

You could try saving inputs instead. When the player presses a button, it saves the input and the time it was pressed. Take new super mario bros wii for example, for the hint videos, a set of inputs are loaded instead of a video, to save on storage.

1 Like

You can also remove every animation data point as long as it is a continuation of the previous animation.

Requiring only the need for the points of change beyond predictability (same animation continuing)

1 Like

Reading this gave me an idea to cut down the sample rate and add an additional data point for the velocity which would allow me to use Hermite Splines to approximate their position. I might experiment with that. (Although I would still have to use the same saving method.)

1 Like

What a cool feature

Sounds quite storage heavy tho. Even if your below the limit of storage, a feature like this will require optimal implementations on your data loading and run recreation algorithm.

But side-chaining data does sound incredibly useful. Like storing the stop and start of animations, and the beginning and endings of user inputs.

If anything try and focus your data on keeping track of differences between points in time.
Like take a difference sampling constant x, monitor the user while they play. Have a difference sum y, and over equally-timed intervals check the difference between some scalar in movement. Add this to the difference sum y on every interval, then check if y is greater than your sampling constant x. If it is, record the interval with the summation of change since your last recording. Reset y and continue. Ideally samples are only recorded when noticable beyond a certain point.

1 Like

I like the user input idea, but after giving it some thought I do not think it would hold. The problem is I’m not quite sure how much error it would introduce into the approximations, plus I think it would not translate well for my game due to the nature of Roblox controls (movement depends on camera direction for certain keys).

I have been looking into the same scheme of work, but for a different purpose. It is difficult to actually have it accurately tracking the character’s behavior. Perhaps utilizing the tracking on the Humanoid may be an optimal idea, I’ll return back to this project for more testing to see if I can create “ghosts”.