Cant seen to get apples to randomly drop

Hello im a new scripter trying to get around and i wanted to challenge myself by making an apple tree that will spawn apples, destroy apples after they’ve been on the ground for more than a certain amount of time. and detect when a player touches it to un-anchor the apple.

So far ive made it spawn despawn but now drop, i tried to use math.random to randomly make an apple drop but that also didn’t work can anyone help?

Here’s my code. any help on this is appreciate it. please give me feed back as well if possible

local RS = game:GetService("ReplicatedStorage")
local AppleTree = game.Workspace.AppleTree:WaitForChild("Fruits")
local ApplesClone1 = RS.AppleTreeFruits:GetChildren()
local SpecialFruits = RS.AppleTreeFruits:FindFirstChild("SpecialFruits"):GetChildren()
local Players = game.Players
local Lifetime = 10
local RandomApple = math.random(1, 42)

while true do
	local function SpawnApple()
		for i = 1, 42 do
			local Apple = ApplesClone1[i]
			local AppleClone = Apple:Clone()

			local Handle = AppleClone:FindFirstChild("Handle")
			if Handle then

				Handle.Touched:Connect(function(otherPart)
					local model = otherPart:FindFirstAncestorOfClass("Model")

					if model then
						local player = Players:GetPlayerFromCharacter(model)

						if player then
							Handle.Anchored = false
						end
					end
				end)

			end
			AppleClone.Parent = AppleTree
			AppleClone.Name = "Apple"
			
		end
	end

	SpawnApple()
	task.spawn(function()
		for i = 1, 42 do
			local Apple = ApplesClone1[i]
			local AppleClone = Apple:Clone()
			local Handle = AppleClone:FindFirstChild("Handle")
			wait(math.random(1, 42))
			Handle.Anchored = false
		end

	end)
	
	wait(180)

	local function RemoveApple()
		for i, v in pairs(AppleTree:GetChildren()) do
			if v.Name == "Apple" then
				v:Destroy()
			end
		end
	end
	RemoveApple()
end

I think it has to do with how youre using task.spawn() and it not doing what you might think it does.

I am not terribly familiar with it myself but I do know that task.spawn is like a coroutine in the way it creates a new thread for a function to run in.

What you should instead be doing is spawning an apple with the SpawnApple() function and doing all the touched connecting and dropping from that function

Here is an updated script

local RS = game:GetService("ReplicatedStorage")
local AppleTree = workspace:WaitForChild("AppleTree"):WaitForChild("Fruits")
local ApplesClone1 = RS:WaitForChild("Apple")
--local SpecialFruits = RS.AppleTreeFruits:FindFirstChild("SpecialFruits"):GetChildren()
local Players = game:GetService("Players")
local Lifetime = 180
local RandomAppleTimer = math.random(1, 42)


local function SpawnApple()

	print("spawning apple")

	local AppleClone = ApplesClone1:Clone()

	AppleClone.Name = "Apple"
	AppleClone.Parent = AppleTree

	local Handle = AppleClone:FindFirstChild("Handle")
	if Handle then

		Handle.Touched:Connect(function(otherPart)
			local model = otherPart:FindFirstAncestorOfClass("Model")

			if model then
				local player = Players:GetPlayerFromCharacter(model)

				if player then
					Handle.Anchored = false
				end
			end
		end)

	end

	coroutine.wrap(function() -- puts the delete timer in a new thread so the for loop can run without yielding
		task.wait(Lifetime)
		if AppleClone.Parent == AppleTree then  -- checks if the apple has been picked up/doesnt exist in the tree anymore
			AppleClone:Destroy()
		end
	end)()
end


for i = 1, 42 do
	SpawnApple()
	task.wait(RandomAppleTimer)
end

I tried not to change too much, and I did not test the picking up part, but some of the issue was your formatting, hopefully this will help re-organize your future scripts

https://gyazo.com/83d5f75363c17ced7ae5ddef7f7fb203
(I changed the timer to be lower for the video)

In the future you will want to spawn the apple in a random position within the scope of the tree mode, let the apple fall to the ground, then wait and anchor it, or dont anchor it at all and it will save you some time.

I hope this helped!

[edit]
reading your post a little closer, I realize you said you already got the spawn and despawn working, so ill try to help with dropping instead, leaving this above here cause its still good…

Im not exactly sure what you mean by randomly spawning, since your code already did that. Could you clarify if you mean randomly spawning as in time? or randomly spawning as in position…

[edit]
No response yet so im going to leave this here and be on my way

Add this function before you parent the apple to the appleTree

local function setApplePos(apple)
		local treePivot = AppleTree.Parent:GetPivot() -- this is a cframe value 
		local spawnBox = workspace:WaitForChild("SpawnBox")
		--[[
			spawnbox is equal to a part in the workspace (or wheverer you want)
			this part defines the specific spawning area minus the y because you will set the part
			at the y-height you want to spawn the apples at

			this code gets the size of said spawning part and changes the position of the apple before
			it spawns to a random spot in the spawnPart size/2
		--]]

		local hitbox = spawnBox.Size
		local ranSpawnX = math.random(-hitbox.X/2, hitbox.X/2)
		local ranSpawnZ = math.random(-hitbox.Z/2, hitbox.Z/2)

		apple.Handle.Position = Vector3.new(treePivot.X + ranSpawnX, spawnBox.Position.Y, treePivot.Z + ranSpawnZ)

	end

https://gyazo.com/ee4bf14c69cc1642168f96520f37462e

1 Like

thank you, sorry for the late reply and yes youve corrected all of my mistakes and made the script better. I really appreciate the help and the time you put into it. Thank you

1 Like

Nice its gotten rid of many errors but now the only issue is its not spawning…

heres the full script. ive added the function before i parent the apple

local RS = game:GetService("ReplicatedStorage")
local AppleTree = workspace:WaitForChild("AppleTree"):WaitForChild("Fruits")
local ApplesClone1 = RS:WaitForChild("Apple")
--local SpecialFruits = RS.AppleTreeFruits:FindFirstChild("SpecialFruits"):GetChildren()
local Players = game:GetService("Players")
local Lifetime = 180
local RandomAppleTimer = math.random(1, 42)


local function SpawnApple()

	print("spawning apple")

	local AppleClone = ApplesClone1:Clone()

	AppleClone.Name = "Apple"
	AppleClone.Parent = AppleTree

	local Handle = AppleClone:FindFirstChild("Handle")
	if Handle then

		Handle.Touched:Connect(function(otherPart)
			local model = otherPart:FindFirstAncestorOfClass("Model")

			if model then
				local player = Players:GetPlayerFromCharacter(model)

				if player then
					Handle.Anchored = false
				end
			end
		end)

	end

	coroutine.wrap(function() -- puts the delete timer in a new thread so the for loop can run without yielding
		task.wait(Lifetime)
		local function setApplePos(apple)
			local treePivot = AppleTree.Parent:GetPivot() -- this is a cframe value 
			local spawnBox = workspace:WaitForChild("SpawnBox")
		--[[
			spawnbox is equal to a part in the workspace (or wheverer you want)
			this part defines the specific spawning area minus the y because you will set the part
			at the y-height you want to spawn the apples at

			this code gets the size of said spawning part and changes the position of the apple before
			it spawns to a random spot in the spawnPart size/2
		--]]

			local hitbox = spawnBox.Size
			local ranSpawnX = math.random(-hitbox.X/2, hitbox.X/2)
			local ranSpawnZ = math.random(-hitbox.Z/2, hitbox.Z/2)

			apple.Handle.Position = Vector3.new(treePivot.X + ranSpawnX, spawnBox.Position.Y, treePivot.Z + ranSpawnZ)

		end
		setApplePos()
		if AppleClone.Parent == AppleTree then  -- checks if the apple has been picked up/doesnt exist in the tree anymore
			AppleClone:Destroy()
		end
	end)()
end


for i = 1, 42 do
	SpawnApple()
	task.wait(RandomAppleTimer)
end	

EDIT

i also added the spawn box into workspace

i also forgot to say all the apples are in replicated storage in a folder so i need to clone them properly or its gonna say attempt to clone table.

Edit

alright thank you for your help. Im going out so i wont be able to see any messages.

as of now only the print(apple spawning is working)

but if you have any way to fix it, it would be appreciated thank you and goodnight.

three things
#1 I changed the variable “ApplesClone1” to match what I had in my testing world and forgot to change it back sorry

#2 The code I sent gets a single apple from RS and clones it, then changes the position of it so it appears to be spawning from the apple tree.

For the folder of apples, im not sure what you want to do with those.
If you have say 3 different types of apples and you want to randomly spawn one of those 3 each spawn interval then you could make a random select function like this

local function pickRandomApple(folder)
	local apples = folder:GetChildren()
	local randomIndex = math.random(1, #apples)
	return apples[randomIndex]
end

Then change your ApplesClone1 variable to
local ApplesClone1 = RS.AppleTreeFruits:GetChildren()

And your final code looks like

local RS = game:GetService("ReplicatedStorage")
local AppleTree = workspace:WaitForChild("AppleTree"):WaitForChild("Fruits")
local ApplesClone1 = RS:WaitForChild("AppleTreeFruits"):GetChildren()
local SpecialFruits = RS.AppleTreeFruits:FindFirstChild("SpecialFruits"):GetChildren()
local Players = game:GetService("Players")
local Lifetime = 180
local RandomAppleTimer = math.random(1, 42)

local function SpawnApple()

	local function pickRandomApple(folder)
		local randomIndex = math.random(1, #folder)
		return folder[randomIndex]
	end

	local randomApple = pickRandomApple(ApplesClone1)

	print("spawning apple")

	local AppleClone = randomApple:Clone()

	AppleClone.Name = "Apple"

	local function setApplePos(apple)
		local treePivot = AppleTree.Parent:GetPivot() -- this is a cframe value 
		local spawnBox = workspace:WaitForChild("SpawnBox")
		--[[
			spawnbox is equal to a part in the workspace (or wheverer you want)
			this part defines the specific spawning area minus the y because you will set the part
			at the y-height you want to spawn the apples at

			this code gets the size of said spawning part and changes the position of the apple before
			it spawns to a random spot in the spawnPart size/2
		--]]

		local hitbox = spawnBox.Size
		local ranSpawnX = math.random(-hitbox.X/2, hitbox.X/2)
		local ranSpawnZ = math.random(-hitbox.Z/2, hitbox.Z/2)

		apple.Handle.Position = Vector3.new(treePivot.X + ranSpawnX, spawnBox.Position.Y, treePivot.Z + ranSpawnZ)

	end

	setApplePos(AppleClone)

	AppleClone.Parent = AppleTree

	local Handle = AppleClone:FindFirstChild("Handle")
	if Handle then

		Handle.Touched:Connect(function(otherPart)
			local model = otherPart:FindFirstAncestorOfClass("Model")

			if model then
				local player = Players:GetPlayerFromCharacter(model)

				if player then
					Handle.Anchored = false
				end
			end
		end)

	end

	coroutine.wrap(function() -- puts the delete timer in a new thread so the for loop can run without yielding
		task.wait(Lifetime)

		if AppleClone.Parent == AppleTree then  -- checks if the apple has been picked up/doesnt exist in the tree anymore
			AppleClone:Destroy()
		end
	end)()
end


for i = 1, 42 do
	SpawnApple()
	task.wait(RandomAppleTimer)
end

#3 Move the setApplePos function to the inside of these two lines if you dont want to do above code

	AppleClone.Name = "Apple"
	
	-- insert function here
	
	AppleClone.Parent = AppleTree

you moved it to the parent check.
Sorry if I changed to much of the code orientation, its probably alot to look at and I apologize

I would recommend you spend some time reading over everything ive sent and try your best to understand each part of it.

I find talking myself through the order in which everything happens to be a huge help in understanding complex code

Cheers

1 Like

Thank you for the explination, when i added it to the game it only said Handle is not a valid member of Apple.

got it working thank you so much

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.