How to make part scale from only 1 face

Untitled_video_-_Made_with_Clipchamp
I want to shorten parts from only one face. Here is my current implementation:

local Players = game:GetService("Players")
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")
local tweenserv = game:GetService("TweenService")
local blade = script.Parent.Blade 
local tipTopAttachment = blade:WaitForChild("TIPTOP")  
local bottomAttachment = blade:WaitForChild("BOTTOM")
local deltsize = 9

local beam = Instance.new("Beam")
beam.Name = "LaserBeam"
beam.Color = ColorSequence.new(Color3.fromRGB(255, 0, 0))  
beam.TextureMode = Enum.TextureMode.Stretch
beam.Parent = blade 

beam.Attachment0 = bottomAttachment  
beam.Attachment1 = tipTopAttachment  

-- update
local TweenInfo = TweenInfo.new(0.01, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut) --smooth 

RunService.Heartbeat:Connect(function()
	-- Calculate the direction from BOTTOM 
	local direction = (tipTopAttachment.WorldPosition - bottomAttachment.WorldPosition).Unit

	--  raycast from the BOTTOM attachment in the Z-axis direction (10 studs max)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.IgnoreWater = true

	-- ignore parts
	local playerParts = {}
	for _, player in ipairs(Players:GetPlayers()) do
		local character = player.Character or player.CharacterAdded:Wait()
		for _, descendant in ipairs(character:GetDescendants()) do
			if descendant:IsA("BasePart") then
				table.insert(playerParts, descendant)
			end
		end
	end

	local ignoreParts = CollectionService:GetTagged("IGNORE")
	local finalIgnoreParts = {}
	for _, part in pairs(playerParts) do
		table.insert(finalIgnoreParts, part)
	end
	for _, part in pairs(ignoreParts) do
		table.insert(finalIgnoreParts, part)
	end
	raycastParams.FilterDescendantsInstances = finalIgnoreParts


	local raycastResult = workspace:Raycast(bottomAttachment.WorldPosition, direction * 10, raycastParams)

	
	local newBladeSizeZ
	if raycastResult then
		--getdistance from hitpoint to bottomattachment
		local distance = (raycastResult.Position - bottomAttachment.WorldPosition).Magnitude
		newBladeSizeZ = math.min(distance, 10) --  length to a max of 10 studs
	else
		--defaultcase
		newBladeSizeZ = 10
	end



	
	local targetProperties = {
		Size = Vector3.new(blade.Size.X, blade.Size.Y, newBladeSizeZ),
	}

	local tween = tweenserv:Create(blade, TweenInfo, targetProperties)
	tween:Play()
end)

Above is a GIF on the current behavior.
How can I adjust the CFRAME to show as scaling from the top only?

9 Likes

When you resize a part it changes its position, so you have to add or remove the amount you are changing (Divided by 2 since it resize from both direction).

You can just use this method:

local part = script.Parent
part:Resize(Enum.NormalId.Left,2)

Specify the direction using Enum.NormalId.

4 Likes

So like setting the cframe? I’m a little confused.

1 Like

You want to short the blade size right ?

In the moment where the blade touches the roof, you run throw all the blade part and use part:Resize().

This function resize the part just like you do in the editor.

4 Likes

Got it, I thought changing the size from both and moving CFRAME was the only way of doing it.
I’ll give it a shot, thanks!

3 Likes

tested around with a regular part in a baseplate, I got
16:14:40.109 Resize is not a valid member of ServerScriptService "ServerScriptService" - Server - Script:2

Sorry, I am not too sure how this works. any idea how to fix this?

2 Likes

you have to define the part as the actual part you want to resize. you set it to script.Parent which is just ServerScriptService.

2 Likes

Got it, how does part:Resize() work?

1 Like

You need to reference the part to use the Resize function

part:Resize() have 2 params you can pass

the first is the direction you want the part to increase the size, and the second is the increment value.

For example if i want to increase the left face size of a part by 5 i do this:

part:Resize(Enum.NormalId.Left,5)
2 Likes

I think I’ve got the basic resize working on a test place, thanks guys!

2 Likes

The big problem with resize is that you’re going to have troubles incrementing with grids & with small increments. In that case consider incrementing the Size property, and shifting the position as well

2 Likes

Yes, that is what I originally thought to do, But I couldn’t figure out the math of getting the new cframe, and it often just broke.

Well, increasing on a specific face is basically changing the size on one local axis.

Changing a part’s size by a length of N along a specific local axis named u, makes it so that the size changes by u/2 & -u/2. You basically expand the part at its center, in both directions.

So you increase (N•u)/2 in the proper direction, and (N•-u)/2 in the other. Since the length of u, noted ||u||, equals 1, you expand N/2 on the face you want, N/2 on the other. To prevent this, you need to shift the part’s position by N/2 in the direction of u.
To transcribe this explanation in a 2D plane (which is easier to understand & easily translatable for 3D spaces), you basically have this:

You can get u from a NormalId or face. Because you can do that, it means that you would do:

Part.Size = Part.Size + K --K is only affecting a single axis, so either K = N * LocalAxisToIncrement

--Here, u is a local vector that is stored in the CFrame of your part. Depending on the face/NormalId you have, you can fetch it properly.
-- To be more correct, you need to either use +u or -u, depending the direction you want to go to.
local u = ±Part.CFrame.[(Right|Up|Look)Vector] --This vector is proper to localspace, but has its own coordinates expressed in world space. This means that localaxis X = (1, 0, 0) will already be transcribed in worldspace if you do Part.CFrame.RightVector

Part.Position += u * (N/2) --You add u * (N/2) to the position, so you shift by N/2, which is the length to compensate

You could use methods proper to CFrames to make it easier, I think it’s better to see what’s going on personally, instead of using methods that aren’t really explicit enough (at first)

SIdenote: My drawing doesn’t respect the scale, it’s just to understand properly what’s going on, and what to do

2 Likes

If I were to subtract length, would I Multiply N by (-1)? or Divide by N / 2?

I’m a bit confused with your question. -N and N/2 are two different things

1 Like

From what I gather, you shrink the part with size, and move the cframe based on half of the change?
I am wondering how I can apply that to my logic, as the n is constantly changing, and I fear it will lag as well.

(N) or (-N) is the amount that you are changing the size?
and N/2 is for getting the New CFRAME?

To simplify my question, If i was to shorten the part, I would

  • Set N to a negative value

But -N / 2 (for example 5)
-5 / 2 is -2.5, so 2.5 backwards? I’m a little confused

-2.5 doesn’t mean anything in this context. Multiplied with a vector, you would have:
-2.5 * u
which makes more sense to say that you FLIP the vector, and extend its length by 2.5
=> 2.5 * (-u)

That’s just mathematical writing, of course -2.5u = 2.5(-u) so you don’t need to explicit that in your code at all

So about shrinkage, since you shorten the size, yes you would have to reflect that in your code. You can keep the same formulas though, as -(-u) = u, so you’d actually keep the opposite direction of your vector (and not flip it), which would make it go the other way, which is exactly what you want to do in that context.

I have programmed such thing with handles back then, I don’t exactly recall the code, but if you somewhat need help, I can sure check it for you

1 Like

i think you can just do size = Vector3.new(blade.Size.X, blade.Size.Y, distance)

and then for the cframe it would be at the hand position, facing the raycast result position, shifted forwards in that direction by half the length (because size scales in both directions)

local cframe = CFrame.new(handPosition, raycastResult.Position)
cframe = cframe + cframe.LookVector*distance/2 -- maybe this one is minus?
1 Like