I’m making a system with AI-controlled passengers walking onto buses, down the aisle and sitting in a seat. However, walking onto the bus causes it to fling around wildly, moving back and forth and side to side (although the angle appears to remain constant) quickly and seemingly at random. I can’t anchor the bus (it’s impractical for various reasons, mainly because it tends to break various A-Chassis things, and I also preferably need them to be able to walk around whilst the bus is moving). I’ve been told this shouldn’t happen with default physics because of an update that happened at some point.
I considered both welding the passenger to the bus then unwelding it when it needs to move and having its movement use a loop that calculates where it needs to be every frame. Both sound extremely bad for performance.
The code that handles movement:
--remove a passenger from their seat
local function Unseat(Passenger)
if Passenger.Humanoid.Sit == false then
return --they're already sat down
end
Passenger.Humanoid.Sit = false
local Seat = Passenger.Humanoid.SeatPart
if Seat ~= nil then
local Weld = Seat:FindFirstChild("SeatWeld")
if Weld ~= nil then
Weld:Destroy()
end
end
Passenger.Humanoid.Sit = false
Passenger.Humanoid:ChangeState(Enum.HumanoidStateType.Running)
AnimatePassenger(Passenger, Passenger.Animate.sit.SitAnim, false)
end
--sit a passenger in the specified seat
local function Seat(Passenger, SeatPart, Animate)
if Animate == nil then Animate = true end
if Passenger.Humanoid.Sit == true then
Unseat(Passenger)--so we can move them
end
SeatPart:Sit(Passenger.Humanoid)
Passenger.Humanoid:ChangeState(Enum.HumanoidStateType.Seated)
if Animate == true then
AnimatePassenger(Passenger, Passenger.Animate.sit.SitAnim, true)
end
end
--teleport a passenger using :SetPrimaryPartCFrame()
local function TeleportToPosition(Passenger, Position)
Unseat(Passenger)--if they're sat down, :SetPrimaryPartCFrame doesn't work
local PassengerNoY = Vector3.new(Passenger.HumanoidRootPart.Position.X, 0, Passenger.HumanoidRootPart.Position.Z)
local PositionNoY = Vector3.new(Position.X, 0, Position.Z)--remove Y values as they're irrelevant and cause false negatives
if regiLibrary.vect_distanceBetweenPositions(PassengerNoY, PositionNoY) > MinTeleportDistance then
Passenger:SetPrimaryPartCFrame(CFrame.new(Position.X, Position.Y + 3, Position.Z))--if it's actually worth our time
end
end
--essentially a wrapper for the above
local function TeleportTo(Passenger, Part)
TeleportToPosition(Passenger, Part.Position)
end
--use Humanoid:MoveTo() to have a passenger walk somewhere (then teleport if failed)
local function MoveTo(Passenger, Part)
local Humanoid = Passenger:FindFirstChildOfClass("Humanoid")
if Humanoid == nil then
error("Passenger missing humanoid.")
end
--make sure they're not sat down, then move them
Unseat(Passenger)
--animate the walking
local WalkAnimation = Passenger.Animate.walk.WalkAnim
local Animator = Humanoid.Animator
local LoadedAnimation = Animator:LoadAnimation(WalkAnimation)
LoadedAnimation: Play()
--and move them
Humanoid:MoveTo(Part.Position, Part)
Humanoid.MoveToFinished:Wait()
TeleportTo(Passenger, Part)
--we 're done, so stop animating
LoadedAnimation: Stop()
end