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?