How to scale a parent without scaling children?

I am trying to scale up an object without scaling it's children. The original scale vectors for both parent and children are (1, 1, 1). The parent is named and tagged differently than the children, but all children are named and tagged the same.

This code works to scale everything (including children) up:

var largeSize : float;  // exposed in inspector

function ScaleUp ()
{
    var velocity = Vector3.zero;
    var targetScale = Vector3(largeSize, largeSize, largeSize);

    while (transform.localScale != targetScale)
    { 
        transform.localScale = Vector3.SmoothDamp(transform.localScale, targetScale, velocity, 0.5);
        yield;
    }
}

But I don't want everything scaled up, so I tried to differentiate the children and offset the scaling by scaling them back down. Since `for (var child : Transform in transform)` does include the parent transform, I tried to differentiate the children by name or by tag, as follows:

function ScaleUp ()
{
    var velocity = Vector3.zero;
    var targetScale = Vector3(largeSize, largeSize, largeSize);
    var childScale = Vector3(largeSize/2, largeSize/2, largeSize/2);

    while (transform.localScale != targetScale)
    { 
        transform.localScale = Vector3.SmoothDamp(transform.localScale, targetScale, velocity, 0.5);
        for (var child : Transform in transform)
        {
            if (child.gameObject.tag == "ChildSpecificTag")
                child.localScale = Vector3.SmoothDamp(child.localScale, childScale, velocity, 0.5);
        }
        yield;
    }
}

This... apparently works, but also catches the parent transform in an if statement it shouldn't be caught in? The result of this code is that no scaling occurs, everything stays the same as it was. But the parent is definitely tagged differently than the children. And also named differently, and the same thing happens (no scaling - or, everything is scaled up and immediately scaled back down) if the if statement is: `if (child.gameObject.name != this.gameObject.name)`

How can I apply scaling to the parent without scaling the children, or, how can I effectively differentiate the children to offset the scaling?

ETA: I have not tried `GetComponent(s)InChildren` because that apparently also returns the same component in the parent, and if the parent can evade an if statement designed to weed it out when returned through `Transform in transform`, will it be any different using `GetComponent(s)InChildren`?

Hi,

I am sure there is a way to get your script working, but I would discourage you from doing it. I would strongly suggest adding a layer of indirection in your hierarchy instead.

Instead of linking your models together and being stuck when willing to scale one independantly, create an empty gameObject name "parent" like so:

 -- "parent"   
    -- "model to scale"   
    -- "another model"
       -- "yet another model"

Everything that you did normally with "model to scale" should now be done via "parent", and for scaling, you simply scale "model to scale" without interfering with the rest of the hierarchy.

I always do that when I need that kind of feature implemented, it's very common for technical assemblies and complex rigs. In assemblies, I even go further and have a layer of indirection of each and every feature rich model, so that I can exchange models, load them on demand, or complex Level of details scripting, basically mess with them without affecting in anyway the actual hierarchy itself.

Hope this helps,

Jean

You can do like this. it’s work perfectly for me.

  Vector3 scaleTmp = object.transform.localScale;
    scaleTmp.x /= parent.localScale.x;
    scaleTmp.y /= parent.localScale.y;
    scaleTmp.z /= parent.localScale.z;
    object.transform.parent = parent;
    object.transform.localScale = scaleTmp;

Jean's answer is probably the best way to do it, but I have something else you can try; You can detach children, scale and re-attach them after. It might be costly with a lot of children though. Something like that :

public class ScaleAndParenthood : MonoBehaviour 
{
    public float s = 1.0f;
    private Transform[] children = null;

    // We build an array with all children, so we can re attach them later
    void Start () 
    {
        children = new Transform[ transform.childCount ];

        int i = 0;  
        foreach( Transform T in transform )
            children[i++] = T;
    }

    // Update is called once per frame
    void Update () 
    {
        if( s != transform.localScale.x )
        {
            transform.DetachChildren();                     // Detach
            transform.localScale = new Vector3( s, s, s );  // Scale        
            foreach( Transform T in children )              // Re-Attach
                T.parent = transform;
        }
    }
}

Hi there! I figure out this solution :smiley:

Just set this script to your child :wink: (It works also in Edit Mode so that you can set up the scale you need.

At the FixeScale set up the size of your child you need and at the parent set your parent model.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class FixedScale : MonoBehaviour {

 public float FixeScale =1 ;
	public GameObject parent;
	
	// Update is called once per frame
	void Update () {
		transform.localScale = new Vector3 (FixeScale/parent.transform.localScale.x,FixeScale/parent.transform.localScale.y,FixeScale/parent.transform.localScale.z);

			}
		}

if (Size != Old_Size && SphereColider != null)
{
SphereColider.radius *= Old_Size / Size;
}
transform.localScale = new Vector3(Size, Size, Size);
Old_Size = Size;

important part is “*= Old_Size / Size;”
multiply that by child scale and it will keep consistent size