Make this compatible with R15?

So, here I have a straightforward pathfinding script.

local Npc = script.Parent
local Humanoid = Npc.Humanoid

local PathfindingService = game:GetService("PathfindingService")

local function getPath(destination)
	local path = PathfindingService:CreatePath()

	path:ComputeAsync(Npc.HumanoidRootPart.Position, destination.Position)

	return path
end

local function walkTo(destination)
	local path = getPath(destination)

	for index,waypoint in pairs(path:GetWaypoints()) do
		Humanoid:MoveTo(waypoint.Position)
		Humanoid.MoveToFinished:Wait()
	end
end

while true do
	walkTo(workspace.destination)
	walkTo(workspace.destinatino2)
	print("Walking to destination")
end

Now, this script works just fine. However, it only works for R6 characters. Whenever I try to put it in an R15 character—it simply doesn’t work and prints no errors.

I’d like to know how I could configure this to work with R15 and why it doesn’t already work with R15.

If anyone knows and could help, that would be great. Thank you!

1 Like

Your script has so many mistakes that I can’t find any. :sweat_smile: It works perfectly fine. The only thing that is stopping your NPC from moving is one anchored part, and that is HumanoidRootPart. It’s anchored by default when you insert a new rig in workspace.

image

Your pathfinding script doesn’t include anything that would have to be modified in order to be compatible with a particular rig-type. Works with both R6 and R15 rigs.

I’m sorry that you had to wait 5 days to get a reply. If pathfinding still doesn’t work and you don’t see any errors, insert a new rig and see what the difference between yours and the original is (any missing Motor6Ds, property configurations etc.). All of that of course with a preposition that HumanoidRootPart is unanchored, as well as any other base parts. Finally (the following is not related to the issue, but is more more of informative nature), to make your script perfect, it’s recommended to stick to Roblox code style. Script ordered this way: (comment block), services, (module imports), constants, variables, functions, (return statement).

Wish you a really pleasant day!

1 Like

*life saved noises *

Thank you so much! Indeed this worked, and I thought I had just messed up the script.

Might I ask just two questions about organization?

How come the variables second to last? I would think those would be second because they’re what define paths with only one word.

Also,

Is there somewhere I can find more on script organization? I’ve heard of a website. However, I don’t know where it is.

Again, thank you!

Your welcome! And yes, there is a website on Roblox Github that helped me a lot. Link: Roblox Lua Style guide.

As far as variables go, it’s sort of a standard. When you look at it, it’s pretty logical:

-- Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService") -- some write runService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")

You need to require modules then, because if the script is long and there are a lot of variables, it’s useful for the person who is using/maintaining/etc. your code to see what modules are required if any.

local GameManager = require(-- path)
-- Relative path if module is stored near the script,
-- otherwise, it's a good practice to use absolute paths
-- and you also already have services defined.

Constants and user configurations (I really got used to capitals here):

local SPEED = 150
local DEBUG_IMPORT_FUNCTIONS = false

Variables:
here come all the variables, ordered by your preference. Some people order by type (paths, booleans, integers and floats…). Personally, I rather group variables partially by type and partially by use:

local NPC = script.Parent.Parent
--[[
	this is a constant, but use of LOUD_SNAKE_CASE is somewhat
	impractical here. It is more commonly used for important
	configurations and constants we need to easily access and
	perhaps change multiple times.
]]
local humanoidType = Enum.HumanoidRigType.R15
local healthDisplayDist = 30 -- we will rarely change this (example)
local other = 40
local isRunning = false

It’s true that variables can be used to shorten paths, or even functions and methods, for instance:

local random = math.random -- important: not math.random(); () takes arguments
print(random(1, 5))

Shortened paths are always useful, and when we have a fast running loop, such as:

local values = script.Parent
RunService.Heartbeat:Connect(function(deltaTime)
	values.value_1.Value += 1
	values.value_2.Value -= 8	
	-- bunch of values with the same path here
end)


-- Good, but can be better.
RunService.Heartbeat:Connect(function(dt)
	script.Parent.value_1.Value += 1
	script.Parent.value_2.Value -= 8
	-- bunch of values with the same path here
end)

Variables are just on the right place, because we don’t very often need to find longs paths to access modules. If we do, we usually didn’t place it well. A module we require, if not external of course, should be either near the script we are accessing it from:

local SomeModule = require(script.SomeModule)

Or relatively close in ReplicatedStorage and ServerStorage:

-- Suppose ServerStorage is defined.
local AnotherModule = require(ServerStorage.Modules.AnotherModule)
-- If the path is still too long:
local modulesFolderPath = ServerStorage.Data.Modules.OtherModules.AnotherOtherModules
local AnotherModule = require(modulesFolderPath.AnotherModule)

This may sound boring and unimportant, but it’s good to keep only the truly needed variables. Otherwise, we can end up with a messy script. It’s also good practice to limit variable scope, so if a variable is only needed inside a certain block, don’t define it outside of it.

do
	-- Imagine we need "n" in this loop.
	local n = 0
	for i = 1, #numbers do
		-- continue
	end
end

Lua garbage collector will clear this n variable from the memory as soon as the loop stops.

There is so much more to tell, and luckly, there are some good posts around the Dev Forum.

I hope this helps!

1 Like