That would take a long time to do, I would have to replace all of my variables like humrp and stuff with, for example, walkToOre(humrp,hum,etc.), would it be worth it?
you wouldn’t have to do that. This line for example has a getNearestOre().Main.Position
call that should just be nearest.Main.Position
. You need only a careful find-and-replace.
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
this is what i think it should look like
ocal ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
local function getTags(model)
local tags = 0
for _,tag in pairs(model:GetChildren()) do
if string.find(tag.Name,'Miner') then
tags += 1
end
end
return tags
end
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closestOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
print(closestOre)
return closestOre
end
local function breakOre()
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,getNearestOre().Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
then
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
call functions in same order
end)
The script does seem to work a lot better now!
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closestOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
return closestOre
end
local function breakOre(nearest)
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,nearest.Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
MiningAnim.Stopped:Wait()
task.wait(0.5)
newHitbox:HitStop()
Mining = false
end
end
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-nearest.Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
end)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
However it still runs into the issue of this:
Do I pcall it or check if Main is a child of Ore?
I’m afraid that there are just too many issues with this
I would need to manually define all of the variables like local function breakOre(Mining,Miner,MiningAnim,newHitbox) for every single function, it would just be too much work and I don’t think that the performance change would be significant enough.
I still run into the issue of half of the miners just being idle and the other half wandering around aimlessly.
May be good to add CollectionService:RemoveTag(nearest, "ToBeMined")
when they are hit inside breakOre
. There is certainly some part here that needs the tag removed, maybe if walking fails, think of ToBeMined as a debounce to be toggled when selecting and when broken/errored.
I was about to say stuff about me deleting the model later on in the script but I added that in and it actually did work, yet still have this issue sadly:
would it be wise to pcall it as I said in a previous reply? or is this avoidable somehow.
I feel like it is something to do with this line of code
and definitely this line of code, as the error message calls this as being the issue
Sorry! Yeah I am not sure why that would be happening, is Main a part of all Stone? which line is that?
Oh I should’ve maybe mentioned this at the start, but here is how a single ore model looks like, all of them are identical apart from their values and the actual name of the model.
Edit: Main is the, well, main part of the ore, the stone/slate mesh thing in the centre.
Well I certainly do not know why that is happening then, if nearest == nil or nearest.Main == nil then
should capture that problem. I say try GetPivot instead, it works with both models and parts, maybe the space between nearest and .Main i really don’t know lol.
(humrp.Position - nearest:GetPivot().Position).Magnitude <= 10
Maybe nearest is destroyed at that point after walking takes some time, since :Destroy
only sets and locks the parent to nil we should check that too
if nearest and nearest.Parent and (humrp.Position - nearest:GetPivot().Position).Magnitude <= 10 then
Wow that actually somehow fixed all of the problems I had before, thanks, I will do a stress test on this and see if it breaks.
Man this post is going on for far too long, i’ve found a few issues but no error messages for them:
Sometimes, the miners just stop completely as if the script has been removed from them and through some print statements, i’ve figured out that this code stops them:
if nearest == nil or nearest.Main == nil then
return
end
I tried to make this call the walkToOre statement again when it returns but that just ended in a stack overflow and studio nearly crashing.
Edit: I just changed the return to nearest = getNearestOre(), thanks for all the help man!
Edit2: the moment I typed the first edit in I checked studio and saw this:
https://gyazo.com/6069f96223d72c026202b6ef7dc4eca4
i’m also definitely not playing Unit: Classified [TECH DEMO] in the background.
You should probably do, The wait is important like it is in the while loop at the end of walkToOre, speaking of which you should remove that while loop. The function is already recursive and will degrade performance over time if you loop and recurse at the same time.
if nearest == nil or nearest.Main == nil then
task.wait(0.5)
walkToOre()
return -- still important! return prevents multiple runs while recursing
end
-- later on ...
WalkAnim:Stop()
-- while task.wait(0.5) do -- delete this
task.wait(0.5)
walkToOre()
still just inactivating after a while, if I put a print in between the task.wait(0.5) walkToOre() return then it prints nothing throughout the entire time, would you like a place download?
sure I’ll take a place download. It should be printing nothing as if nearest == nil then
should be the one catching this, it’s the case where it cannot find a closest ore that isn’t tagged.
– place download link removed to not let anyone else reading this to copy my game
edit: miner script is located in ServerScriptService → AI.
I think this addition will fix them idling around, I added remove tag after the pathfinding, since it will only try to break ore when they are close enough. Another fix may be to increase the minimum distance but then the teleport is quite visible. I also removed the MiningAnim.Stopped:Wait()
as that never seemed to trigger for me.
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and nearest.Parent and (humrp.Position - nearest:GetPivot().Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
-- removes tag if failed to mine
if nearest and nearest.Parent then
CollectionService:RemoveTag(nearest, "ToBeMined")
end
WalkAnim:Stop()
task.wait(0.5)
walkToOre()
end
Yep, thank you so much for the help, here are the results after stress testing for half an hour
The one slight