I thought it would be fun to remake a .io game on Roblox as a break from my current project. It is pretty much complete, except I need to ensure the player can’t leave the playspace. To do this, I am trying to make it so they can touch the edge of the playspace, but they can’t go any further.
However, this is not exactly working as intended. Currently, there are three outcomes (none of which are what I expected):
A) https://gyazo.com/78a99985d94f5571e78309b876918117
The character gets sent to some magical realm (typically, it is -3000x, 3000x, -3000z, or 3000z).
B) https://gyazo.com/6032e43747aebda2468c618a868ca41a
The character boundary works as intended… except it is roughly 1/5 studs too far inside the play area.
C) https://gyazo.com/a3bbfd1ea0d10b86c5cf064f818895fe
This is the closest it gets. The character can’t go past the edge; However, it glitches rapidly between being on the edge as it should and the behavior described in point B.
NOTE: All of these outcomes are from the same code.
The following is the section of code responsible for calculating the movement (some parts were removed to skim it down to its bones for the sake of your sanity):
local StudsPerStep = 0.5
local LastUpdatedSize = 5
local function ReturnLargestNumber(a: number, b:number)
if a > b then
return a,b
elseif b > a then
return b,a
end
return a,b
end
local function CalculateDifference(a: number, b:number)
local largest, smallest = ReturnLargestNumber(a,b)
return largest - smallest
end
local function isNegative(n: number)
if n >= 0 then
return true
end
return false
end
local function CalculateMovementInBorders(position: Vector3, size: Vector3, rate: number, x: number, z:number)
if (x == 0) and (z == 0) then
return x, z
end
local positionX
local positionZ
if isNegative(position.X) then
positionX = position.X + (size.X / 2)
else
positionX = position.X - (size.X / 2)
end
if isNegative(position.Z) then
positionZ = position.Z + (size.Z / 2)
else
positionZ = position.Z - (size.Z / 2)
end
local calculatedX = positionX + x
local calculatedZ = positionZ + z
local insidePositiveX = if (calculatedX < 1024) then true else false
local insideNegativeX = if (calculatedX > -1024) then true else false
local insidePositiveZ = if (calculatedZ < 1024) then true else false
local insideNegativeZ = if (calculatedZ > -1024) then true else false
if insidePositiveX and insideNegativeX and insidePositiveZ and insideNegativeZ then
return x,z
end
local differenceX = 0
local differenceZ = 0
if (not insidePositiveX) or (not insideNegativeX) then
if isNegative(calculatedX) then
differenceX = CalculateDifference(calculatedX,-1024)
else
differenceX = CalculateDifference(calculatedX,1024)
end
end
if (not insidePositiveZ) or (not insideNegativeZ) then
if isNegative(calculatedZ) then
differenceZ = CalculateDifference(calculatedZ,-1024)
else
differenceZ = CalculateDifference(calculatedZ,1024)
end
end
local updatedX = if (insidePositiveX and insideNegativeX) then x else differenceX
local updatedZ = if (insidePositiveZ and insideNegativeZ) then z else differenceZ
return updatedX,updatedZ
end
RunService.RenderStepped:Connect(function()
if (not Character) or (not HumanoidRootPart) then
return
end
local x = 0
local z = 0
if Keys.W or Keys.Up then
x = x + StudsPerStep
end
if Keys.A or Keys.Left then
z = z - StudsPerStep
end
if Keys.S or Keys.Down then
x = x - StudsPerStep
end
if Keys.D or Keys.Right then
z = z + StudsPerStep
end
local CharacterCFrame = HumanoidRootPart.CFrame
x, z = CalculateMovementInBorders(CharacterCFrame.Position,HumanoidRootPart.Size,StudsPerStep,x,z)
if (x == 0) and (z == 0) then
if Tween then
Tween:Cancel()
Tween = nil
end
else
local CalculatedCFrame = CharacterCFrame + Vector3.new(x,0,z)
if CalculatedCFrame ~= CharacterCFrame then
CharacterCFrame = CalculatedCFrame
local difference = (CalculatedCFrame.Position - CharacterCFrame.Position).Magnitude
if Tween then
Tween:Cancel()
end
local properties = {CFrame = CalculatedCFrame}
Tween = TweenService:Create(HumanoidRootPart,TweenInfo.new(difference,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut),properties)
Tween:Play()
end
end
end)
NOTE: The playspace is a 2048 x 2048 area position at 0,0,0.
I am guessing it is something with my math, but I have been staring at this for too long and am clearly overlooking something. Any help is much appreciated.