I have a script the output says attempt to call a nil value, even though the function is the same! Why is it doing this and how can I prevent this from happening in future times? here is the script
math.random (1,2) local Tool = script.Parent wait(2) if math.random == 1 then function onActivated() local rc = script.Parent.Parent.Parent.Parent.Lighting.A:Clone() rc.Parent = script.Parent.Parent end end if math.random == 2 then function onActivated() local rc = script.Parent.Parent.Parent.Parent.Lighting.B:Clone() rc.Parent = script.Parent.Parent end end Tool.Activated:connect(onActivated)
Please help!!! Thank you!!!
There are a few problems with this.
Begin by tabbing your code correctly
You are defining onActivated
twice.
It's usually bad o define functions inside if
or for
or while
. In this case, that is causing a problem, especially because
Your two if
statements AREN'T such that if one happens, the other doesn't:
A
)B
)A
, then obliterate that and use B
)You defined Tool
but barely use it! That will shorten your code a lot. But the lowercase tool
would be preferable in ROBLOX's naming system (and the remainder of your names).
At the same time, it makes no sense at all to refer to Lighting
like that. Use game.Lighting
. Besides that, you should use ReplicatedStorage
for storing objects, not the Lighting.
So ABSOLUTELY first, we need to use else
instead of having two if
s:
math.random(1, 2); local tool = script.Parent; wait(2); if math.random == 1 then function onActivated() local rc = tool.Parent.Parent.Parent.Lighting.A:Clone(); rc.Parent = tool.Parent; end else function onActivated() local rc = tool.Parent.Parent.Parent.Lighting.B:Clone(); rc.Parent = tool.Parent; end end Tool.Activated:connect(onActivated);
This will prevent the error. However, it's still wrong.
math.random
is a function. It won't ever be 1
. You have to call it, like you did on the first line. But the call on the first line doesn't do anything since you didn't use the value it returned.
You should instead say
local tool = script.Parent wait(2); if math.random(2) == 1 then -- same as with (1, 2) function onActivated() local rc = tool.Parent.Parent.Parent.Lighting.A:Clone(); rc.Parent = tool.Parent; end else function onActivated() local rc = tool.Parent.Parent.Parent.Lighting.B:Clone(); rc.Parent = tool.Parent; end end Tool.Activated:connect(onActivated);
As I said earlier, though, you shouldn't be defining the function twice.
You should define it once.
If you meant that, it will decide when created either A or B to use forever, then you would want to do this:
local tool = script.Parent local rc if math.random(2) == 1 then rc = game.Lighting.A -- Use ReplicatedStorage instead, though. else rc = game.Lighting.B end function onActivated() rc:Clone().Parent = tool.Parent; end Tool.Activated:connect(onActivated);
If you instead wanted to make it random each time the tool is activated, you would move the if
into the function:
local tool = script.Parent function onActivated() if math.random(2) == 1 then game.Lighting.A:Clone().Parent = tool.Parent -- Use ReplicatedStorage instead, though. else game.Lighting.B:Clone().Parent = tool.Parent end end Tool.Activated:connect(onActivated);
Variables must be declared and initiated in a 'foo=bar' type of format. Just saying 'math.random(1,2) is not correct. You must bind it to a variable name.
For example, you can do:
local ran = math.random(1,2) if ran == 1 then print("It's 1!") else print("It's 2!") end
In basic terms, functions are pre-written chunks of code that can be called to adapt to new or constant arguments. When functions are declared, THEY ARE NOT RUN. Functions must be called in order for them to run.
Let's look at an example:
function printHi() print("Hi!") end
The following code above won't print anything even though the function has been declared because it hasn't called the function yet.
Now, let's call it:
function printHi() print("Hi!") end printHi() --Outputs "Hi!"
Not only this; You can not have two functions with the same name. If you tried calling one, the compiler would be pretty upset with you for declaring two with the same name.
Don't use Lighting to store objects. Put them in Server Storage or Replicated Storage. It is more paradigm-like and there are certain advantages to it along with organization and structural neatness.
Alright, now using what we've learned, let's fix your script:
local Tool = script.Parent function chooseA() local rc = script.Parent.Parent.Parent.Parent.Lighting.A:Clone() rc.Parent = script.Parent.Parent end function chooseB() local rc = script.Parent.Parent.Parent.Parent.Lighting.B:Clone() rc.Parent = script.Parent.Parent end function onActivated() local ran = math.random(1,2) if ran == 1 then chooseA() else chooseB() end Tool.Activated:connect(onActivated)