Help on how to fix and make better scripts

So first of all i am not a good coder, i don’t put puzzle pieces together i glue them into a random mass which causes quite a few issues. Anyway this is my barebones “Script” that i have been working on:

local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")

local mob = {}

function IsObstacleInFront(mob)
local ray = Ray.new(mob.PrimaryPart.Position, mob.PrimaryPart.CFrame.LookVector * 5) 
local hit, position = workspace:FindPartOnRay(ray, mob)
return hit ~= nil and position.Y > mob.PrimaryPart.Position.Y + 2 
end

function MakeMobJump(mob)
local humanoid = mob:WaitForChild("Humanoid")
if humanoid:GetState() == Enum.HumanoidStateType.Running then
	humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end

function CanMobJump(mob)
local config = mob:FindFirstChild("Config")
if config then
	local canJumpValue = config:FindFirstChild("CanJump")
	if canJumpValue and canJumpValue:IsA("BoolValue") then
		return canJumpValue.Value
	end
end
return false 
end

function ChaseTarget(mob, target)
local humanoid = mob:WaitForChild("Humanoid")
local targetHumanoidRootPart = target:WaitForChild("HumanoidRootPart")
local predictionTime = 0.5 

local canJump = CanMobJump(mob)

while target and target.Parent and humanoid.Health > 0 do
	local targetPosition = targetHumanoidRootPart.Position
	local targetVelocity = targetHumanoidRootPart.Velocity
	local mobPosition = mob.PrimaryPart.Position

	local predictedPosition = targetPosition + (targetVelocity * predictionTime)

	local direction = (predictedPosition - mobPosition).Unit

	local moveToPosition = mobPosition + direction * humanoid.WalkSpeed * 0.5 

	humanoid:MoveTo(moveToPosition)

	if canJump then
		local playerDistance = (targetPosition - mobPosition).Magnitude
		if IsObstacleInFront(mob) then
			MakeMobJump(mob)
		end
	end

	wait(0.1)
   end
      end

function mob.Patrol(mob, map)

local humanoid = mob:FindFirstChild("Humanoid")
local config = mob:FindFirstChild("Config")
local targetRange = config.ChaseRange.Value
local waypoints = map:FindFirstChild("Waypoints"):GetChildren()
local currentWaypointIndex = math.random(1, #waypoints)

while humanoid and humanoid.Health > 0 do
	local nearestTarget = nil
	local shortestDistance = targetRange
	local mobPosition = mob:WaitForChild("HumanoidRootPart").Position


	        for _, enemy in pairs(workspace.Mobs:GetChildren()) do
		local character = enemy
		if character:FindFirstChild("HumanoidRootPart") and 
                    character:FindFirstChild("Humanoid") then
	        local humanoid = character.Humanoid
		
			if humanoid.Parent:FindFirstChild("Config") and humanoid.Parent.Config.Team.Value ~= mob.Config.Team.Value then
				if humanoid.Health > 0 then
					local distance = (character.HumanoidRootPart.Position - mobPosition).Magnitude
					if distance < shortestDistance then
						nearestTarget = character
						shortestDistance = distance
				
					end
				end
			end
		end
	end

	for _, player in pairs(Players:GetPlayers()) do
		local character = player.Character
		if character and character:FindFirstChild("HumanoidRootPart") and character:FindFirstChild("Humanoid") then
			local humanoid = character.Humanoid
			if humanoid.Parent:FindFirstChild("Config") and humanoid.Parent.Config.Team.Value ~= mob.Config.Team.Value then
				if humanoid.Health > 0 then
					local distance = (character.HumanoidRootPart.Position - mobPosition).Magnitude
					if distance < shortestDistance then
						nearestTarget = character
						shortestDistance = distance
						
						return nearestTarget
						
					end
				end
			end
		end
	end

		

	if nearestTarget then
		ChaseTarget(mob, nearestTarget)
	else
		local waypoint = waypoints[currentWaypointIndex]
		mob.MovingTo.Value = currentWaypointIndex
		humanoid:MoveTo(waypoint.Position)
		humanoid.MoveToFinished:Wait()


		currentWaypointIndex = currentWaypointIndex % #waypoints + 1
	end

	
	wait(0.1)
end
end


    function mob.Spawn(name, quantity, map)
local mobExists = ServerStorage.Mobs:FindFirstChild(name)

if mobExists then
	for i = 1, quantity do
		task.wait(0.5)
		local newMob = mobExists:Clone()
		local Config = newMob:FindFirstChild("Config")

	
		if Config.Team.Value == 1 then
			newMob.HumanoidRootPart.CFrame = map.Team1Base.CFrame
		elseif Config.Team.Value == 2 then
			newMob.HumanoidRootPart.CFrame = map.Team2Base.CFrame
		end

		
		newMob.Parent = workspace.Mobs
		newMob.HumanoidRootPart:SetNetworkOwner(nil)

		
		local movingTo = Instance.new("IntValue")
		movingTo.Name = "MovingTo"
		movingTo.Parent = newMob

	
		newMob.Humanoid.Died:Connect(function()
			task.wait(0.5)
			newMob:Destroy()
		end)

		
		coroutine.wrap(mob.Patrol)(newMob, map)
			end
	
	
else
	warn("Requested mob does not exist:", name)
end
end

return mob 

Now i have a few questions A. Do you have any ideas on how to make this script or other scripts better and how fix them and all that stuff and B. Do you have any idea on how to possibly fix a few bugs, for example when two mobs find each other or when a mob finds a player, sometimes it just stands still for no apparent reason, it doesn’t chase, it doesn’t do much and two do you know how to assign team values when a mob spawns, like right now i have to put it as a value which isn’t changed meaning one mob can’t spawn on both teams, if it’s value is 1 internally, there no way i can like code it to be able to be on team 2 as well if you have any guides or ideas on how to do those things that’d be great. I just wanna add that this script isn’t finished but it is in a “working” state

I’d just take some of the functions and put them in a module script, I’m sure you’ll find a use for them later on again. This will make your script drastically smaller and easier to debug as well.
Use the task library to replace some coroutines (like wraps) and all the wait functions (with task.wait functions).
Don’t use pairs or ipairs, just remove it (for i in t do…).
Might be beneficial to use :Once instead of :Connect in some events (so that the event disconnects itself).
I’d use custom attributes instead of object values (IntValue etc).

1 Like

When I first started I also thought fixing bugs would be harder than I thought but it is actually quite easy, the key component to it all is knowing how your code works and what tasks your scripts perform. So if your mob sees a player but doesn’t chase you want to look at your mobs script specifically its vision control. If you are using a raycasting to see if the player is in the mobs vision then you issue will likely be held within the raycasting part. It is also a HUGE help to use print() to see your script values and see where it starts to mess up.
For making scripts better I recommend having functions you’ll use often in a module script.

Hope this helps!

1 Like