Resize Model Scale X,Y,Z Tween Emitters, Bones, Mesh, Motors, HipHeight, Lights,Tool.Grip, Textures, Fire, Smoke,Weld [Open Source]

This is a useful function that Resizes everything so their is no visual bugs in bones and rigs.
This is different than ScaleTo as it Scales Tool.Grip and Attachments. All the code is written by me.
You could use this to scale anything without issue. I also added a ScaleFactor value so that you can change the ScaleFactor in real time.
The resizetween function is really cool unfortunately I’ve encountered the same issues as the ScaleTo API with this function. It currently scales the position as well


function multnumseq(sequence,Scale)
	local numberKeypoints2 = {}
	for i = 1, #sequence.Keypoints do
		local currKeypoint = sequence.Keypoints[i]
		table.insert(numberKeypoints2, NumberSequenceKeypoint.new(currKeypoint.Time,currKeypoint.Value*Scale))	
	end
	return NumberSequence.new(numberKeypoints2)
end
function Resize(Model,Scale)
	local PrevFrame=nil
	if Model:FindFirstChild("HumanoidRootPart") or Model:IsA("Model") then
		if Model.PrimaryPart then
			PrevFrame=Model.PrimaryPart.CFrame
		end	
	end
	local vars=Model:GetDescendants()
	if Model:IsA("Tool") then
		local Vcf = Model.Grip
		local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
		Model.Grip = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
	end
	if Model:IsA("BasePart") then
		Model.Size = Model.Size * Scale
	end
	for k,v in next,vars do
		if v:IsA("BasePart") or v:IsA("Bone") or v:IsA("Attachment") then
			
			local Vcf = v.CFrame
			local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
			if v:IsA("BasePart") then
				v.Anchored=true
				--local orig=v.Size
				v.Size = v.Size * Scale
				--local dif=(v.Size-orig)
				v.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
			else 
				v.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
			end
		elseif v:IsA("SpecialMesh") or v:IsA("Mesh") then
			v.Scale = v.Scale * Scale
			v.Offset= v.Offset * Scale
		elseif v:IsA("Humanoid") then
			--v.CameraOffset=v.CameraOffset*Scale
			v.HipHeight=v.HipHeight*Scale
			--v.WalkSpeed=v.WalkSpeed*Scale
		elseif v:IsA("Motor6D") or v:IsA("Weld") then
			if v.C0 and v.C1 and v.Name~="AccessoryWeld" then
			local Vcf = v.C0
			local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
			v.C0 = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
			local Vcf = v.C1
			local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
				v.C1 = CFrame.new(Vcf.p * Scale)* CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
			end	
		elseif v:IsA("ParticleEmitter") then
				v.Size=multnumseq(v.Size,Scale)
		elseif v:IsA("Beam") then
			v.Width0=v.Width0*Scale
			v.Width1=v.Width1*Scale
			v.Segments=v.Segments*Scale
			v.CurveSize0=v.CurveSize0*Scale
			v.CurveSize1=v.CurveSize1*Scale
			v.TextureLength=v.TextureLength*Scale
		elseif v:isA("Texture") then
			v.OffsetStudsU=v.OffsetStudsU*Scale
			v.OffsetStudsV=v.OffsetStudsV*Scale
			v.StudsPerTileV=v.StudsPerTileV*Scale
			v.StudsPerTileU=v.StudsPerTileU*Scale
		--elseif v:IsA("NumberValue") and v.Parent.ClassName=="Humanoid" then
			--	v.Value=v.Value*Scale
		elseif v:IsA("Smoke") or v:IsA("Fire") then
			v.Size=v.Size*Scale
		elseif v:IsA("PointLight") or v:IsA("SpotLight") or v:IsA("SurfaceLight") then
			v.Range=v.Range*Scale	
		end
	end
	for k,v in next,vars do
		if v:IsA("BasePart") then
			v.AssemblyLinearVelocity=Vector3.new(0,0,0)
			v.Anchored=false
		end	
	end
	if PrevFrame~=nil then
		Model:SetPrimaryPartCFrame(PrevFrame)
	end
	return Model
end

function ResizeNPC(Subject,Scale)
if Subject:FindFirstChild("ScaleFactor")==nil then	
		local check=Instance.new("NumberValue")
		check.Name="ScaleFactor"
		check.Parent=Subject
		dfg.Resize(Subject,Scale)
	end
	local prevv=Subject.ScaleFactor.Value
	Subject.ScaleFactor:GetPropertyChangedSignal("Value"):Connect(function()
		local basev=1/prevv*Subject.ScaleFactor.Value
		dfg.Resize(Subject,basev)
		prevv=Subject.ScaleFactor.Value
	end)
	return Subject.ScaleFactor
end
function tweenemitter(v,Scale,duration)
	spawn(function()
		local base=v.Size
		local frame=(1/30)
		local timer=0
		local numofframes=duration/frame
		local dif=Scale-1
		repeat
			v.Size=multnumseq(base,1+(dif*(timer/numofframes)))
			task.wait(frame)
			timer=timer+frame
		until timer>=duration
	end)
end	

function ResizeTween(Model,Scale,duration)
	local tweenInfo=TweenInfo.new(duration)
	local PrevFrame=nil
	if Model:FindFirstChild("HumanoidRootPart") or Model:IsA("Model") then
		if Model.PrimaryPart then
			PrevFrame=Model.PrimaryPart.CFrame
		end	
	end
	local vars=Model:GetDescendants()

	if Model:IsA("Tool") then
		local Vcf = Model.Grip
		local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
		local goalc={}
		goalc.Grip = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
		local tween=TweenService:Create(Model,tweenInfo,goalc)
		tween:Play()
	end
	if Model:IsA("BasePart") then
		local goalc={}
		goal.Size = Model.Size * Scale
		local tween=TweenService:Create(Model,tweenInfo,goalc)
		tween:Play()
	end
	for k,v in next,vars do
		if v:IsA("BasePart") or v:IsA("Bone") or v:IsA("Attachment") then

			local Vcf = v.CFrame
			local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
			if v:IsA("BasePart") then
				local goalc={}
				
				goalc.Size = v.Size * Scale
				goalc.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				goalc.AssemblyLinearVelocity=Vector3.new(0,0,0)
				local tween=TweenService:Create(v,tweenInfo,goalc)
				tween:Play()
			else 
				local goalc={}
				goalc.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local tween=TweenService:Create(v,tweenInfo,goalc)
				tween:Play()	
			end

		elseif v:IsA("SpecialMesh") or v:IsA("Mesh") then
			local goalc={}
			goalc.Scale = v.Scale * Scale
			goalc.Offset= v.Offset * Scale
			
			local tween=TweenService:Create(v,tweenInfo,goalc)
			tween:Play()
		elseif v:IsA("Humanoid") then
			--v.CameraOffset=v.CameraOffset*Scale
			local goalc={}
			goalc.HipHeight=v.HipHeight*Scale

			local tween=TweenService:Create(v,tweenInfo,goalc)
			tween:Play()
			--v.WalkSpeed=v.WalkSpeed*Scale
		elseif v:IsA("Motor6D") or v:IsA("Weld") then
			if v.C0 and v.C1  then
				local Vcf = v.C0
				local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
				local goald={}
				goald.C0 = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local Vcf2 = v.C1
				local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf2:components()
				goald.C1 = CFrame.new(Vcf2.p * Scale)* CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local tween2=TweenService:Create(v,tweenInfo,goald)
				tween2:Play()
			end	
		elseif v:IsA("ParticleEmitter") then
			
			tweenemitter(v,Scale,duration)
		elseif v:IsA("Beam") then
			local goal={}	
			goal.Width0=v.Width0*Scale
			goal.Width1=v.Width1*Scale
			goal.Segments=v.Segments*Scale
			goal.CurveSize0=v.CurveSize0*Scale
			goal.CurveSize1=v.CurveSize1*Scale
			goal.TextureLength=v.TextureLength*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		elseif v:isA("Texture") then
			local goal={}
			goal.OffsetStudsU=v.OffsetStudsU*Scale
			goal.OffsetStudsV=v.OffsetStudsV*Scale
			goal.StudsPerTileV=v.StudsPerTileV*Scale
			goal.StudsPerTileU=v.StudsPerTileU*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
			--elseif v:IsA("NumberValue") and v.Parent.ClassName=="Humanoid" then
			--	v.Value=v.Value*Scale
		elseif v:IsA("Smoke") or v:IsA("Fire") then
			local goal={}
			goal.Size=v.Size*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		elseif v:IsA("PointLight") or v:IsA("SpotLight") or v:IsA("SurfaceLight") then
			local goal={}
			goal.Range=v.Range*Scale	
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		end
	end
	return Model
end

This works like ScaleTo Api I guess except this is open sourced and you can use it however you like.

You could tween these CFrame and Size properties to simulate growing using any rig

I commented out the line for the CameraOffset but that may be useful to consider for your use case.

Setting the linear velocity to 0 is so the part doesn’t get yeeted out of existance which happens sometimes.

Here is a link to the model!!

ResizeDemo with Dog and Randomly Generated NPC - Roblox ResizeDemo with Dog and Randomly Generated NPC - Roblox

10 Likes

Sooo I wanted to share something useful I learning while working with modules.
if you have any global variables that are say :GetChildren() It’s best to only do this once for a static directory. In addition you can specify a global variable to return the array only when it is defined like in this example

local wingarray= function() if wings==nil then wings=wingdir:GetChildren() end return wings end
function dfg.Wingsaccessory(Subject,Specific)
	local war=wingarray()
	local wr=mathrandom(1,#war)
	local wingsaccess=nil
	for i,v in pairs(war) do
		if i==wr or (v.Name==Specific and Specific~=nil) then
			for t,c in pairs(v:GetChildren()) do
				if c:IsA("Accessory") then
					wingsaccess=c:Clone()
					break
				end
			end
		end
		if wingsaccess then break end
	end
	Subject.Humanoid:AddAccessory(wingsaccess)
	return wingsaccess
end
1 Like

I’m confused couldn’t you just use the new model Scale API?

Continuing the discussion from Introducing an Engine-Level Model Scale API [Beta]:

1 Like

Because it doesn’t work as well as this function. I use to use it but it changes the original position. This function is exactly the same except better. just no hastle works for everything in real time and you can modify it to tween the Scale of the model in real time to simulate growing.

But speaking of multiplying number sequences such as particle emitters in real time I have also made a function for that but forgot to include it in this post!
This will multiply any number sequence by the scale.

function multnumseq(sequence,Scale)
	local numberKeypoints2 = {}
	for i = 1, #sequence.Keypoints do
		local currKeypoint = sequence.Keypoints[i]
		table.insert(numberKeypoints2, NumberSequenceKeypoint.new(currKeypoint.Time,currKeypoint.Value*2))	
	end
	return NumberSequence.new(numberKeypoints2)
end
if example:IsA("ParticleEmitter") then multnumseq(example.Size,2) end

I added another function is a optional pipeline for the Resize function to have a connecting to the ScaleFactor value. This is useful for calculating new values based off the new scale. This also handles the math to base the changed scale from a base value of 1

local basev=1/prevv*Subject.ScaleFactor.Value

I have done the ResizeTween function because I needed it for something, so I’m going to share the function here on this resource!

function tweenemitter(v,Scale,duration)
	spawn(function()
		local base=v.Size
		local frame=(1/30)
		local timer=0
		local numofframes=duration/frame
		local dif=Scale-1
		repeat
			v.Size=multnumseq(base,1+(dif*(timer/numofframes)))
			task.wait(frame)
			timer=timer+frame
		until timer>=duration
	end)
end	

function ResizeTween(Model,Scale,duration)
	local tweenInfo=TweenInfo.new(duration)
	local PrevFrame=nil
	if Model:FindFirstChild("HumanoidRootPart") or Model:IsA("Model") then
		if Model.PrimaryPart then
			PrevFrame=Model.PrimaryPart.CFrame
		end	
	end
	local vars=Model:GetDescendants()

	if Model:IsA("Tool") then
		local Vcf = Model.Grip
		local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
		local goalc={}
		goalc.Grip = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
		local tween=TweenService:Create(Model,tweenInfo,goalc)
		tween:Play()
	end
	if Model:IsA("BasePart") then
		local goalc={}
		goal.Size = Model.Size * Scale
		local tween=TweenService:Create(Model,tweenInfo,goalc)
		tween:Play()
	end
	for k,v in next,vars do
		if v:IsA("BasePart") or v:IsA("Bone") or v:IsA("Attachment") then

			local Vcf = v.CFrame
			local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
			if v:IsA("BasePart") then
				local goalc={}
				
				goalc.Size = v.Size * Scale
				goalc.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				goalc.AssemblyLinearVelocity=Vector3.new(0,0,0)
				local tween=TweenService:Create(v,tweenInfo,goalc)
				tween:Play()
			else 
				local goalc={}
				goalc.CFrame = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local tween=TweenService:Create(v,tweenInfo,goalc)
				tween:Play()	
			end

		elseif v:IsA("SpecialMesh") or v:IsA("Mesh") then
			local goalc={}
			goalc.Scale = v.Scale * Scale
			goalc.Offset= v.Offset * Scale
			
			local tween=TweenService:Create(v,tweenInfo,goalc)
			tween:Play()
		elseif v:IsA("Humanoid") then
			--v.CameraOffset=v.CameraOffset*Scale
			local goalc={}
			goalc.HipHeight=v.HipHeight*Scale

			local tween=TweenService:Create(v,tweenInfo,goalc)
			tween:Play()
			--v.WalkSpeed=v.WalkSpeed*Scale
		elseif v:IsA("Motor6D") or v:IsA("Weld") then
			if v.C0 and v.C1  then
				local Vcf = v.C0
				local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
				local goald={}
				goald.C0 = CFrame.new(Vcf.p * Scale) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local Vcf2 = v.C1
				local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf2:components()
				goald.C1 = CFrame.new(Vcf2.p * Scale)* CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
				local tween2=TweenService:Create(v,tweenInfo,goald)
				tween2:Play()
			end	
		elseif v:IsA("ParticleEmitter") then
			
			tweenemitter(v,Scale,duration)
		elseif v:IsA("Beam") then
			local goal={}	
			goal.Width0=v.Width0*Scale
			goal.Width1=v.Width1*Scale
			goal.Segments=v.Segments*Scale
			goal.CurveSize0=v.CurveSize0*Scale
			goal.CurveSize1=v.CurveSize1*Scale
			goal.TextureLength=v.TextureLength*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		elseif v:isA("Texture") then
			local goal={}
			goal.OffsetStudsU=v.OffsetStudsU*Scale
			goal.OffsetStudsV=v.OffsetStudsV*Scale
			goal.StudsPerTileV=v.StudsPerTileV*Scale
			goal.StudsPerTileU=v.StudsPerTileU*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
			--elseif v:IsA("NumberValue") and v.Parent.ClassName=="Humanoid" then
			--	v.Value=v.Value*Scale
		elseif v:IsA("Smoke") or v:IsA("Fire") then
			local goal={}
			goal.Size=v.Size*Scale
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		elseif v:IsA("PointLight") or v:IsA("SpotLight") or v:IsA("SurfaceLight") then
			local goal={}
			goal.Range=v.Range*Scale	
			local tween2=TweenService:Create(v,tweenInfo,goal)
			tween2:Play()
		end
	end
	return Model
end
1 Like

I created a new function with the old function that now Scales anything on X,Y,Z! You input a Scale vector. Scale=Vector3.new(.5,1,.5)
This will allow you to resize you anything with x.y.z. :slight_smile: The functionality for particle emitters and beams is not complete. But this algorithm should work very well and be performant on anything.

function dfg.ResizeVect(Model,Scale)
    local PrevFrame=nil
    if Model:FindFirstChild("HumanoidRootPart") or Model:IsA("Model") then
        if Model.PrimaryPart then
            PrevFrame=Model.PrimaryPart.CFrame
        end	
    end
    local vars=Model:GetDescendants()

    if Model:IsA("Tool") then
        local Vcf = Model.Grip
        local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
        Model.Grip = CFrame.new(Vector3.new(Vcf.p.X*Scale.X,Vcf.p.Y*Scale.Y,Vcf.p.Z*Scale.Z)) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
    end
    if Model:IsA("BasePart") then
        Model.Size = Vector3.new(Model.Size.X*Scale.X,Model.Size.Y*Scale.Y,Model.Size.Z*Scale.Z)
    end
    for k,v in next,vars do
        if v:IsA("BasePart") or v:IsA("Bone") or v:IsA("Attachment") then

            local Vcf = v.CFrame
            local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
            if v:IsA("BasePart") then
                v.Size = v.Size * Scale
                v.CFrame = CFrame.new(Vector3.new(Vcf.p.X*Scale.X,Vcf.p.Y*Scale.Y,Vcf.p.Z*Scale.Z)) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
                v.AssemblyLinearVelocity=Vector3.new(0,0,0)
            else 
                v.CFrame = CFrame.new(Vector3.new(Vcf.p.X*Scale.X,Vcf.p.Y*Scale.Y,Vcf.p.Z*Scale.Z)) * CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
            end

        elseif v:IsA("SpecialMesh") or v:IsA("Mesh") then
            v.Scale = Vector3.new(v.Scale.X*Scale.X,v.Scale.Y*Scale.Y,v.Scale.Z*Scale.Z)
            v.Offset= v.Offset * Scale
        elseif v:IsA("Humanoid") then
            --v.CameraOffset=v.CameraOffset*Scale
            v.HipHeight=v.HipHeight*Scale.Y
            --v.WalkSpeed=v.WalkSpeed*Scale
        elseif v:IsA("Motor6D") or v:IsA("Weld") then
            if v.C0 and v.C1 and v.Name~="AccessoryWeld" then
                local Vcf = v.C0
                local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
                v.C0 =CFrame.new(Vector3.new(Vcf.p.X*Scale.X,Vcf.p.Y*Scale.Y,Vcf.p.Z*Scale.Z))* CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
                local Vcf = v.C1
                local _,_,_,C0,C1,C2,c3,c4,c5,c6,c7,c8 = Vcf:components()
                v.C1 = CFrame.new(Vector3.new(Vcf.p.X*Scale.X,Vcf.p.Y*Scale.Y,Vcf.p.Z*Scale.Z))* CFrame.new(0,0,0,C0,C1,C2,c3,c4,c5,c6,c7,c8)
            end	
        elseif v:IsA("ParticleEmitter") then
            v.Size=multnumseq(v.Size,Scale.Y)
        elseif v:IsA("Beam") then
            v.Width0=v.Width0*Scale
            v.Width1=v.Width1*Scale
            v.Segments=v.Segments*Scale
            v.CurveSize0=v.CurveSize0*Scale
            v.CurveSize1=v.CurveSize1*Scale
            v.TextureLength=v.TextureLength*Scale
        elseif v:isA("Texture") then
            v.OffsetStudsU=v.OffsetStudsU*Scale.Z
            v.OffsetStudsV=v.OffsetStudsV*Scale.X
            v.StudsPerTileV=v.StudsPerTileV*Scale.X
            v.StudsPerTileU=v.StudsPerTileU*Scale.Z
            --elseif v:IsA("NumberValue") and v.Parent.ClassName=="Humanoid" then
            --	v.Value=v.Value*Scale
        elseif v:IsA("Smoke") or v:IsA("Fire") then
            v.Size=v.Size*Scale.Y
        elseif v:IsA("PointLight") or v:IsA("SpotLight") or v:IsA("SurfaceLight") then
            v.Range=v.Range*Scale.Y	
        end
    end
    for k,v in next,vars do
        if v:IsA("BasePart") then
            v.AssemblyLinearVelocity=Vector3.new(0,0,0)
        end	
    end
    if PrevFrame~=nil then
        Model:SetPrimaryPartCFrame(PrevFrame)
    end
    for k,v in next,vars do
        if v:IsA("BasePart") then
            v.AssemblyLinearVelocity=Vector3.new(0,0,0)
        end	
    end
    return Model
end

Changing the XYZ scales of your models too much can cause some visual bugs because if you have an angle and it extends too far it will reach a point of elvation beyond its original geometry.when calculating from the center point. using XYZ. I assume that’s why this isn’t a common feature.

I’m using this function to scale a pool of lava model in place of a ocean.

1 Like