Hello! I’m trying to figure out how to send a path through a can collide door, the door opens when approached by any humanoid root part. Can anyone have any ideas on how to accomplish this?
I saw a post like this recently and didn’t see any good solutions. I had an idea though;
What if you check if the path was unable to be completed, and if it was then you check where the nearest door is to the player (edit: and see if a path will succeed from that door to the target location). You could then draw a path to that door, and a second path from the door to the target location.
Depending on your map, this may not work so well. But, I think this may be one of your only options if you want to go the Pathfinding route. I personally do not know of any good ways to create a custom path finding system of your own, so this is the first thing I would try in your situation.
One Method That Might Work is using the Path.Blocked
Event, if it is triggered check which way point is blocked then check for any doors nearby(or anything in the ignore list that the way point is being blocked by) , recompute the path to the previous point (before the blocked one) then tell the part to move to that point, then tween or animate the part through the door(to the other side of the object) and finally recompute the path again to the final destination(if path is blocked again, repeat)
Edit: I noticed this is somewhat similar to @Hazania’s Method (splitting the path up)
Another Alternative More Advanced option would be to create a custom path finding system:
For this i would recommend A* (A More efficient Pathfiding Algorithm than Dijkstra’s Algorithm
(I’ve made an example of A* not too long ago):
Note That the Path Finding Service already utilizes A*! (i believe…)
Worth noting that pathfinding will ignore any models with a Humanoid object, which is an extremely stupid way to make an ignore list (which should be a default feature). @Hazania solution should work fine for this though.
What would be the best way to search for a nearby door? What if the path is long… and the door would not be found?
Will pathfinding detect uncancollide opjects?
There are few ways to find a nearby door(Also by nearby i mean the objects that are blocking the path), placing all ignore list objects in a folder looping through it and checking each objects magnitude from the way point and finding the closet object (which i wouldn’t suggest doing, because it would be quite inaccurate) , sending a ray cast or even just a part to detect touching parts. However if the path is really long, sending a Ray in the direction the path is going, is probably a better idea.(Most likely overall too)
The solutions listed so far are either impractically slow or very specific. The solution used abroad is neither of those, though it does NOT support dynamic maps; if a part that the humanoid has to cross moves, you will have to use one of the methods people have told you.
The usual method of solving this is literally copying the entire map, removing all parts you want the humanoid to ignore (like the doors), placing the map roughly 100,000 studs away from the original (far enough away so it doesn’t render and does not cost anything), and using it for calculating your path. With this new map in place, simply take the start and endpoints of your needed path, translate them 100,000 studs in whatever direction you sent the pathmap (as I call it), calculate the path, and translate all the waypoints of the path 100,000 studs back. This will create a path that effectively allows you to ignore certain parts while being very cheap processor-wise.
The map is way way way too big to copy all it.
As long as there is less than say 100k parts, you can easily copy everything during a loading screen. Remember that this needs to be done only once when the server starts up, never after that.
Its a very big map… spanning a wide range with a lot of parts… and a lot lot lot of terrain.
How does one create a ray along a non existing/blocked path. And if the path is detected its blocked wont it detect any wall thats in the way? @Jaycbee05
This is hardly cheap and efficent at all; This solution is not any better than the rest. If anything, it’s a hacky solution. Also, pathfinding isn’t always a one time thing, so you might have to run this multiple times. At that point, the map would have to be fully cloned, replicated to the client, destroyed, and removed from all clients - not a quick and cheap process.
You misunderstand how a pathmap works. It is created ONCE on the server, and never again. Once a pathmap is made, all pathfinding (when specified of course) will use the pathmap instead of the normal map to create a path. It can easily be made so a client can use the pathmap without having to make its own.
The pathmap is never removed; it is kept and saved for the duration of the server or until a new map is made (such as in a round-based game).
Once a pathmap is made, the only expense is adding Vector3.new(100000,0,0) to the start/endpoints, and then subtracting it from the output waypoints. This is an expense that is so small that it is literally impossible to measure.
The only downside of this method is that it doesn’t work for dynamic maps, those that have moving parts.
Yet again, this depends. If the map is dynamic, one path map will not always work. Even cloning the entire map once is a huge process to do on the server (not to mention if the client has to replicate it)
Either way, it’s still a hacky solution, and not cheap and easy. While your solution works, I wouldn’t consider it the end all be all like you implied.
If you want to continue this argument, I’d suggest taking this into DMs. I don’t want to clutter this topic unnecessarily.
You are echoing what I already noted while adding in something that is simply not true.
Yes, this method doesn’t work with dynamic maps; I stated this 3-4 times now. If it did, it would be the perfect method.
Cloning the entire map is not as bad of a process as you may think, especially when it is not even rendered in. My game clones maps of 50k parts every round and it is not even noticeable.
As for the client side ‘lag’, there is none. Period. If you clone the map 100k studs away, there is no significant latency or processing on the client’s part. The client simply receives data that the new instances were added without rendering it.
It is not a ‘hacky’ solution, it is cheap, and it is easy to do as I am sure even a novice scripter can do it.
Please do not make things up. I never implied that it is the perfect solution or even applicable everywhere as I numerously wrote it’s main limitation, while still noting it’s superiority over other solutions in non-dynamic maps.
How many parts are in the map? If it is below 100k, it is doable. If it is below 50k, it is not even a problem. Above 100k and it kinda stops being practical as the map size is just too large; I would be curious of how long the pathfinder takes to make a path through it in the first place.
so, ive done some playing around with path finding, and found out that firstly if the part is set to can collide fasle in most cases the pathfinding service will not detect it, however this means setting the entire object to not collide, along with other disadvantages leads me to believe that a more customizable option (recommendation) is to create your own pathfinding system(preferably using A*), yes dont get me wrong there are many other alternatives but it boils down to the customizability and performance.(generalizing, not saying my solution has great performance)
if you still wanted know how you could find blocked part using the possible (untested) solution I gave:(might need some tweaking…)
local Ignorelist ----Folder or Table containing parts
for i, obj in pairs(ignorelist:GetDescendants()) do-------Loop through descendants or children to set all parts to false in the ignore list
if obj and obj:IsA("Part") then
obj.CanCollide = false
end
end
local Path = PathfindingService:CreatePath()
Path:ComputeAsync(Start.Position, End.Position)
local waypoints = Path:GetWaypoints()
for i, waypoint in pairs(waypoints) do
if waypoints[i + 1] then
local Dist = (waypoints[i].Position - waypoints[i + 1].Position).Magnitude
local ray = Ray.new(waypoints[i].Position, Vector3.new( 0,0, -Dist/2))
local raypart = workspace:FindPartOnRay(ray)--Finds the "Touching" part
if raypart and raypart:IsDescendantOf(ignorelist) then
local PartBetween = {v, waypoints[i + 1]}---- Waypoints neighboring the part
------- finish the rest, Tween Here and finish path
end
Just some thoughts, Have a Great Day or Night!
I would add that custom A* implementations can be MUCH faster than the built in pathfinder and don’t come with the restrictions. For example see
and
The most essential part to making a faster A* implementation than the built in one would be to use a map representation other than a simple grid. The larger the nodes, the less need to be traversed to reach a goal. Don’t use a simple grid, use navigation meshes, rooms, areas, regions, or something similar. Hierarchical implementations are a little more tricky but have HUGE payoffs.
This may be a little complex for what i need. I have a huge map with mostly terrain. This is a lot of extra learning to implement this than i think i’m willing at the moment.