I am having problems with this system I’ve created (Its not the full finished version), there are 2 types of pets normal and huge, for normal pets the system works great but for huge pets the positioning is off and I’ve spent days trying to figure out a solution but I just cant right now so I’m looking for help.
This is what its doing
I want the huge pets the be spaced apart the equivalent distance that the normal pets are but for whatever reason this is quite a challenge
local player = _GLOBAL_.Services.Players.LocalPlayer
local petsDisplayed = {}
local petsDisplayedHuge = {}
local petsOrdered = {}
local petsOrderedHuge = {}
local petRows = {}
local petRowsHuge = {}
local order = 1
_GLOBAL_.Services.RunService.Heartbeat:Connect(function()
--// Render [ petsDisplayed ]
local char = player.Character
if char and #petsOrdered >= 1 or #petsOrderedHuge >= 1 then
local lookVector = char.PrimaryPart.CFrame.LookVector
local charLocation = char.PrimaryPart.CFrame.Position
local rightVector = -char.PrimaryPart.CFrame.RightVector
local leftVector = char.PrimaryPart.CFrame.RightVector
local petDistance = 2.5
local petDistanceSide = 2.5
local petNumber = 1
local baseLocation = charLocation + Vector3.new(-lookVector.X * petDistance, -lookVector.Y - 0, -lookVector.Z * petDistance)
local charLook = charLocation + lookVector
local lookat = Vector3.new(charLook.X, baseLocation.Y + 0, charLook.Z)
local function RenderPetsOfType(rows: any, petSize: number, lastNormalRow: number)
local ordered = petsOrdered if petSize == 2 then ordered = petsOrderedHuge end
petNumber = 1
for rowNumber, petsPerRow in rows do
local petsToSide = math.floor(petsPerRow / 2)
local hasMiddlePet if petsPerRow / 2 ~= petsToSide then hasMiddlePet = true end
baseLocation = charLocation + Vector3.new(-lookVector.X * (petDistance * (rowNumber + lastNormalRow)), -lookVector.Y + 0, -lookVector.Z * (petDistance * (rowNumber + lastNormalRow)))
--// Pets to the left
for i = 1, petsToSide, 1 do
if ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local addVector = Vector3.new()
local pet = ordered[petNumber]['pet']
if not hasMiddlePet then addVector = (leftVector * Vector3.new(petDistanceSide, petDistanceSide, petDistanceSide)) / Vector3.new(2, 2, 2) end
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(baseLocation + ((leftVector) * i) * petDistanceSide - addVector, lookat), 0.01)
petNumber += 1
end
end
--// Pets in the middle
if hasMiddlePet then
if ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local pet = ordered[petNumber]['pet']
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(baseLocation, lookat), 0.01)
petNumber += 1
end
end
--// Pets to the right
for i = 1, petsToSide, 1 do
if ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local addVector = Vector3.new()
local pet = ordered[petNumber]['pet']
if not hasMiddlePet then addVector = (rightVector * Vector3.new(petDistanceSide, petDistanceSide, petDistanceSide)) / Vector3.new(2, 2, 2) end
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(baseLocation + ((rightVector) * i) * petDistanceSide - addVector, lookat), 0.01)
petNumber += 1
end
end
end
return #rows
end
local normalRender = RenderPetsOfType(petRows, 1, 0)
petDistanceSide = 5
petDistance = 7
local hugeRender = RenderPetsOfType(petRowsHuge, 2, normalRender)
end
end)
If your pets use a Mesh there is an Offset in the properties. Looks like your huge pets are the same size. May be as simple and setting the Offset right. You then could use that on all of them without changing your script at all. Or setting the right Offset vs what side they are on.
This looks like offset settings. May just have to guess untill you find what works.
Also unrelated … You’re using Heartbeat in a loop. I’ll bet you could use Stepped
and it would work just as well. Saving a lot of cycles being overused.
Heartbeat is around 240 fps … Stepped is around 60 fps. 60 updates a second should be fine.
This is hard to test as I don’t have your pets or everything set up to work with your script. So I’m speculating. First thought that comes to mind is to use the small pets as the base and proportional spacing for huge pets. To try and keep it in line I’ll stick to double. You may need to try other settings.
local player = _GLOBAL_.Services.Players.LocalPlayer
local petsDisplayed = {}
local petsDisplayedHuge = {}
local petsOrdered = {}
local petsOrderedHuge = {}
local petRows = {}
local petRowsHuge = {}
local order = 1
_GLOBAL_.Services.RunService.Heartbeat:Connect(function()
local char = player.Character
if char and (#petsOrdered >= 1 or #petsOrderedHuge >= 1) then
local lookVector = char.PrimaryPart.CFrame.LookVector
local charLocation = char.PrimaryPart.CFrame.Position
local rightVector = -char.PrimaryPart.CFrame.RightVector
local leftVector = char.PrimaryPart.CFrame.RightVector
local petDistance = 2.5
local petDistanceSide = 2.5
local baseLocation = charLocation + Vector3.new(-lookVector.X * petDistance, -lookVector.Y, -lookVector.Z * petDistance)
local charLook = charLocation + lookVector
local lookat = Vector3.new(charLook.X, baseLocation.Y, charLook.Z)
local function RenderPetsOfType(rows, petSize, lastNormalRow)
local ordered = petsOrdered
if petSize == 2 then
ordered = petsOrderedHuge
petDistance = petDistance * 2 -- Double the distance for huge pets
petDistanceSide = petDistanceSide * 2
end
local petNumber = 1
for rowNumber, petsPerRow in rows do
local petsToSide = math.floor(petsPerRow / 2)
local hasMiddlePet = petsPerRow % 2 ~= 0
local rowBaseLocation = charLocation + Vector3.new(-lookVector.X * (petDistance * (rowNumber + lastNormalRow)), 0, -lookVector.Z * (petDistance * (rowNumber + lastNormalRow)))
for i = 1, petsToSide do
if ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local pet = ordered[petNumber]['pet']
local addVector = hasMiddlePet and Vector3.new(0, 0, 0) or (leftVector * petDistanceSide) / 2
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(rowBaseLocation + ((leftVector * i) * petDistanceSide) - addVector, lookat), 0.01)
petNumber += 1
end
end
if hasMiddlePet and ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local pet = ordered[petNumber]['pet']
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(rowBaseLocation, lookat), 0.01)
petNumber += 1
end
for i = 1, petsToSide do
if ordered[petNumber] and ordered[petNumber]['pet'] and ordered[petNumber]['pet']:FindFirstChild('PetCFrame') then
local pet = ordered[petNumber]['pet']
local addVector = hasMiddlePet and Vector3.new(0, 0, 0) or (rightVector * petDistanceSide) / 2
pet.PetCFrame.Value = pet.PetCFrame.Value:Lerp(CFrame.new(rowBaseLocation + ((rightVector * i) * petDistanceSide) - addVector, lookat), 0.01)
petNumber += 1
end
end
end
return #rows
end
local normalRender = RenderPetsOfType(petRows, 1, 0)
RenderPetsOfType(petRowsHuge, 2, normalRender)
end
end)
Not tested. Hopefully this will give you an extra setting to use for this. Right now script is set to * 2.
This is also setting up a spot this would be set… even if the petDistanceSide = petDistanceSide * 2 isn’t quite right. This would still be the area you would need to make the calulation in.
(make sure to back up your original script first)
So there is some math you are going to need to do here, but you need to figure out what your base line size is, and then determine the scale size difference from base is.
So for example iif base is 5, then 10 would be a scale factor of 2. 5/5 = 1 so scale of 1.
7/5 = 1.4 scale factor. You then multiply that into your distance calculations.
So when they are arranging themselves, at whatever position a pet is, you should scale how it positions and other around it. You do not demonstrate exactly what you want here in your explanation, but my assumption is if you had a uniform grid, and each pet resented 1 unit on that grid. And you have a pet that is 2 grids in size, you want them to position around it in a way that makes sense. This is the way to do it.
There are quite a few ways you can achieve this based on the exact following pattern you want, this is functionally what you need to do no matter what overall.
If it was me, a pet would take up an area of space that others could be near it, and while they strive for a uniform positioning they don’t require it to be perfect and will be mildly displaced by a larger pet in the grouping.
If you want to do something more dynamic, consider looking at how boids work, and use a variable arriving and hold variable would also likely achieve what you are looking for.
I ended up rewriting the whole system and now it works exactly as intended
The problem was with the way the rows were being calculated because whenever you render a huge its start position is the row number X the new separation distance so you have to account for the first rows being smaller than the huge rows