Hello Devs, Im Making A game where NPC’s will be capable of swimming. But I have No Idea On How I should Go About In Making them be able to swim. So If anyone has any suggestions Please feel free to share, Thanks For Reading!
Can’t you just use a NPC animation script, then use :MoveTo() to make the NPC go in the water and swim around?
This + I would probably change the NPC’s HRP density to make them sink or float
I will give this a try although I was planning to use a swimmable part Thanks for the suggetion!
You can use the same approach as you would with a player.
You can use a BodyGyro to control the rotation of the NPC, and a BodyVelocity to control the velocity.
If you want to make it more realistic, you can use a BodyAngularVelocity to control the angular velocity of the NPC, and a BodyForce to control the force applied to the NPC.
Here’s a quick example of a script that will make a character swim.
local character = script.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local swimming = false
local function startSwimming()
swimming = true
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.Parent = character.PrimaryPart
bodyGyro.maxTorque = Vector3.new(0, math.huge, 0)
bodyGyro.cframe = character.PrimaryPart.CFrame
bodyGyro.cframe = bodyGyro.cframe * CFrame.Angles(0, math.pi / 2, 0)
local bodyVelocity = Instance.new("BodyVelocity")
bodyVelocity.Parent = character.PrimaryPart
bodyVelocity.maxForce = Vector3.new(0, math.huge, 0)
bodyVelocity.velocity = Vector3.new(0, 0, -10)
end
local function stopSwimming()
swimming = false
local bodyGyro = character.PrimaryPart:FindFirstChildWhichIsA("BodyGyro")
if bodyGyro then
bodyGyro:Destroy()
end
local bodyVelocity = character.PrimaryPart:FindFirstChildWhichIsA("BodyVelocity")
if bodyVelocity then
bodyVelocity:Destroy()
end
end
local function onHumanoidDied(humanoid)
stopSwimming()
end
local function onHumanoidJumping(humanoid)
stopSwimming()
end
local function onHumanoidRunning(humanoid)
stopSwimming()
end
local function onHumanoidSwimming(humanoid)
startSwimming()
end
local function onHumanoidFreeFalling(humanoid)
stopSwimming()
end
local function onHumanoidSeated(humanoid, active)
stopSwimming()
end
local function onHumanoidClimbing(humanoid, active)
stopSwimming()
end
local function onHumanoidGettingUp(humanoid)
stopSwimming()
end
local function onHumanoidFallingDown(humanoid)
stopSwimming()
end
local function onHumanoidStateChanged(humanoid, state)
if state == Enum.HumanoidStateType.Dead then
onHumanoidDied(humanoid)
elseif state == Enum.HumanoidStateType.Jumping then
onHumanoidJumping(humanoid)
elseif state == Enum.HumanoidStateType.Running then
onHumanoidRunning(humanoid)
elseif state == Enum.HumanoidStateType.Swimming then
onHumanoidSwimming(humanoid)
elseif state == Enum.HumanoidStateType.Freefall then
onHumanoidFreeFalling(humanoid)
elseif state == Enum.HumanoidStateType.Seated then
onHumanoidSeated(humanoid, true)
elseif state == Enum.HumanoidStateType.Climbing then
onHumanoidClimbing(humanoid, true)
elseif state == Enum.HumanoidStateType.GettingUp then
onHumanoidGettingUp(humanoid)
elseif state == Enum.HumanoidStateType.FallingDown then
onHumanoidFallingDown(humanoid)
end
end
local function onHumanoidChangedState(humanoid, state)
if state == Enum.HumanoidStateType.Seated then
onHumanoidSeated(humanoid, false)
elseif state == Enum.HumanoidStateType.Climbing then
onHumanoidClimbing(humanoid, false)
end
end
local function onHumanoidAdded(newHumanoid)
humanoid = newHumanoid
humanoid.StateChanged:Connect(function(state)
onHumanoidStateChanged(humanoid, state)
end)
humanoid.ChangedState:Connect(function(state)
onHumanoidChangedState(humanoid, state)
end)
end
if humanoid then
onHumanoidAdded(humanoid)
else
character.ChildAdded:Connect(function(child)
if child:IsA("Humanoid") then
onHumanoidAdded(child)
end
end)
end
I’ve made a swimmable part not too long ago.
Create a ServerScript
inside the NPC and paste the following code:
local runService = game:GetService("RunService")
local character = script.Parent
local head = character:WaitForChild("Head")
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local rootpart = humanoid.RootPart
local isSwimming = false
local toFind = "Water"
local currentBody = nil
humanoid.UseJumpPower = true
function swimIn(hit)
if hit:IsA("BasePart") and string.find(hit.Name, toFind) then
if not isSwimming then
isSwimming = true
currentBody = hit
local swimSupport = Instance.new("BodyVelocity")
swimSupport.Name = "SwimSupport"
swimSupport.P = game.Workspace.Gravity * rootpart.Mass / 3
swimSupport.MaxForce = Vector3.new(4000, 5000, 4000)
swimSupport.Parent = rootpart
humanoid.JumpPower = 0
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
end
end
end
function swimOut(hit)
if hit:IsA("BasePart") and string.find(hit.Name, toFind) then
if isSwimming then
isSwimming = false
currentBody = nil
if rootpart:FindFirstChild("SwimSupport") then
rootpart:WaitForChild("SwimSupport"):Destroy()
end
humanoid.JumpPower = 50
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
end
function onJump()
if isSwimming then
local swimSupport = rootpart:WaitForChild("SwimSupport")
local floatVelocity = Vector3.new(0, 3, 0)
if swimSupport.Velocity == floatVelocity then
swimSupport.Velocity = Vector3.new(0, humanoid.WalkSpeed + 2, 0)
end
if rootpart:FindFirstChild("SwimFloat") then
rootpart:WaitForChild("SwimFloat"):Destroy()
end
end
end
function handleSwimming(delta)
if isSwimming then
local swimSupport = rootpart:WaitForChild("SwimSupport")
swimSupport.Velocity = humanoid.MoveDirection * humanoid.WalkSpeed
if swimSupport.Velocity == Vector3.new(0, 0, 0) then
local surfaceY = currentBody.Position.Y + currentBody.Size.Y / 2 - 0.5
swimSupport.Velocity = Vector3.new(0, 3, 0)
task.delay(0.2, function()
if head.Position.Y >= surfaceY - 2 then
if not rootpart:FindFirstChild("SwimFloat") then
local swimFloat = Instance.new("BodyPosition")
swimFloat.Name = "SwimFloat"
swimFloat.P = 4000
swimFloat.MaxForce = Vector3.new(0, 8000, 0)
swimFloat.Position = Vector3.new(0, surfaceY, 0)
swimFloat.Parent = rootpart
end
end
end)
else
if rootpart:FindFirstChild("SwimFloat") then
rootpart:WaitForChild("SwimFloat"):Destroy()
end
end
humanoid:ChangeState(Enum.HumanoidStateType.Swimming)
else
if rootpart:FindFirstChild("SwimFloat") then
rootpart:WaitForChild("SwimFloat"):Destroy()
end
end
end
head.Touched:connect(swimIn)
head.TouchEnded:connect(swimOut)
runService.Heartbeat:connect(handleSwimming)
humanoid:GetPropertyChangedSignal("Jump"):connect(onJump)
And yes, I did modify it to only work for NPC’s
Feel free to use!
You should just be able to use Pathfinding and Pathfinding Modifiers to get NPCs to swim wherever you want.