Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. On February 28th the Feedback website will shut down and be redirected to the Unity forums. See the full post for more information.
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Unity 2018.3 is now released.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Scale Around Point - similar to Rotate Around

Discussion in 'Scripting' started by De-Panther, Mar 7, 2014.

  1. De-Panther


    Dec 27, 2009

    So I had a problem, and I solved it, and because I saw lots of questions about it, but without a solution, here is how I solved it:

    Unity has Transform.RotateAround
    Rotates the transform about axis passing through point in world coordinates by angle degrees.
    But it doesn't have ScaleAround

    In order to scale around a point in the world, you'll need this formula:

    GameObject Local Position

    New pivot position(relative to object's parent)

    Old scale Vector3(2,2,2)
    New scale Vector3(5,5,5)

    Find Object position relative to pivot(It's similar to put the game object as a child of a pivot object, and then get it's localPosition):

    Relative Scale(we need to check how much did the object scaled):
    RS=New Scale / Old Scale
    2.5=5 / 2

    Final Position:

    Vector3.Scale(Vector3(2.5,2.5,2.5), Vector3(5,3,1)) + Vector3(4,5,6)
    Vector3(12.5,7.5,2.5) + Vector3(4,5,6)=Vector3(16.5,12.5,8.5)

    (Relative Scale * Object Position Relative to Pivot) + Pivot Position

    Good luck :)
    Afroman and amonitzer like this.
  2. MaRTiDoRe


    Jul 4, 2011
    I don't understand where do you get:

    Old scale Vector3(2,2,2)
    New scale Vector3(5,5,5)

    Where do you get those values from and why do you have two scale values?

    The rest is crystal clear.
    Last edited: Jul 3, 2014
  3. gregroberts


    Nov 21, 2014
    I've translated De-Panther's pseudocode into working code. Enjoy:

    var targetGO : GameObject;
    var pivotGO : Transform;

    function Start () {
    var A : Vector3 = targetGO.transform.position;
    var B : Vector3 = pivotGO.transform.position;

    var RS : float = 0.2; // relataive scale factor
    var startScale = targetGO.transform.localScale;
    var endScale = targetGO.transform.localScale *RS;

    var C : Vector3 = A-B; // diff from object pivot to desired pivot/origin

    // calc final position post-scale
    var FP : Vector3 = (C*RS)+B;

    // finally, actually perform the scale/translation
    targetGO.transform.localScale = endScale;
    targetGO.transform.position = FP;
    tobetobe likes this.
  4. keenanwoodall


    May 30, 2014
    Thanks. Btw, protip, put code tags arounf your code so that it's formatted correctly and easy to read. Here's the official post on coding tags:
  5. trul


    Nov 15, 2013
    I've created static method to scale target around the pivot:

    Code (CSharp):
    1. public static void ScaleAround(Transform target, Transform pivot, Vector3 scale) {
    2.         Transform pivotParent = pivot.parent;
    3.         Vector3 pivotPos = pivot.position;
    4.         pivot.parent = target;      
    5.         target.localScale = scale;
    6.         target.position += pivotPos - pivot.position;
    7.         pivot.parent = pivotParent;
    8.     }
    antonsem likes this.
  6. KyleBlumreisinger


    Mar 6, 2017
    So trul's code with parenting wasn't quite what I personally was looking for and I couldn't get it to work, but gregroberts's example code also didn't work for me out of the box, so I eventually made this:
    I've translated gregroberts's mostly-working (I'm assuming Java) code translation of De-Panther's pseudocode into fully functioning and tested C#:

    Code (CSharp):
    1. public void ScaleAround(GameObject target, Vector3 pivot, Vector3 newScale)
    2. {
    3.     Vector3 A = target.transform.localPosition;
    4.     Vector3 B = pivot;
    6.     Vector3 C = A - B; // diff from object pivot to desired pivot/origin
    8.     float RS = newScale.x / target.transform.localScale.x; // relative scale factor
    10.     // calc final position post-scale
    11.     Vector3 FP = B + C * RS;
    13.     // finally, actually perform the scale/translation
    14.     target.transform.localScale = newScale;
    15.     target.transform.localPosition = FP;
    16. }
    Code (CSharp):
    1. ScaleAround(targetGameObject, scaleCenterPivot, desiredFinalScale);
    Alternatively, if you would rather use a Transform / GameObject's position as the pivot, you can do:
    Code (CSharp):
    1. ScaleAround(targetGameObject, pivotGameObject.transform.position, desiredFinalScale);
    Just remember: It is extremely important that the pivot point be in the target's PARENT'S space. So if your target object has no parent, your pivot is in world space. If your target is a child of SomeGameObject, you pivot point must be in SomeGameObject's space. This can be accomplished with
    Code (CSharp):
    1. targetGameObject.transform.parent.InverseTransformPoint(pivot);
    if your pivot is in world space.

    Hope this helps someone who needed it as much as I did, thanks to everyone who contributed here, and happy coding!
    stenfeio and De-Panther like this.
  7. De-Panther


    Dec 27, 2009
    @KyleBlumreisinger , I'm happy that it helped someone after so many years :D

    I think that the "target" type on ScaleAround should be Transform.

    And maybe we can add a bool that ask if pivot is in parent space or world space.

    Also, now that I think about it, it works only if the scaling was unified.
    So iguess it shold be:
    Vector3 RS= new Vector3(newScale.x / target.transform.localScale.x, newScale.y / target.transform.localScale.y, newScale.z / target.transform.localScale.z);
    Vector3 FP = B + C.Scale(RS);

    But I'll have to test it.
  8. stenfeio


    Jan 18, 2015
    This was excellent. It's easy to forget that final positions need to also be handled as we've come so much to rely on parenting...
    Last edited: Sep 3, 2018