- Home /

# Adjust scale of object based on distance to maintain same perceived size

Hi all,

Having a little trouble explaining what I am trying to do so please bear with me. I am working on a demo that involves massive scales in the space. To make things more manageable I want to do is keep the planets closer together in game units, but scale them so that they appear to be the real world size as seen from that location.

For example let's say the camera is at the Earth. Instead of putting the sun 150 million kilometers away and making it have a radius of 695,700km, I want to put it say just 10,000 meters away from the Earth but scale it down (some unknown amount) so that the PERCEIVED size would be the same.

However despite an hour or so of Googling I can't seem to figure out how to calculate the scale factor based on distance. I ran into some topics about perceived angle, but I don't understand what that means, nor how I could even translate an "angle" into a size in game.

I feel like I am close to the answer, spiraling in on it but not quite hitting it. Here is the code I am currently using. This is in C#

```
Vector3d activeRealPosition = activeBody.GetOrbitPosition("real");
Vector3d activeGamePosition = activeBody.GetOrbitPosition("play");
Vector3 realOrbitPosition = Vector3.zero;
Vector3 actualOrbitPosition = Vector3.zero;
if (TypeOfBody != BodyType.Star)
{
realOrbitPosition = transform.TransformPoint(_orbits["real"].position); // CelestialOrbit stores position in local space
actualOrbitPosition = transform.TransformPoint(_orbits["play"].position);
}
double realDistance = Vector3d.Distance(activeRealPosition, realOrbitPosition);
double actualDistance = Vector3d.Distance(activeGamePosition, actualOrbitPosition);
Debug.Log("Real Distance: " + realDistance + ", Actual Distance: " + actualDistance);
// actual distance should always be much smaller than real distance
if (actualDistance > realDistance)
Debug.LogWarning("[UpdateScale] Actual distance is larger than real distance");
double difference = (realDistance - (realDistance-actualDistance)) / (realDistance);
Debug.Log("Difference: " + difference);
double newScale = RealRadius * difference;
transform.localScale = Vector3.one * (float)newScale;
```

I am basing it on some manual tests I did just positioning two objects at different distances and looking if they appear the same size, and in those manual setups they did. So I then tried to apply that math to the real deal, but it doesn't work. The math is based on: http://www.calculatorsoup.com/calculators/algebra/percent-change-calculator.php

Determine your planet's size on the screen:

```
float getScreenSize ()
{
transform.LookAt(Camera.main.transform, transform.up);
Bounds bounds = gameObject.GetComponent().bounds;
Vector3 v1 = Camera.main.WorldToScreenPoint(transform.position - 0.5f * bounds.size.y * transform.up);
Vector3 v2 = Camera.main.WorldToScreenPoint(transform.position + 0.5f * bounds.size.y * transform.up);
return Vector3.Distance(v1, v2);
}
```

I have assumed the shape of your planets is spherical. Note that the results of the above will not be reliable with the planets screen size is around or exceeds the screen height.

Then rescale the object to the desired size by stetting transform.localScale.

Interesting take on the problem, but I am not sure using the camera to determine screen size would work as the camera isn't always seeing these objects. Basically body that isn't the active planet needs to be scaled down, in case the player does move the camera in such a way as to see them.

In any case, I finally found my problem with fresh eyes this morning. I should not have been transforming the orbital values from Local to World space. Once I changed that it started working well.

**Answer** by Glurth
·
Dec 31, 2016 at 11:49 PM

Note: I have not actually tested this out. Please let me know if it fails, so I can remove this post.

I think you can use the law of similar triangles to figure this out.

Givens:

```
SunActualRadius, SunActualDistanceFromCamera, SunGameUnitDistanceFromCamera
```

Desired output:

```
SunGameUnitRadius
```

Make a right triangle using `SunActualRadius`

as side A, and `SunActualDistanceFromCamera`

as side B. The angle to the hypotenuse defines how “big” the sun looks from the camera position.
How we use this angle, is simply by duplicating it: Draw an identical right triangle, with the same angles.
Now, label side A of this new triangle `SunGameUnitRadius`

and side B `SunGameUnitsFromCamera`

.
Since these two triangles are identical, the ratio of sides A and B will also be identical.
Expressed as a formula:

```
SunActualRadius/ SunActualDistanceFromCamera = SunGameUnitRadius/ SunGameUnitDistanceFromCamera
```

Solve for our desired output:

```
SunGameUnitRadius = SunActualRadius * SunGameUnitDistanceFromCamera / SunActualDistanceFromCamera
```

**Answer** by elenzil
·
Jan 01, 2017 at 05:19 AM

i think you're making this too hard.

just scale everything down by some constant factor.

in this case your scale factor would be 10,000 meters divided by 150,000,000,000 meters. so just multiply 695,700,000 by (10,000 / 150,000,000,000) to get the scaled radius.

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.

### Follow this Question

### Related Questions

Calculate launch angle based on launch direction 2 Answers

Sprite doesn't flip correctly. 1 Answer

How to get the correct ratio of collision distance to total scale? 1 Answer

Calculate speed for distance with bpm 1 Answer

How to simplify the equation of a moving vertex if its object is squeezed? 0 Answers