Model positioning bug

I have this slime collecting mechanic and I currently have 2 slimes modeled and textured, their meshsizes are diffrent so I sized slime1 to a size that I like took the size to meshsize ratio and multiplied the slime2’s size property by those values and managed to achieve two slimes with two diffrent meshsizes to be the same size. But when I do that slime2 spawns a little bit underground due to the spawning logic which is down here. I

SpawnEvent.OnClientEvent:Connect(function(SlimeBatch)
	local List = SlimeBatch
	if not SlimeBatch[1] and SlimeBatch.ID then
		List = {SlimeBatch}
	end

	for _, SlimePacket in ipairs(List) do
		local Config = SlimeData[SlimePacket.Type]
		local VisualName = Config and Config.ModelName or SlimePacket.Type

		local Model = GetSlimeFromPool(VisualName)

		if Model then
			local RandomRot = CFrame.Angles(0, math.rad(math.random(0,360)), 0)
			local GroundCF = CFrame.new(SlimePacket.Position + Vector3.new(0, 0, 0)) * RandomRot
			local StartCF = GroundCF + Vector3.new(0, SPAWN_HEIGHT, 0)

			RenderedSlimes[SlimePacket.ID] = Model
			SlimeTypeCache[SlimePacket.ID] = {Type = SlimePacket.Type, Zone = SlimePacket.Zone}

			if Model.PrimaryPart then 
				Model:PivotTo(StartCF)
				local BounceCF = GroundCF + Vector3.new(0, BOUNCE_HEIGHT, 0)

				local Proxy = Instance.new("CFrameValue")
				Proxy.Name = "TweenProxy"
				Proxy.Value = StartCF
				Proxy.Parent = Model

				local Connection = Proxy.Changed:Connect(function(val)
					if Model then Model:PivotTo(val) end
				end)

				local TweenFall = TweenService:Create(Proxy, InfoFall, {Value = GroundCF})
				local TweenBounceUp = TweenService:Create(Proxy, InfoBounceUp, {Value = BounceCF})
				local TweenBounceDown = TweenService:Create(Proxy, InfoBounceDown, {Value = GroundCF})

				TweenFall.Completed:Connect(function()
					if RenderedSlimes[SlimePacket.ID] then
						ActiveTweens[SlimePacket.ID] = TweenBounceUp
						TweenBounceUp:Play()
					else
						Proxy:Destroy() 
					end
				end)

				TweenBounceUp.Completed:Connect(function()
					if RenderedSlimes[SlimePacket.ID] then
						ActiveTweens[SlimePacket.ID] = TweenBounceDown
						TweenBounceDown:Play()
					else
						Proxy:Destroy()
					end
				end)

				TweenBounceDown.Completed:Connect(function()
					ActiveTweens[SlimePacket.ID] = nil
					Proxy:Destroy() 
				end)

				ActiveTweens[SlimePacket.ID] = TweenFall
				TweenFall:Play()
			else 
				Model:MoveTo(GroundCF.Position) 
			end
		end
	end
end)

This block of gives the SlimeBatch it’s position info

local function GetRandomPosition(Part)
	local Size = Part.Size
	local CFramePos = Part.CFrame
	local RX = (RNG:NextNumber() - 0.5) * Size.X
	local RZ = (RNG:NextNumber() - 0.5) * Size.Z
	return (CFramePos * CFrame.new(RX, Size.Y/2 + 1, RZ)).Position
end

The issue is that you’re positioning the slime using SlimePacket.Position, but that position assumes a fixed height. Since slime2 has a different mesh size, its actual height might be taller or shorter, causing it to spawn slightly underground.

You can offset the spawn position vertically based on the slime’s bounding box size:

local heightOffset = Model:GetExtentsSize().Y / 2
local GroundCF = CFrame.new(SlimePacket.Position + Vector3.new(0, heightOffset, 0)) * RandomRot

This way, the slime will spawn with its center at the correct height, regardless of mesh size.

Model:GetExtentsSize().Y gives the full height of the model. Dividing by 2 places its center just above the ground, preventing it from clipping underground

Don’t hesitate to tell me if I got something wrong

That made sense but for some reason all the slimes are now spawning in the air, pic attached.

Try using the offset from the PrimaryPart’s bottom to its center:

local primarySizeY = Model.PrimaryPart.Size.Y
local scaleY = Model.PrimaryPart.Size.Y / Model.PrimaryPart.MeshSize.Y -- if using mesh scaling
local offsetY = (primarySizeY * scaleY) / 2
local GroundCF = CFrame.new(SlimePacket.Position + Vector3.new(0, offsetY, 0)) * RandomRot

Or if you’re not scaling the mesh manually, just:

local offsetY = Model.PrimaryPart.Size.Y / 2

This ensures the slime sits flush on the ground, regardless of mesh size or scaling. Tell me if this works

It’ll sound weird but subtracting one from the original equation you’ve provided fixed the problem and now they are all PERFECTLY level thank you a lot for your help you’ve helped me a ton.

local heightOffset = Model:GetExtentsSize().Y / 2 - 1
local GroundCF = CFrame.new(SlimePacket.Position + Vector3.new(0, heightOffset, 0)) * RandomRot

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.