Unity units are actually less than 1 meter unless the earth is flat.

I’m trying to make a simulation of the flat earth belief to debunk it but when I go to make a sim of the real world to show the Earths curvature from different heights, the Earth is much smaller than it should be. The radius of the Earth is 6 million meters. A sphere of this radius (a sliver of a half sphere to save on memory) in Unity units has clearly visible curvature and you don’t have to go up very high at all (30 or 40 meters) to see the curve even more. I tried even 20 million Unity units of radius and it still looks small compared to the earth and a curve can be easily measured (though not very obvious) even at surface level.

I know I get floating-point errors at that size but would that contribute to it being smaller than it should be? Or are Unity units actually slightly less than 1 meter? They say the sizes are arbitrary but with stuff like this it matters, and relative to an average persons size and the size of a first-person-controller in Unity it should be one meter however with larger numbers everything is proportionally smaller. I’m logical enough to assume it is a Unity thing rather than it proving the Earth is flat but I can’t make this if it is only going to reinforce flat-Earthers.

Interesting topic! Actually it’s correct that “the sizes are arbitrary” and relative to the viewer, so to look at a small sphere from a short distance is exactly the same as looking at a huge sphere from a greater distance. However there is another factor you might not have tried dealing with which is the camera’s field of view which plays a big role defining what is big and what is not to the viewer, it’s more like an optical illusion and I believe that the human eye’s field of view is around 120 degrees (Unity camera default FOV is 60), it’s actually more complicated than that and needs some specificity and experience in the field of optics and computer graphics. The whole point is that you’ll never do a simulation that is 100 percent accurate, after all you are dealing with a flat bounded screen! I think in such case as yours using virtual reality may fill some gaps and gives better accuracy in terms of optics.

First of all you can avoid all the hassle by simply using Google Maps in 3D mode. Here’s a view on the Eifel tower in paris (it’s a google.de link since google aggressively prevents you to use google.com if you are located in germany so hopefully it opens as intended). Note that the eiffel tower has an height of about 300m. If you zoom out you shouldn’t see any curvature at all until you are really far out. Unfortunately google maps doesn’t tell you your view height, though you can approximately deduce the height in relation to the tower.

Apart from that i achieved a similar result in Unity. However i used a scale of 0.001. So one unit becomes 1000m. I actually implemented a crude straight forward raytracer for rendering the earth. I simply used Unity’s SphereCollider(radius 6000, position (0, -6000, 0)) and Collider.Raycast to do the ray tracing. That means the world origin (0,0,0) is just at the surface of the sphere. The raytracing looks like this:

void UpdateTex()
{
    UpdateRes();
    var cam = Camera.main;
    var col = GetComponent<SphereCollider>();
    var center = transform.position;
    for (int y = 0; y < m_Height; y++)
    {
        int yOff = y * m_Width;
        for (int x = 0; x < m_Width; x++)
        {
            Ray r = cam.ScreenPointToRay(new Vector3(x, y));
            RaycastHit hit;
            Color c = Color.red;
            if (col.Raycast(r, out hit, float.PositiveInfinity))
            {
                var dir = (hit.point - center).normalized;
                dir = transform.InverseTransformDirection(dir);
                // local lat / lon
                var l0 = (Mathf.Asin(dir.y) / Mathf.PI) + 0.5f;
                var l1 = Mathf.Atan2(dir.z, dir.x) / (Mathf.PI*2);
                // sample texture
                c = earthTex.GetPixelBilinear(l1, l0);
                // apply simple directional lighting
                c = c * Vector3.Dot(hit.normal, -light.forward);
                c.a = 1;
            }
            else
                c = Color.clear;
            m_Colors[yOff + x] = c;
        }
    }
    tex.SetPixels(m_Colors);
    tex.Apply(false);
}

The “UpdateRes” method just sets up the texture so it matches the screen resolution as well as creating the Color array (m_Colors).

As texture i used the blue marble (highest resolution), though it’s just to provide some structure to the surface. I placed a 1m large cube (scale of 0.001) at (0, 0.0005, 0). The camera uses a near clipping plane of “0.01” (you can’t set it lower in Unity) and a far clipping plane of 1000, though the clipping planes have no meaning to the raytracer ^^. Here’s an animated gif as the camera is moving straight up in steps:

Note that the “white thing” in the first two images is the 1m cube which is about 50m in front of the camera. The ray tracer will render just the earth into a texture which is then blitted to the screen as “background” using a seperate camera. Of course the real time performance is horrible. At this small resolution, when the whole sphere is in view i get about 7 frames per second ^^. If the sphere is completely off screen i get 26 fps (since no texture lookup and no lighting calculation takes place, just about 70000 raycasts and the texture update)

As i use a scale of 0.001 that means when the camera is at y= 0.01 we are at 10m height above ground. “0.1” would be 100m and “1.0” would be 1000m. The sphere is a perfectly round sphere since we just raycast against a sphere collider to render that image.

ps: the location on earth is just an arbitrary location. I just rotated the earth 45° on x to actually have land below and not just ice ^^. I also just realised even i used the 8k earth texture it had it’s default max size of 2k . Though the difference it’s that huge at close distance since at 8k we only have 0.38 pixels per seamile. (btw. the seamile is the only length measurement we use on earth that actually makes sense ^^)

Unity units ARE arbitrary, their size does NOT matter. Ever. Nothing about the Unity engine implies a certain real world scale except for the default value of Physics.gravity which can be easily adjusted to any scaling you want. The question whether curvature can be seen on a sphere is independent of the absolute scale (like basically everything in geometry), just relative distances matter.

Also remember that the earth is not a perfect sphere and since this is a real simulation, you need to have in mind other factors like atmospheric refraction.

Earth has an atmosphere of air, whose density and refractive index vary considerably depending on the temperature and pressure. This makes the air refract light to varying extents, affecting the appearance of the horizon.

I hope any of this helps a bit, I really want to see that simulation!

Apparently, there is actually a slight curve just like I was seeing in the simulation and like we see at 50m in bunny83’s sim. It’s just more apparent with pixels. I grabbed a photo of the ocean horizon, stretched it out vertically to exaggerate any curve that might be there, overlayed a straight line and voila, there is indeed a detectable curve.

Let the information speak for itself, it doesn’t need your help. And don’t be afraid of alternative views.