3
\$\begingroup\$

I am trying to make a simple top down scrolling shooter using Unity3D comprising of the following elements:

1) Top down orthographic camera: points at 65 degrees towards the ground. At a height of 1000 units. Size 100.

2) Spaceship: Moves around based on the up/down/left/right keyboard commands. Each press moves the ship 1/100 of the screenwidth in distance. I keep its position in screen coordinates and use a ray cast to project it to a height of 500 units off the ground in the camera space using the following code:

Ray ray = mainCamera.camera.ScreenPointToRay(screenLocation);
Plane plane = new Plane(new Vector3(10, 500, 0), 
    new Vector3(0, 500, 10), 
    new Vector3(-10, 500, 0));
float enter;
plane.Raycast(ray, out enter);
transform.position = ray.origin + ray.direction * enter;

3) A camera scroll component that moves the camera forward by 0.75 units every frame.

When I play the game the spaceship is controlled in screen space and its world coordinates are calculated relative to the scrolling camera. The camera starts at y: 1000, z:0 and z is incremented by 0.75 (scroll per frame).

The problem I am running into is that after a while, the player ship begins jittering. The jittering gets worse the longer the game goes on. The jittering is noticeable around the time z becomes 4200 which gives me about 1m30s game time at 60fps before the jittering starts. The levels I want to create would only be less than 20 mins which would mean that I need a max Z value of 2700 assuming my Z started at -2700 and finished at +2700.

I realised this must be caused by the limitations of floating point precision so I started playing around with the numbers to see what I could do to solve this.

I found that modifying the height of the camera to 50 and the ship to height 25 whilst keeping the orthographic camera size at 100 allowed me to set the distance to around 32,000 with no jittering. I didn't fully understand why this worked as the values of the ship transform and camera transform were still truncated to 2 decimal places at the extreme distance of 32,000. Scaling the camera size to 5 brought back the original problem. This 'fix' seemed mighty hacky to me though as it pretty much screws up the scale of objects in the game and only looks 'normal' because of the orthographic perspective. I don't know how well this would play with other things I plan to add to the game.

I have 3 options at this point:

1) Continue to find a way to get it to work with the limit of 20 minutes and using a virtual camera that tracks around the world coordinate frame. This would be great if it works as I could easily use the editor to add enemies at correct positions e.t.c.

2) Make it so that when it reaches a z limit, the camera resets to z = 0 and all objects in the scene revert back relative to the camera shift. The downside to this I guess is that I would need to figure out how to get the objects to shift back correctly when the limit is reached and also it would be trickier to use unity's editor to do enemy placement e.t.c.

3) Keep the camera at position z=0 and scroll the world backwards towards the camera. This seems like the ideal thing to do as I could place objects and scripts in unity world space and when the game runs, these elements could shift back every frame. I don't know how to achieve this at the moment however. I thought of using a parent object that moves back by 0.75 every frame. Enemies would be children of this object and the player camera would not be a child but be at the same place all the time. However I think this would still cause problems as maybe enemies placed far out in the z direction might jitter as they moved around. Is this concern legitimate?

I am wondering if anyone has any better ideas to solve my problem or understands why changing the height scale seems to temporarily fix the problem?

\$\endgroup\$
  • \$\begingroup\$ If you stop moving the camera after the player starts jittering, does it still jitter? What do the player position values look like when it's jittering, are they jittering too? It doesn't seem like you'd notice floating point precision issues at such low values. I think something else is going on. \$\endgroup\$ – MichaelHouse Sep 8 '13 at 14:45
  • \$\begingroup\$ would it be possible to keep the ship in the same place but move the scenery around it? \$\endgroup\$ – ratchet freak Sep 8 '13 at 15:00
  • \$\begingroup\$ @Byte56 - I stopped the camera scroll but the jittering still seems to occur when I move the player ship along the z direction. The movement is not entirely smooth. The player does not jitter if both the camera and player are stationary. \$\endgroup\$ – Jkh2 Sep 8 '13 at 16:54
1
\$\begingroup\$

Another, very invasive, fix might be to create the levels in sections. Each section is built around a local origin and is brought in when needed (and offset) and prior levels discarded. At each transition the offsets are reapplied to keep active levels in a local range.

I'm unsure if that's possible in the Unity environment, however.

Kind of like Gumby train tracks

\$\endgroup\$
1
\$\begingroup\$

That jitter you see comes from the way floating point numbers work. A float has only a fixed number of significant digits. If they are storing a large number, the decimals suffer from loss of precision.

Let me put an example using decimal numbers. Suppose floats can hold say, 5 significant digits only.

Also, let's say the ship is positioned at 10.000, If you want to move it slightly, you could move it to position 10.001. However, if instead the ship is located at position 10000, you can only move the ship to 10001, which is a jump of 1, instead of the 0.001 you previously had. Hence the jitter.

The solution 3) you mention would be the best option. Try having the coordinates of the camera and the ships as small as possible. In particular their absolute value should be small compared to the distance between them. That is, don't place the camera at position 10000 and the target at position 10005, instead make it so they are closer to 0 and 5.

\$\endgroup\$
0
\$\begingroup\$

I was facing same issue on "large" world. My PointLight shadows started to jittering at coords >4090, it also depends how you set your Perspective (near and far plane), if near plane is around 0,1 (for big close up), the world starts jittering at around 4000, if you set near plane to 1.0f, you are safe till 8000 coords (in my case). But this is not solution, just improvement.

Solution (also for me was) is your option 3. Have static camera that can see, let's say 2000px far (much enough) and you move with world around it. Camera will be the origin of the world.

My pointlights at around Zero: http://www.youtube.com/watch?v=GFVaU9ZO2rQ

My pointlights at the edge around (4096,4096): http://www.youtube.com/watch?v=5V9zVoXFG9c

You can see the jittering, till camera finally stops moving. Yes it is float issue with high numbers.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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