Teleport something to the other side of axis-aligned box and keeping it in the box?

I’m trying to teleport a part to the other side of a box when it exits that box, the code I use to do this is:

self.Position = -(self.Position - self.BoundingBox.Origin) + self.BoundingBox.Origin

This does work, but I want it to be inside the box. How can I do this?
Picture to help visualize:


Sorry if this is confusing, I can provide more info if needed.

What is it you’re trying to do? When the item leaves one side of the box, it comes out the other, retaining velocity?

I’m trying to create boids and the teleporting behavior shown in this video:

The problem is that when it detects that the boid is outside the box, it teleports it to the opposite side, but remains outside of it. On the next frame, it detects the boid is outside, teleporting it and causing flickering.

What does the checks look like?

It’s just aabb checks:

function BoundingBox.__index:IsInside(Point: Vector3)

    return (self.MaxX >= Point.X and Point.X >= self.MinX) and (self.MaxY >= Point.Y and Point.Y >= self.MinY) and (self.MaxZ >= Point.Z and Point.Z >= self.MinZ)

end
function Boid.__index:UpdatePosition(dt: number)
    self.Position += self.Velocity * dt
    if self.BoundingBox then
        if not self.BoundingBox:IsInside(self.Position) then
            self.Position = -(self.Position - self.BoundingBox.Origin) + self.BoundingBox.Origin
        end
    end
end

I swapped the position movement and outside check around and it still flickered.

You should add padding for the IsInside check to compensate for the size of the object, and rotation. What’s happening is its clipping outside the bounds, and being teleported to the other side, and thus is going into a loop

The boid, at least in the code, doesn’t have size or rotation, so there is no need to account for it.

Okay then perfect

function BoundingBox.__index:IsInside(Point: Vector3)

    return (self.MaxX > Point.X and Point.X > self.MinX) and (self.MaxY > Point.Y and Point.Y > self.MinY) and (self.MaxZ > Point.Z and Point.Z > self.MinZ)

end

Try this instead

Wait hold on, I need to take a look at the comparisons real quick

Nope, flickering still occurs.

Does this work?

function BoundingBox.__index:IsInside(Point: Vector3)

	return 
		(self.MaxX + 1 >= Point.X and Point.X >= self.MinX -1) and 
		(self.MaxY + 1 >= Point.Y and Point.Y >= self.MinY - 1) and 
		(self.MaxZ + 1 >= Point.Z and Point.Z >= self.MinZ - 1)

end

Nope, they still flicker. I’m pretty sure it has nothing to do with the check.

Can you send a gif of it? ShareX or Gyazo

Can you back the camera up so I can see the entire bounding box? I’m trying to see where else they are flickering to

It’s as I thought, they are teleporting outside the other side of the bounds. I’m not sure how, but you should print like

print('----------------');
print(point.X, point.Y);
print(bounds.MinX, bounds.MinY);
print(bounds.MaxX, bounds.MaxY);

So that you can see the actual coordinates compared to the bounds when they teleport

For anyone who is looking for a solution, a friend on discord helped make this for me:

local function ClampVectorToBox(Vector, BoxDimension)
    local B = 2 * Vector3.new(math.abs(Vector.X), math.abs(Vector.Y), math.abs(Vector.Z)) / BoxDimension
    
    return Vector/math.max(B.X, B.Y, B.Z)
end
-- blah blah blah
function Boid.__index:UpdatePosition(dt: number)
    if self.BoundingBox then
        if not self.BoundingBox:IsInside(self.Position) then
            self.Position = ClampVectorToBox(self.BoundingBox.Origin - self.Position, self.BoundingBox.Size) + self.BoundingBox.Origin
            
        end
    end
    self.Position += self.Velocity * dt
    
end
1 Like