Random position not working?

I am trying to make a shark fin swim around the map damaging players. On the third line of my script, I’m moving the shark fin on a random location on the map. Since this is the first time I ran my script, I don’t know if there is any other bugs. If there is any other bugs, I will edit this post. If you need to know anything else, just tell me.

– FIXED

The error message:

Workspace.Ocean.Sharks.SharkFin.Move:3: invalid argument #1 to ‘random’ (interval is empty)

My script:

local fin = script.Parent

fin.Position = Vector3.new(CFrame.new(math.random(-(workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.X * #workspace.Ocean.Chunks:GetChildren()) / 2, (workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.X * #workspace.Ocean.Chunks:GetChildren()) / 2), fin.Position.Y, math.random(-(workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.Z * #workspace.Ocean.Chunks:GetChildren()) / 2), (workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.Z * #workspace.Ocean.Chunks:GetChildren()) / 2)) -- I don't see where the problem is here.

while wait(6) do
	local plrs = game.Players:GetChildren()
	local charTarget = plrs[math.random(1, #plrs)].character
	local ignore = {}
	
	-- Creating ignore list
	
	for i, v in pairs(workspace.Ocean.Chunks:GetDescendants()) do
		if v:IsA('Part') then
			table.insert(ignore, v)
		end
	end
	
	table.insert(ignore, fin)
	
	-- Raycasting
	
	local ray
	
	if math.round(math.random(1, 3)) == 1 then
		ray = Ray.new(fin.Position, (fin.Position - (Vector3.new(charTarget.Position.X, fin.Position.Y, charTarget.Position.Z))).Unit * 10)
	else
		local randomCFrame = CFrame.new(math.random(-(workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.X * #workspace.Ocean.Chunks:GetChildren()) / 2, (workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.X * #workspace.Ocean.Chunks:GetChildren()) / 2, fin.Position.Y, math.random(-(workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.Z * #workspace.Ocean.Chunks:GetChildren()) / 2), (workspace.Ocean.Chunks.Chunk1.SeaFloor.Size.Z * #workspace.Ocean.Chunks:GetChildren()) / 2))
		
		ray = Ray.new(fin.Position, (fin.Position - Vector3.new(randomCFrame)).Unit * 10)
	end
	
	local hit = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
	
	-- Finding player
	
	if hit then
		for i, v in pairs(game.Players:GetChildren()) do
			if v.Character == hit.Parent then
				print('Shark is coming for you!')
			end
		end
	end
	
	-- Moving
	
	for i = 0, 1, 0.01 do
		fin.Position = Vector3.new(fin.CFrame:Lerp(ray.Direction.Unit * 10, i))
		
		fin.Touched:Connect(function(h)
			local hum = h:FindFirstChild('Humanoid')
			
			if hum then
				script.Parent.Bite:Play()
				
				hum.Health -= 75
			end
		end)
		
		wait(0.01)
	end
end

Edit 1:

I fixed that bug, but now I have an even weirder problem.

This is my new “fixed” script:

local fin = script.Parent
local chunks = workspace.Ocean.Chunks:GetChildren()
local seaFloor = workspace.Ocean.Chunks.Chunk1.SeaFloor
local minX = -(seaFloor.Size.X * #chunks) / 2
local maxX = seaFloor.Size.X * #chunks / 2
local minZ = -(seaFloor.Size.Z * #chunks) / 2
local maxZ = seaFloor.Size.Z * #chunks / 2

fin.Position = Vector3.new(CFrame.new(math.random(minX, maxX), 33, math.random(minZ, maxZ)))

while wait(6) do
	local plrs = game.Players:GetChildren()
	local charTarget = plrs[math.random(1, #plrs)].character
	local ignore = {}
	
	-- Creating ignore list
	
	for i, v in pairs(workspace.Ocean.Chunks:GetDescendants()) do
		if v:IsA('Part') then
			table.insert(ignore, v)
		end
	end
	
	table.insert(ignore, fin)
	
	print('Created ignore list')
	
	-- Raycasting
	
	local ray
	
	if math.round(math.random(1, 3)) == 1 then
		ray = Ray.new(fin.Position, (fin.Position - (Vector3.new(charTarget.HumanoidRootPart.Position.X, 33, charTarget.HumanoidRootPart.Position.Z))).Unit * 10)
	else
		minX = -(seaFloor.Size.X * #chunks) / 2
		maxX = seaFloor.Size.X * #chunks / 2
		minZ = -(seaFloor.Size.Z * #chunks) / 2
		maxZ = seaFloor.Size.Z * #chunks / 2
		
		ray = Ray.new(fin.Position, (fin.Position - Vector3.new(CFrame.new(math.random(minX, maxX), 33, math.random(minZ, maxZ))).Unit * 10))
	end
	
	print('Casted ray')
	
	-- Finding player
	
	local hit = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
	
	if hit then
		for i, v in pairs(game.Players:GetChildren()) do
			if v.Character == hit.Parent then
				print('Shark is coming for you!')
			end
		end
	end
	
	print('Possibly found player')
	
	-- Moving
	
	local recentPlr
	
	print(fin.Position)
	
	for i = 0, 1, 0.01 do
		fin.CFrame = fin.CFrame:Lerp(CFrame.new(ray.Direction.Unit * 10), i)
		
		fin.Touched:Connect(function(h)
			local hum = h.Parent:FindFirstChild('Humanoid')
			
			if hum and h.Parent ~= recentPlr then
				script.Parent.Bite:Play()
				
				recentPlr = hum.Parent
				
				hum.Health -= 75
			end
		end)
		
		wait(0.01)
		
		print(i)
	end
	
	print(fin.Position)
	print('Moved fin')
end

I added print() functions because whenever I ran the game, I couldn’t see the shark when I selected it. I told it to print its new position and the X and Z where fine, but the Y was negative infinity or something. Another part of the problem was, before the shark would move, it would print its starting position as 0,0,0 all the time.

Can you tell me why this is?

Edit 2:

Where I got the random position code from: Random Position

Edit 3:

New script:

local fin = script.Parent
local chunks = workspace.Ocean.Chunks:GetChildren()
local seaFloor = workspace.Ocean.Chunks.Chunk1.SeaFloor
local randomObj = Random.new(tick())
local minX = -(seaFloor.Size.X * #chunks) / 2
local maxX = seaFloor.Size.X * #chunks / 2
local minZ = -(seaFloor.Size.Z * #chunks) / 2
local maxZ = seaFloor.Size.Z * #chunks / 2

print(minX, maxX, minZ, maxZ)

fin.Position = Vector3.new(CFrame.new(randomObj:NextInteger(minX, maxX), 33, randomObj:NextInteger(minZ, maxZ)))

print(fin.Position)
print('')

while wait(4) do
	local plrs = game.Players:GetChildren()
	local charTarget = plrs[math.random(1, #plrs)].character
	local posTarget
	local ignore = {}
	
	-- Creating ignore list
	
	for i, v in pairs(workspace.Ocean.Chunks:GetDescendants()) do
		if v:IsA('Part') then
			table.insert(ignore, v)
		end
	end
	
	table.insert(ignore, fin)
	
	print('Created ignore list')
	print(ignore)
	print('')
	
	-- Raycasting
	
	local rayPerams = RaycastParams.new()
	local rayResult
	local plrOrPos
	local objHit = false
	
	rayPerams.FilterDescendantsInstances = ignore
	rayPerams.FilterType = Enum.RaycastFilterType.Blacklist
	
	if randomObj:NextInteger() == 1 then
		plrOrPos = true
		
		charTarget = Vector3.new(charTarget.HumanoidRootPart.Position.X, 33, charTarget.HumanoidRootPart.Position.Z)
		
		rayResult = workspace:Raycast(fin.Position, (fin.Position - charTarget.Unit * 10), rayPerams)
	else
		plrOrPos = false
		
		minX = -(seaFloor.Size.X * #chunks) / 2
		maxX = seaFloor.Size.X * #chunks / 2
		minZ = -(seaFloor.Size.Z * #chunks) / 2
		maxZ = seaFloor.Size.Z * #chunks / 2
		
		posTarget = Vector3.new(CFrame.new(randomObj:NextInteger(minX, maxX), 33, randomObj:NextInteger(minZ, maxZ)))
		
		rayResult = workspace:Raycast(fin.Position, (fin.Position - posTarget.Unit * 10), rayPerams)
	end
	
	print(plrOrPos)
	print(charTarget)
	print(posTarget)
	print('')
	
	print('Casted ray')
	print(rayResult)
	print('')
	
	-- Finding player
	
	if rayResult then
		if rayResult.Instance.Parent:FindFirstChild('Humanoid') then
			objHit = true
			
			print('THE SHARK IS COMING!!!') -- Sound effect (Jaws theme)
		end
	end
	
	print('Possibly found player')
	
	-- Moving
	
	local recentPlr
	
	for i = 0, 1, 0.01 do
		if objHit then
			fin.CFrame = fin.CFrame:Lerp(CFrame.new(rayResult.Position), i)
		else
			if plrOrPos then
				fin.CFrame = fin.CFrame:Lerp(CFrame.new(fin.Position, ((fin.Position * 2) - charTarget).Unit) * CFrame.new(0, 0, -10), i)
			else
				fin.CFrame = fin.CFrame:Lerp(CFrame.new(fin.Position, ((fin.Position * 2) - posTarget).Unit) * CFrame.new(0, 0, -10), i)
			end
		end
		
		fin.Touched:Connect(function(hit)
			local hum = hit.Parent:FindFirstChild('Humanoid')
			
			if hum and hit.Parent ~= recentPlr then
				script.Parent.Bite:Play()
				
				recentPlr = hum.Parent
				
				hum.Health -= 75
			end
		end)
		
		wait(0.01)
	end
	
	print(fin.Position)
	print('Moved fin')
end

Thank you :slight_smile:

2 Likes

Maybe check for any unnecessary brackets or typos. Just a tip from a friend, try to avoid writing these long lines of code. You could use instead use variables to store your chunk sizes and what not.

1 Like

I’m just going to make variables for those big chunks like you said. I’ll remember that for the future. Thx.

1 Like

Thank you. I fixed that bug, but now I have an even weirder problem.

This is my new “fixed” script:

local fin = script.Parent
local chunks = workspace.Ocean.Chunks:GetChildren()
local seaFloor = workspace.Ocean.Chunks.Chunk1.SeaFloor
local minX = -(seaFloor.Size.X * #chunks) / 2
local maxX = seaFloor.Size.X * #chunks / 2
local minZ = -(seaFloor.Size.Z * #chunks) / 2
local maxZ = seaFloor.Size.Z * #chunks / 2

fin.Position = Vector3.new(CFrame.new(math.random(minX, maxX), 33, math.random(minZ, maxZ)))

while wait(6) do
	local plrs = game.Players:GetChildren()
	local charTarget = plrs[math.random(1, #plrs)].character
	local ignore = {}
	
	-- Creating ignore list
	
	for i, v in pairs(workspace.Ocean.Chunks:GetDescendants()) do
		if v:IsA('Part') then
			table.insert(ignore, v)
		end
	end
	
	table.insert(ignore, fin)
	
	print('Created ignore list')
	
	-- Raycasting
	
	local ray
	
	if math.round(math.random(1, 3)) == 1 then
		ray = Ray.new(fin.Position, (fin.Position - (Vector3.new(charTarget.HumanoidRootPart.Position.X, 33, charTarget.HumanoidRootPart.Position.Z))).Unit * 10)
	else
		minX = -(seaFloor.Size.X * #chunks) / 2
		maxX = seaFloor.Size.X * #chunks / 2
		minZ = -(seaFloor.Size.Z * #chunks) / 2
		maxZ = seaFloor.Size.Z * #chunks / 2
		
		ray = Ray.new(fin.Position, (fin.Position - Vector3.new(CFrame.new(math.random(minX, maxX), 33, math.random(minZ, maxZ))).Unit * 10))
	end
	
	print('Casted ray')
	
	-- Finding player
	
	local hit = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
	
	if hit then
		for i, v in pairs(game.Players:GetChildren()) do
			if v.Character == hit.Parent then
				print('Shark is coming for you!')
			end
		end
	end
	
	print('Possibly found player')
	
	-- Moving
	
	local recentPlr
	
	print(fin.Position)
	
	for i = 0, 1, 0.01 do
		fin.CFrame = fin.CFrame:Lerp(CFrame.new(ray.Direction.Unit * 10), i)
		
		fin.Touched:Connect(function(h)
			local hum = h.Parent:FindFirstChild('Humanoid')
			
			if hum and h.Parent ~= recentPlr then
				script.Parent.Bite:Play()
				
				recentPlr = hum.Parent
				
				hum.Health -= 75
			end
		end)
		
		wait(0.01)
		
		print(i)
	end
	
	print(fin.Position)
	print('Moved fin')
end

I added print() functions because whenever I ran the game, I couldn’t see the shark when I selected it. I told it to print its new position and the X and Z where fine, but the Y was negative infinity or something. Another part of the problem was, before the shark would move, it would print its starting position as 0,0,0 all the time.

Can you tell me why this is?

1 Like

Ray.new is deprecated. Look into workspace:Raycast instead.

2 Likes

I did that. Thank you. Now it’s not 100000 miles down!

New error :frowning: :

Argument 1 missing or nil

on line 47.

local hit = workspace:FindPartOnRayWithIgnoreList(ray, ignore) -- Ignore is the ignore list.

FindPartOnRayWithIgnoreList is deprecated.
Look here:
https://developer.roblox.com/en-us/api-reference/function/WorldRoot/Raycast

Use RaycastParams for options:
https://developer.roblox.com/en-us/api-reference/datatype/RaycastParams

1 Like

maybe this little demo project might help you

Shark.rbxl (42.4 KB)

it uses AlignPosition and AlignOrientation to move the shark

image

and the script is a simple script like this

local alignPosition = script.Parent.AlignPosition
local alignOrientation = script.Parent.AlignOrientation

script.Parent.Touched:Connect(function(otherPart)
	local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
	if player == nil then return end
	if player.Character == nil then return end
	player.Character.Humanoid.Health = 0
end)

while true do
	local currentPosition = script.Parent.Position
	local targetPosition = Vector3.new(math.random(-100, 100), currentPosition.Y, math.random(-100, 100))
	alignPosition.Position = targetPosition
	alignOrientation.CFrame = CFrame.lookAt(currentPosition, targetPosition)
	local deltaTime = (currentPosition - targetPosition).Magnitude / alignPosition.MaxVelocity
	task.wait(deltaTime)
end
2 Likes

That is cool. Thanks, but I used raycasting so it doesn’t go through walls.

ok here is a version that does raycasting

Shark.rbxl (44.8 KB)

local alignPosition = script.Parent.AlignPosition
local alignOrientation = script.Parent.AlignOrientation
local raycastParams = RaycastParams.new()
local size = math.max(script.Parent.Size.X, script.Parent.Size.Y, script.Parent.Size.Z) / 2

script.Parent.Touched:Connect(function(otherPart)
	local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
	if player == nil then return end
	if player.Character == nil then return end
	player.Character.Humanoid.Health = 0
end)

while true do
	local currentPosition = script.Parent.Attachment.WorldPosition
	local targetPosition = Vector3.new(math.random(-200, 200), currentPosition.Y, math.random(-200, 200))
	local direction = targetPosition - currentPosition
	local raycastResult = workspace:Raycast(currentPosition, direction.Unit * (direction.Magnitude + size), raycastParams)
	if raycastResult ~= nil then
		targetPosition = raycastResult.Position + raycastResult.Normal * size
		direction = targetPosition - currentPosition
	end
	alignPosition.Position = targetPosition
	alignOrientation.CFrame = CFrame.lookAt(currentPosition, targetPosition)
	local deltaTime = direction.Magnitude / alignPosition.MaxVelocity
	task.wait(deltaTime)
end
1 Like