For example the famous Flappy Bird game, or anything that sort really, is the player(in this case the bird, or the camera whichever you prefer) moving forward or is the whole world moving backwards(the bird only changes Y position and has a constant X position)?

  • 1
    We have deleted many off-topic comments from this question and its answers. We've also moved several reasonable discussions to chat, in some cases repeatedly. Despite this, several users have felt the need to ignore the fact that comments aren't for extended discussions and continued on. As such, this question has been temporarily locked. – Josh Dec 7 '17 at 16:18
up vote 89 down vote accepted

Both options work.

But if you want the endless runner to be truly endless, you will have to keep the player stationary and move the world. Otherwise you will eventually hit the limits of the variables you use to store the X-position. An integer would eventually overflow and a floating point variable would become increasingly less accurate which would make the gameplay glitchy after a while. But you can avoid this problem by using a large enough type that nobody will encounter these problems within the timespan one could conceivably play in one session (when a player moves 1000 pixels per second, a 32 bit integer will overflow after 49 days).

So do whatever feels conceptually more intuitive to you.

  • Comments are not for extended discussion; this conversation has been moved to chat. – Josh Dec 6 '17 at 16:17
  • 1
    I don't think that is solves anything. Instead of keeping player's (and camera) position, you keep world's scroll position - how is that any different? – Agent_L Dec 8 '17 at 13:26
  • 1
    @Agent_L Generally, worlds are generated piecemeal, and each piece has its X/Y position. When the piece gets behind the player by enough (e.g. offscreen), it's deleted, and they're only generated a certain amount in advance, so they're always within a relatively small range -- one game I made never had a coordinate greater than ~1000 or less than 0, despite being an infinite, randomly generated runner, because of that -- I kept track of the player's position in each chunk, and each chunk's index in the sequence. – Nic Hartley Dec 8 '17 at 20:14
  • I don't buy the "variable overflow" concept. If the player isn't moving, then the "background" will be negatively offset by the same amount that the player would be offset if it were moving. Both cases would run into exactly the same problem (in opposite directions), and both would require special handling at the limits of overflow. – spender Dec 10 '17 at 18:27
  • 2
    at 1000 pixels per second it would take over 586 million years to go over an 64 bit integer. This is only really a problem if you are using really small types like 16 bit integers. – Lyndon White Dec 11 '17 at 9:21

I slightly disagree with Philipp's answer; or at least with how he presented it. It gives the impression that moving the world around the player might be a better idea; when it's the exact opposite. So here is my own answer...


Both options can work, but it's generally a bad idea to "invert the physics" by moving the world around the player rather than the player around the world.


Performance loss/waste:

The world will usually have a lot of static or sleeping objects. The player will have one, or relatively few objects. Moving the whole world around the player, means moving everything in the scene except for the player. Static objects, sleeping dynamic objects, active dynamic objects, light-sources, sound-sources, etc; all have to be moved.

That's (obviously) considerably more expensive than moving only what's actually moving (the player, and maybe a few more stuff).


Maintainability & Extensibility:

Moving the world around the player makes the world (and everything in it) be the point where things are most actively happening. Any bug or change in the system means that, potentially, everything changes. This is not a good way to do things; you want bugs/changes to be as isolated as possible, so that you don't get unexpected behaviors somewhere you haven't made changes to.

There are also many other problems with this approach. For example, it breaks many assumptions of how things are supposed to work in-engine. You'd not be able to use dynamic RigidBody for anything other than the player, for example; as an object with an attached RigidBody not set to kinematic will behave unexpectedly when setting position/rotation/scale (which you'd be doing every frame, for every object in the scene, except the player 😨)


So the answer is to only move the player then!

Well...yes and no. As mentioned in Philipp's answer, in an infinite-runner type of game (or any game with a large seamless explorable area), going too far from origin would eventually introduce noticeable FPPEs (Floating-Point Precision Errors), and further still, eventually, overflow the numeric type, either causing your game to crash, or, basically, make the game-world smoke crack...On steroids! 😵 (because by this point, FPPEs would make the game already be on "normal" crack)


The actual solution:

Do neither and do both! You should keep the world static, and move the player around it. But "re-root" both, the player and the world, when the player starts getting too far from the root (position [0, 0, 0]) of the scene.

If you keep the relative position of things (player to the world around it), and do this process in a single frame-update, the (actual) player won't even notice!

To do it, you have two primary options:

  1. Move the player to the root of the scene, and move the world chunk to it's new position relative to the player.
  2. Think of the world like a grid; move the part of the grid that the player is in to the root, and move the player to it's new position relative to that part of the grid.

Here is an example of this process in action


But, how far is too far?

If you look at Unity's source-code, they use 1e-5 (0.00001) as the basis for considering two floating-point values "equal", inside of Vector2 and Vector3 (the data-types responsible for objects' positions, [euler-]rotations and scales). Since floating-point precision loss happens both ways away from zero, it's safe to assume that anything under 1e+5 (100000) units away from the scene root/origin is safe to work with.

But! Since...

  1. It's more appropriate to make a system to handle these re-rooting processes automatically.
  2. Whatever your game is, there is no need for a contiguous "section" of the world to be 100000 units (meters[?]) wide.

... then it's probably a good idea to re-root far sooner/more often than that 100000 units mark. The example video I provided seems to do it every 1000 units or so, for example.

  • 2
    Comments are not for extended discussion; this conversation has been moved to chat. Please use that chat instead of posting more comments here. – Alexandre Vaillancourt Dec 5 '17 at 13:25
  • > That's (obviously) considerably more expensive than moving only what's actually moving < Is it? When rendering, you will anyway have to do a matrices multiplication with the camera matrix on all objects, having the camera fixed at the identity would be less expensive in this manner. – Matsemann Dec 11 '17 at 11:08
  • That moment when game development becomes unity development... – LJᛃ Dec 11 '17 at 13:45
  • @Matsemann - If you had went to chat, you'd have noticed this is not a new point. As already explained, render NOT-EQUALS scene; they are different and almost completely independent subjects and pipelines. Doing an inversion of frame of reference in the way objects are positioned in the scene will mean you will have a heavier process on both ends, rather than just in render. --- Also, even if performance was equally-traded as you argue, all other problems with the inversion would still remain unsolved, making that approach still worse than the re-rooting one. – XenoRo Dec 11 '17 at 20:07
  • @LJᛃ The question was made about unity specifically (see OP's tags prior to D. Everhard's [IMHO defacing] edits), and so the answer was tailored to reflect that. --- But here's the best part: Be it Unity, Unreal, CryEngine, Source, etc... The best and/or most popular engines work this way (and they do it for a reason), so the answer is not only perfectly valid in general, but the points being made are still at the pinnacle of accuracy. Generally speaking, if you invert the physics' frame of reference, you can expect to run into problems, specially on dynamic objects. – XenoRo Dec 11 '17 at 20:22

Building off of XenoRo's answer, instead of the re-rooting method they describe, one could do the following:

Create a circular buffer of parts of your infinite map generated, which your character moves through with position updated with modulo arithmetic (so you just run around the circular buffer). Start replacing parts of your buffer as soon as your character leaves the chunk. The players update equation would be something like:

player.position = (player.position + player.velocity) % worldBuffer.width;

here is a pictoral example of what I'm talking about:

enter image description here

Here is an example of what happens on wrapping at the end.

enter image description here

With this method you don't run into precision errors ever, but you may need to make a very large buffer if you intend to do this in 3d with very far view distance (as you will still need to be able to see ahead of yourself). If its flappy bird your chunk size will probably only be as large as it needs to be to hold a single scene for a single screen, and your buffer can be very tiny.

Note that you will start to get repeating results with ANY prng, and the max number of non repeating sequences of a PRNG generation is typically less than the length of pow(2,number of bits used internally), with merzenne twister this isn't much of an issue, as it uses 2.5k of internal state, but if you use the tiny variant, you have 2^127-1 max iterations before repeat (or worse), this is still an astronomically large number however. You can fix repeating period problems even if your PRNG has a short period via good avalanche mixing functions for the seed (as you add more state implicitly) repeatedly.

  • Comments are not for extended discussion; this conversation has been moved to chat. – Josh Dec 5 '17 at 16:36

As already asked and accepted, it really depends on the scope and style of your game, but since it wasn't mentioned: FlappyBird moves the obstacle across the screen, rather than the player across the world.

A spawner is instantiating objects off screen with a fixed speed in the Vector2.left direction.

  • 2
    That works for FlappyBird because it's a very simple game. As mentioned in my answer, the same technique, while still possible, would be very problematic on anything more complex (with more world objects / details), like Subway Surfer. – XenoRo Dec 4 '17 at 22:57
  • 14
    I agree, and your answer is very thorough. I just didn't see anyone mention which method flapping bird actually uses, so I figured I'd add it. – Stephan Dec 4 '17 at 23:00

protected by Alexandre Vaillancourt Dec 6 '17 at 20:02

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.