Search Unity

Scaling Sprites properly

Discussion in 'Scripting' started by Nigey, Jul 6, 2015.

  1. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Hi Guys,

    For a full day now I've been trying to scale one object, to a percentage size of another object (2 sprites).

    I've created two objects with a SetInitialSize() function. The first sets it's own size to the viewport, keeping it's aspect ratio (working correctly). The second one, takes that object's size AFTER it's been scaled to the viewport, and is made to a percentage size of that sprite. The issue being that I'm not able to find the size of the sprite after it's been scaled.

    FIRST ONE CALLED
    Code (CSharp):
    1.     public bool SetInitialSize()
    2.     {
    3.         SpriteRenderer sr = GetComponent<SpriteRenderer>();
    4.  
    5.         if(sr)
    6.         {
    7.             Camera cam;
    8.             if(cam = transform.parent.GetComponent<Camera>())
    9.             {
    10.                 float worldScreenHeight = (float)(cam.orthographicSize * 2.0);
    11.                 float worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
    12.                 float newLocalScale = (worldScreenWidth / sr.sprite.bounds.size.x);
    13.  
    14.                 Debug.Log("BEFORE" + GetComponent<SpriteRenderer>().sprite.bounds.size);
    15.  
    16.                 transform.localScale = new Vector3(newLocalScale, newLocalScale, 1);
    17.                 SetScaleClamp(transform.localScale);
    18.  
    19.                 Debug.Log("AFTER" + GetComponent<SpriteRenderer>().sprite.bounds.size);
    20.             }
    21.             else
    22.             {
    23.                 Debug.Log("MapHandler::SetInitialSize() - Camera not found as parent to Map Object!");
    24.                 return false;
    25.             }
    26.         }
    27.         else
    28.         {
    29.             Debug.Log("MapHandler::SetInitialSize() - SpriteRenderer Component not found!");
    30.             return false;
    31.         }
    32.         return true;
    33.     }
    SECOND ONE CALLED
    Code (CSharp):
    1. public bool SetInitialSize()
    2.     {
    3.         SpriteRenderer sr = GetComponent<SpriteRenderer>();
    4.      
    5.         if (sr)
    6.         {
    7.             Camera cam;
    8.             if (cam = GameObject.Find("MapViewCamera").GetComponent<Camera>())
    9.             {
    10.                 // Grid height in pixels from Map
    11.                 Bounds mapBounds = GameObject.Find("Map").GetComponent<SpriteRenderer>().sprite.bounds;
    12.                 Bounds imgBounds = GetComponent<SpriteRenderer>().sprite.bounds;
    13.                 float sizeY = imgBounds.size.y;
    14.                 float gridSize = mapBounds.size.y / 6;
    15.                 Vector3 newScale = new Vector3(gridSize / sizeY, gridSize / sizeY, gridSize / sizeY);
    16.                 transform.localScale = newScale;
    17.  
    18.                 // Set correct z position according to parent (should be the map)
    19.                 Vector3 pos = transform.position;
    20.                 pos.z = transform.parent.transform.position.z - 1;
    21.                 transform.position = pos;
    22.             }
    23.             else
    24.             {
    25.                 Debug.Log("ProtractorHandler::SetInitialSize() - Camera not found as parent to Map Object!");
    26.                 return false;
    27.             }
    28.         }
    29.         else
    30.         {
    31.             Debug.Log("ProtractorHandler::SetInitialSize() - SpriteRenderer Component not found!");
    32.             return false;
    33.         }
    34.         return true;
    35.     }
    AND HERE IS WHERE THEY'RE CALLED AND CONTROLLED
    Code (CSharp):
    1.     void OnEnable()
    2.     {
    3.         if (bInitiliased)
    4.         {
    5.             if (!SetInitialSizeObjects())
    6.                 Debug.Log("MapObjectHandler::OnEnable - SetInitialSizeObjects Failed!");
    7.         }
    8.     }
    9.  
    10.     bool SetInitialSizeObjects()
    11.     {
    12.         if(map)
    13.         {
    14.             MapHandler mapHandler;
    15.             if (mapHandler = map.GetComponent<MapHandler>())
    16.             {
    17.                 if (mapHandler.SetInitialSize())
    18.                 {
    19.                     if(protractor)
    20.                     {
    21.                         ProtractorHandler protHandler;
    22.                         if (protHandler = protractor.GetComponent<ProtractorHandler>())
    23.                         {
    24.                             if(protHandler.SetInitialSize())
    25.                             {
    26.                                 return true;
    27.                             }
    The main issue is that the bounds of the object don't change before or after setting localScale, so there's no way to find it's object size. The Console is returning:

    BEFORE(44.4, 29.5, 0.2)
    AFTER(44.4, 29.5, 0.2)

    I've tried changing the object to different scales before the game starts, to make sure there IS a change in size. Looking at the game visually. It is actually changing it's size. Can anyone make any suggestions?

    Thanks!
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    To double check that there isn't any code changing it's scale before these scripts are doing anything I've added:

    Code (CSharp):
    1.  
    2.     void Start ()
    3.     {
    4.         Debug.Log("STARTING" + GetComponent<SpriteRenderer>().sprite.bounds.size);
    5.         bInitiliased = true;
    6.     }
    7.     void OnDisable()
    8.     {
    9.         Debug.Log("INITIAL" + GetComponent<SpriteRenderer>().sprite.bounds.size);
    10.     }
    (On start up the object is disabled until it's used)

    which also returns: INITIAL(44.4, 29.5, 0.2), STARTING(44.4, 29.5, 0.2)

    There is no change to bounds. Though visually, there is obviously a change. What is happening with Sprite Bounds?
     
  3. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    After doing more research I've found that the object is scaling correctly, however it's scaling to the sprite's original size, ignoring localScale. Is there a way to find it's pixel size after localScale has been applied? Or am I to manually calculate the pixel size by reducing the the localScale as a percentage from the total image size?
     
  4. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Shameless bump lol.
     
  5. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Sprite.bounds does not change as a reaction to changing the scale of your object. It is the bounds of the sprite in conjunction with Sprite.pixelsPerUnit. Meaning, it only changes if either the sprite itself changes (obviously), or if Sprite.pixelsPerUnit changes.

    In other words, a Sprite is not aware of the game objects it is used on.
     
  6. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    This now makes sense. Does that mean it's impossible to scale one sprite in proportion to another one's scale, without really going into some maths on their theoretic pixel size based on their original bounds and their current localScale?

    It seems like I'd need to make some formula for that... ?
     
  7. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Unless the sprites are exactly the same size, it's going to involve a little math. It shouldn't be very hard, though, since you can always relate sprites to one another in terms of relative sizes. For example, a sprite that is 100x100 is exactly 0.5 times the size of another sprite that is 200x200. (Assuming the same pixelsPerUnit value, of course. If those are not the same, you need to convert for that as well.)
     
  8. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,129
    Yeah you were right, I only needed a simple converter for my script to make it work.

    I added this from another static class, for anyone struggling with the same issue :).

    Code (CSharp):
    1. public static Vector3 CurrentObjectSize(Vector3 objBoundsSize, Vector3 objLocalScale)
    2.     {
    3.         Vector3 newObj;
    4.  
    5.         newObj.x = objBoundsSize.x * objLocalScale.x;
    6.         newObj.y = objBoundsSize.y * objLocalScale.y;
    7.         newObj.z = objBoundsSize.z * objLocalScale.z;
    8.  
    9.         return newObj;
    10.     }
    Code (CSharp):
    1.     public bool SetInitialSize()
    2.     {
    3.         SpriteRenderer sr = GetComponent<SpriteRenderer>();
    4.        
    5.         if (sr)
    6.         {
    7.             Camera cam;
    8.             if (cam = GameObject.Find("MapViewCamera").GetComponent<Camera>())
    9.             {
    10.                 SpriteRenderer m_sr;
    11.                 if(m_sr = GameObject.Find("Map").GetComponent<SpriteRenderer>())
    12.                 {
    13.                     Bounds mapBounds = m_sr.sprite.bounds;
    14.  
    15.                     mapBounds.size = Helper.CurrentObjectSize(m_sr.sprite.bounds.size, m_sr.transform.localScale);
    16.                     float sizeY = sr.sprite.bounds.size.y;
    17.  
    18.                     float gridSize = (mapBounds.size.y / 6) / (protMeasurePercentSize / 100);
    19.                     Vector3 newScale = new Vector3(gridSize / sizeY, gridSize / sizeY, gridSize / sizeY);
    20.                     transform.localScale = newScale;
    21.  
    22.                     // Set correct z position according to parent (should be the map)
    23.                     Vector3 pos = transform.position;
    24.                     pos.z = cam.transform.position.z + 1;
    25.                     transform.position = pos;
    26.                 }
    27.                 else
    28.                 {
    29.                     Debug.Log("ProtractorHandler::SetInitialSize - Unable to find SpriteRenderer component in Map GameObject!");
    30.                     return false;
    31.                 }
    32.             }
    33.             else
    34.             {
    35.                 Debug.Log("ProtractorHandler::SetInitialSize() - Camera not found as parent to Map Object!");
    36.                 return false;
    37.             }
    38.         }
    39.         else
    40.         {
    41.             Debug.Log("ProtractorHandler::SetInitialSize() - SpriteRenderer Component not found!");
    42.             return false;
    43.         }
    44.         return true;
    45.     }
    46. }
     
    DMorock likes this.
  9. blizzy

    blizzy

    Joined:
    Apr 27, 2014
    Posts:
    775
    Now just throw this away and use Vector3.Scale() :D
     
    DMorock and Nigey like this.