How to make parts align with the part a ray hits

I made a script to add an ice cover to a part hit by a ray, but it’s not staying on the part hit by the ray and instead going beyond the box I put the ice cube in to test it

local FreezeParts = {}
local module = require(game.ReplicatedStorage.lotsoffunstuff)
local ice = script.Ice:Clone()
script.Ice:Destroy()
local function func(v, vec)
	if vec and v then
		local newpart = Instance.new("Part", workspace)
		newpart.Color = script.Parent.Color
		newpart.Name = "FreezePart"
		local playersfrozen = {}
		
		for i,v in pairs(script.icedecals:GetChildren()) do
			local clon = v:Clone()
			clon.Parent = newpart
		end
		newpart.Color = Color3.fromRGB(4, 175, 236)
		newpart.Material = Enum.Material.SmoothPlastic
		newpart.CanCollide = false
		newpart.Transparency = 0.7
		
		local ray = RaycastParams.new()
		ray.IgnoreWater = true
		ray.FilterType = Enum.RaycastFilterType.Exclude
		ray.FilterDescendantsInstances = {script.Parent, FreezeParts, frozedparts}
		local realray = workspace:Raycast(script.Parent.Position, vec * 50, ray)

		if realray then
			local partthing = realray.Instance
			if partthing then
				local hum = module.FindHumanoid(partthing.Parent)
				if not hum then
					if partthing.Locked == false then
						table.insert(frozedparts, partthing)
						newpart.CFrame = CFrame.new(realray.Position, realray.Position + realray.Normal)
						if (script.Parent.Position - newpart.Position).Magnitude <= 20 then
							table.insert(FreezeParts,newpart)
							newpart.Orientation = partthing.Orientation
							local SizeX = math.clamp(newpart.Size.X, partthing.Size.X - partthing.Size.X/2, partthing.Size.X + partthing.Size.X/2)
							local SizeZ = math.clamp(newpart.Size.Z, partthing.Size.Z - partthing.Size.Z/2, partthing.Size.Z + partthing.Size.Z/2)
							local SizeY = math.clamp(newpart.Size.Y, partthing.Size.Y - partthing.Size.Y/2, partthing.Size.Y + partthing.Size.Y/2)
							
							local fitvector =  Vector3.new(SizeX, SizeY, SizeZ)
							
							

							if partthing.Size.X > 20 or partthing.Size.Y > 20 or partthing.Size.Z > 20 then
								newpart.Size = fitvector * Vector3.new(0.8,0.8,0.8)
							else
								newpart.Size = fitvector
							end 
						else
							newpart:Destroy()
						end
					end
				else
					local rootpart = hum.Parent:FindFirstChild("HumanoidRootPart")	
					if rootpart then
						spawn(function()
							local icing = ice:Clone()
							table.insert(FreezeParts, icing)
							icing.Parent = workspace
							icing.CFrame = rootpart.CFrame * CFrame.Angles(math.rad(-90),0,0)
							rootpart.Anchored = true
							wait(2)
							rootpart.Anchored = false
							icing:Destroy()
						end)
					end
				end
			end
		end

		newpart.Anchored = true
	end
end
wait(5)
script.Parent.ice_shatter:Play()
for i,v in pairs(workspace:GetChildren()) do
	if v ~= script.Parent then
		if v:IsA("Part") then
			local magnitude = (script.Parent.Position - v.Position).Magnitude
			if magnitude <= 50 then
				func(v, script.Parent.CFrame.RightVector.Unit)
				func(v, -script.Parent.CFrame.RightVector.Unit)
				func(v, script.Parent.CFrame.UpVector.Unit)
				func(v, -script.Parent.CFrame.UpVector.Unit)
				func(v, script.Parent.CFrame.LookVector.Unit)
				func(v, -script.Parent.CFrame.LookVector.Unit)
			end
		end
	end
end```
1 Like
  1. You could try adjusting the following lines of code:
local fitvector = Vector3.new(SizeX, SizeY, SizeZ)
if partthing.Size.X > 20 or partthing.Size.Y > 20 or partthing.Size.Z > 20 then
    newpart.Size = fitvector * Vector3.new(0.8,0.8,0.8)
else
    newpart.Size = fitvector
end 

to:

local fitvector = Vector3.new(SizeX, SizeY, SizeZ)
if partthing.Size.X > 20 or partthing.Size.Y > 20 or partthing.Size.Z > 20 then
    newpart.Size = fitvector * Vector3.new(0.8,0.8,0.8)
else
    newpart.Size = fitvector
end 
newpart.Position = realray.Position

This way, the newpart will be placed at the exact position where the ray hit the object, and the size will be adjusted accordingly.

  1. Alternatively, you could try changing the line newpart.Anchored = true to newpart.Anchored = false. This will allow the newpart to move freely with the physics simulation, which might help it stay on the part hit by the ray.

Try that :slight_smile:

local FreezeParts = {}
local frozedparts = {} -- Declare the 'frozedparts' table
local icedecals = {} -- Define 'icedecals' if it's not defined already

local module = require(game.ReplicatedStorage.lotsoffunstuff)
local ice = script.Ice:Clone()
script.Ice:Destroy()

local function func(v, vec)
    if vec and v then
        local newpart = Instance.new("Part", workspace)
        newpart.Color = script.Parent.Color
        newpart.Name = "FreezePart"
        local playersfrozen = {}
        
        for i, v in pairs(script.icedecals:GetChildren()) do
            local clon = v:Clone()
            clon.Parent = newpart
        end
        
        newpart.Color = Color3.fromRGB(4, 175, 236)
        newpart.Material = Enum.Material.SmoothPlastic
        newpart.CanCollide = false
        newpart.Transparency = 0.5 -- Adjust the transparency value
        
        local ray = RaycastParams.new()
        ray.IgnoreWater = true
        ray.FilterType = Enum.RaycastFilterType.Blacklist -- Use 'Blacklist' instead of 'Exclude'
        ray.FilterDescendantsInstances = { script.Parent, FreezeParts, frozedparts } -- Add 'frozedparts' to the filter
        
        local realray = workspace:Raycast(script.Parent.Position, vec * 50, ray)

        if realray then
            local partthing = realray.Instance
            if partthing then
                local hum = module.FindHumanoid(partthing.Parent)
                if not hum then
                    if partthing.Locked == false then
                        table.insert(frozedparts, partthing)
                        newpart.CFrame = CFrame.new(realray.Position, realray.Position + realray.Normal)
                        if (script.Parent.Position - newpart.Position).Magnitude <= 20 then
                            table.insert(FreezeParts, newpart)
                            -- Adjust the orientation setting if needed
                            newpart.Orientation = partthing.Orientation
                            local SizeX = math.clamp(newpart.Size.X, partthing.Size.X - partthing.Size.X/2, partthing.Size.X + partthing.Size.X/2)
                            local SizeZ = math.clamp(newpart.Size.Z, partthing.Size.Z - partthing.Size.Z/2, partthing.Size.Z + partthing.Size.Z/2)
                            local SizeY = math.clamp(newpart.Size.Y, partthing.Size.Y - partthing.Size.Y/2, partthing.Size.Y + partthing.Size.Y/2)
                            
                            local fitvector = Vector3.new(SizeX, SizeY, SizeZ)

                            if partthing.Size.X > 20 or partthing.Size.Y > 20 or partthing.Size.Z > 20 then
                                newpart.Size = fitvector * Vector3.new(0.8, 0.8, 0.8)
                            else
                                newpart.Size = fitvector
                            end
                        else
                            newpart:Destroy()
                        end
                    end
                else
                    local rootpart = hum.Parent:FindFirstChild("HumanoidRootPart")	
                    if rootpart then
                        spawn(function()
                            local icing = ice:Clone()
                            table.insert(FreezeParts, icing)
                            icing.Parent = workspace
                            icing.CFrame = rootpart.CFrame * CFrame.Angles(math.rad(-90), 0, 0)
                            rootpart.Anchored = true
                            wait(2)
                            rootpart.Anchored = false
                            icing:Destroy()
                        end)
                    end
                end
            end
        end

        newpart.Anchored = true
    end
end

wait(5)
script.Parent.ice_shatter:Play()

for i, v in pairs(workspace:GetChildren()) do
    if v ~= script.Parent then
        if v:IsA("Part") then
            local magnitude = (script.Parent.Position - v.Position).Magnitude
            if magnitude <= 50 then
                func(v, script.Parent.CFrame.RightVector.Unit)
                func(v, -script.Parent.CFrame.RightVector.Unit)
                func(v, script.Parent.CFrame.UpVector.Unit)
                func(v, -script.Parent.CFrame.UpVector.Unit)
                func(v, script.Parent.CFrame.LookVector.Unit)
                func(v, -script.Parent.CFrame.LookVector.Unit)
            end
        end
    end
end

I think I phrased what I was trying to do with this script wrong, in the first image is what I’m trying to achieve. But instead of that, I’m getting what’s going on in the second image. I added the “fitvector” to try to make it not go past the box and appear as it does in the first image.