Attempting to get npc to jump over hazardess object

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!

im trying to make a smart npc to attack players/dummies, but its failing to jump over simple hazardess objects

  1. What is the issue? Include screenshots / videos if possible!


the dummy keeps walking right into the kill part, even with pathfinding modifiers
image_2025-01-21_195153898

what is appears to be doing is walking right up to the brick without care
then goes left to then attempt to jump over, though already being dead when they reach the first waypoint:
image_2025-01-21_195323964

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

ive looked all over, very few resources i found that talked about this specific subject, and noen of them were any help.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

params:

	local agentParams = {
		["AgentHeight"] = 5.5,
		["AgentRadius"] = 4,
		["AgentCanJump"] = true,
		["Costs"] = {
			Hazard = math.huge
		}
		
	}

I know this is possible to achieve as ive seen a dev forum post long ago with a fully functional npc that completed obbies (ex: the stereotypical killbrick jumps) with no difficulty

How would i go about fixing this?

2 Likes

You can use a magnitude to find the distance between the object, and when the distance is low it tells the NPC to jump.

Would you like an example of this?

i have done something like this, but its very unreliable if the size is high

What do you exactly mean by “Size”

for instance of a kill brick is 25,25,25. the magnitude would be at the center of said object, making it unreliable

If the NPC is jumping over it doesn’t matter either way

You can probably do something like this.

local npc = script.Parent
local Killbrick = workspace.Killbrick --replace this obviously
local jumpHeight = 50

local function ForceJump()
    npc.Humanoid.Jump = true
end

local function checkAndJump()
    if (npc.PrimaryPart.Position - Killbrick.Position).magnitude < 10 then
        ForceJump()
    end
end

while true do
    checkAndJump()
    wait(0.1)
end

That would be true in most circumstances, but its still pretty unreliable in some settings.
like saying if the killbrick was as it currently is, and you have it jump right here
image_2025-01-21_211138532
the npc would still die if the killbrick was like this
image_2025-01-21_211217601

Then you can change the WalkSpeed of the humanoid.

that defeats the whole purpose

You can also change the jumpheight too.

again this defeats the whole purpose of the npc, its supposed to be smart and actually be competitive torwards the player, not straight up unfair

Try the script first. If the npc dies then decrease the magnitude.

doing something of that manner it jumps onto the brick and then dies, decreasing it makes it jump too late and already be dead

May you please show me with the script?

good luck

local function calculatedis(pos1, pos2)
	return (pos1 - pos2).magnitude
end
local function calculatedir(pos1, pos2)
	return (pos1 - pos2).unit
end

local char = script.Parent
local hrp = script.Parent:WaitForChild("HumanoidRootPart")
local hum = script.Parent:FindFirstChildOfClass("Humanoid")
local CollectionService = game:GetService("CollectionService")

local MaxDistance = 500

local function FindNearest()
	local nearest = nil
	local nearestmag = MaxDistance
	for i,v in pairs(workspace:GetChildren()) do
		if v:FindFirstChild("HumanoidRootPart") and v:FindFirstChildOfClass("Humanoid") and v ~= char and v:FindFirstChild("Info") and v:FindFirstChild("Info").Slappable.Value == true then
			local hrp2 = v:FindFirstChild("HumanoidRootPart")
			local hum2 = v:FindFirstChildOfClass("Humanoid")
			if hum2.Health > 0 then
				local mag = calculatedis(hrp.Position, hrp2.Position)
				if  mag <= nearestmag then
					nearest = v
					nearestmag = mag
				end
			end
		end
	end
	return nearest
end

local eInfo = {}

local function IsLocationTravelable(location:Vector3)

	local rayinfo = RaycastParams.new()
	rayinfo.FilterType = Enum.RaycastFilterType.Exclude
	rayinfo.RespectCanCollide = true
	rayinfo.FilterDescendantsInstances = char:GetDescendants()
	rayinfo.CollisionGroup = "Default"

	local info = workspace:Raycast(location,Vector3.new(0,-20,0),rayinfo)

	if info then
		return info.Instance
	end
	return false
end

local function TrailTo(Location)
	workspace.DIE:ClearAllChildren()
	local dis = calculatedis(hrp.Position,Location)
	local dir = calculatedir(Location,hrp.Position)

	local PartSeperationDistance = 1
	local VectorTable = {}
	local CanTravel = true
	for i = 0,dis,PartSeperationDistance do
		local Part = Instance.new("Part",workspace.DIE)
		Part.Anchored = true
		Part.CanCollide = false
		Part.CanQuery = false
		Part.CanTouch = false
		Part.Transparency = 0
		Part.Position = hrp.Position + (dir * i)
		Part.CFrame = CFrame.new(Part.Position,Location)
		Part.Size = Vector3.new(1,1,1)
		local pos = Part.Position
		local Travelable = IsLocationTravelable(pos)
		if not Travelable then
			CanTravel = false
			break
		end
		VectorTable[i] = {pos,Travelable}
	end


	return CanTravel
end

local function CanSeeTarget(Target:Model)
	local rayinfo = RaycastParams.new()
	rayinfo.FilterType = Enum.RaycastFilterType.Exclude
	rayinfo.RespectCanCollide = true
	rayinfo.FilterDescendantsInstances = char:GetDescendants()
	rayinfo.CollisionGroup = "Default"
	local hum = Target:FindFirstChildOfClass("Humanoid")
	local ehrp = hum.RootPart

	--raycasts to the hrp, retuns false if theres objects in the way, true if it can see
	local e = calculatedir(ehrp.Position,hrp.Position) * 100

	local Part = Instance.new("Part",workspace.DIE)
	Part.Anchored = true
	Part.CanCollide = false
	Part.CanQuery = false
	Part.CanTouch = false
	Part.Transparency = 0
	Part.Position = hrp.Position+e
	Part.CFrame = CFrame.new(Part.Position,ehrp.Position)
	Part.Color = Color3.new(0, 1, 0)
	Part.Size = Vector3.new(1,1,1)


	local info = workspace:Raycast(hrp.Position,e,rayinfo)
	if info then
		Part.Position = info.Position
		if info.Instance:IsDescendantOf(Target) then
			return true
		end
	end
	return false
end

local function PathfindToLocation(Location,eChar)
	workspace.PathfindDebug:ClearAllChildren()
	if IsLocationTravelable(Location) == false then
		return false
	end
	local agentParams = {
		["AgentHeight"] = 5.5,
		["AgentRadius"] = 4,
		["AgentCanJump"] = true,
		["Costs"] = {
			Hazard = math.huge
		}
		
	}
	local PathfindingService = game:GetService("PathfindingService")
	local Path = PathfindingService:CreatePath(agentParams)
	Path:ComputeAsync(hrp.Position,Location)
	local Waypoints = Path:GetWaypoints()
	for i,v in pairs(Waypoints) do
		local pos = v.Position
		local Part = Instance.new("Part",workspace.PathfindDebug)
		Part.Anchored = true
		Part.CanCollide = false
		Part.CanQuery = false
		Part.CanTouch = false
		Part.Transparency = 0
		Part.Position = pos
		Part.Size = Vector3.new(1,1,1)
		Part.Color = Color3.new(1,0,0)

	end
	local doBreak = false
	
	task.spawn(function()
		
	end)
	
	hum:GetPropertyChangedSignal("PlatformStand"):Connect(function()
		doBreak = true
	end)
	
	for i,v:PathWaypoint in pairs(Waypoints) do
		local pos = v.Position
		if doBreak then
			break
		end


		local success,fail = pcall(function()
			local finish = false
			if IsLocationTravelable(pos) then
			hum:MoveTo(pos)
			else
				finish = true
				doBreak = true
			end
			if v.Action == Enum.PathWaypointAction.Jump then
				hum.Jump = true
			end
			local t = 10
			if TrailTo(Location) and CanSeeTarget(eChar) then
				t = 0.01
				doBreak = true
			end
			task.spawn(function()
				if hum.WalkToPoint ~= v.Position then
					doBreak = true
				end
			end)





			hum:GetPropertyChangedSignal("PlatformStand"):Connect(function()
				finish = true
			end)
			hum.MoveToFinished:Connect(function()
				finish = true
			end)
			task.spawn(function()
				task.wait(2)
				if finish == false then
				finish = true
				hum.Jump = true
				hum:MoveTo(hrp.CFrame*CFrame.new(0,0,-3).Position)
				end
			end)
			

repeat task.wait() until finish

		end)
		if fail then
			print(fail.." IS THE STATUS")
			hum:MoveTo(Location)
			doBreak = true
			break
		end

	end
	--	end)

end

local BaseRange = 6
local function NearestHazardessObject()
	local hazards = {}
	
	local function PartVelDec(obj:BasePart)
		local Vel = obj.AssemblyLinearVelocity.Magnitude
		
		if Vel/2 >= 1 then
			return BaseRange*Vel/2
		else
			return BaseRange
		end
		
	end
	
	
	for _, object in pairs(workspace:GetDescendants()) do
		if CollectionService:HasTag(object, "Hazard") and (object.Position-hrp.Position).Magnitude < PartVelDec(object) then
			table.insert(hazards, object)
			return true,hazards
		end
	end


	return false
end


local function Smart(eChar:Model)
	local ehrp = eChar:FindFirstChild("HumanoidRootPart")
	local ehum = eChar:FindFirstChildOfClass("Humanoid")
	local Distance = calculatedis(hrp.Position, ehrp.Position)
	local Tool = char:FindFirstChildOfClass("Tool")

	if Distance <= 8 then
		Tool:Activate()
	end

	local override = false

	--print(Distance)
	if not override then

		local CanTravel = TrailTo(ehrp.Position)
		local CanSee = CanSeeTarget(eChar)

		if Distance >= 50 and Distance <= 100 then

			if CanTravel and CanSee then
				hum:MoveTo(ehrp.Position)
			else
				PathfindToLocation(ehrp.Position,eChar)
			end
		elseif Distance < 50 and Distance > 25 then

			if CanTravel and CanSee then
				hum:MoveTo(ehrp.Position)
			else
				PathfindToLocation(ehrp.Position,eChar)
			end
			if ehum.FloorMaterial == Enum.Material.Air then
				local Chance = math.random(1,5)
				if Chance == 1 and not eChar:FindFirstChild("Ragdolled" )then
					hum.Jump = true
				end
			end

		elseif Distance < 25 and Distance > 10 then
			local Chance = math.random(1,25)

			if Chance > 1 then
				if CanTravel and CanSee then
					hum:MoveTo(ehrp.Position)
				else
					PathfindToLocation(ehrp.Position,eChar)
				end
			else
				hum.Jump = true
			end

		end
	end



end

local CanEvade = true
local savedMag = nil
while task.wait() do
	local nearest = FindNearest()
	if nearest then
		local ehrp = nearest.HumanoidRootPart
		local ehum = nearest:FindFirstChildOfClass("Humanoid")
		local dir = (ehrp.Position-char.HumanoidRootPart.Position).Unit
		char.Torso.LookAt.CFrame = CFrame.new(char.Torso.Position, char.Torso.Position + Vector3.new(dir.X,0,dir.Z))

		local dir = calculatedir(hrp.Position,ehrp.Position)
		local dis = calculatedis(ehrp.Position,hrp.Position)
		if not eInfo[nearest] then
			eInfo[nearest] = {}
		end

		if not eInfo[nearest]["LastSwung"] and nearest:FindFirstChildOfClass("Tool") then
			local eTool = nearest:FindFirstChildOfClass("Tool") 
			eInfo[nearest]["LastSwung"] = 0
			eTool.Activated:Connect(function()
				eInfo[nearest]["LastSwung"] = 0
			end)
			task.spawn(function()
				while task.wait(0.001) do
					eInfo[nearest]["LastSwung"] += 0.001
				end
			end)
		end
		
		
		local function IsTravelingTorwardNPC()
			if savedMag then
				if savedMag < dis then
					return true
				end
			end
			savedMag = dis
			return false
		end
		
		
		local orien = hrp.Orientation
		local eOrien = ehrp.Orientation
		local test = (orien-eOrien).Magnitude
		local function LikleyToAttack()
			if test < 100 and test > 85 then
				if ehum.FloorMaterial == Enum.Material.Air and IsTravelingTorwardNPC() then
					return true
				end
			end
			return false
		end
		
		
		
		

		local lastSwung = eInfo[nearest]["LastSwung"] 
		if lastSwung~=nil and lastSwung < 0.05 and CanEvade and dis < 15 then
			CanEvade = false
			local special = Random.new():NextNumber(-0.25,0.25)
			local Far = 10*special
			local Back = hrp.Position+dir*Far
			if IsLocationTravelable(Back) then
				hum:MoveTo(Back)
				hum.Jump = true
				task.wait(0.5*special)
				delay(1.5*special/2,function()
					CanEvade = true
				end)
			end
		end
		
		local FoundHazard, Hazards = NearestHazardessObject()
		if FoundHazard then
			hum.Jump = true
		end
		

		if IsLocationTravelable(hrp.Position) then
			Smart(nearest)
		end

	end
end

There may be a few issues.
First, The jumpPower is not defined
Second, you need to instantly trigger jump
Third, Adjust smart jump logic.

jump is instantly triggered, and “smart” function’s jump logic doesnt intefer in the current state, but i see how it can in some situations and i will look into that, but this doesnt help my issue

The jump logic can interfere in certain situations though.