Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Attempt to call a nil value? I defined the function though! [Solved]

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!!!

3 comments

0

What on earth. I just submitted an answer and it didn't go through.

0

XD can you re-post it please? XD

0

I did. :P

2 answers

✓ Accepted answer

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:

  • The first one may succeed and the second fail (use A)
  • The second may succeed and the first may fail (use B)
  • Both may succeed (first use A, then obliterate that and use B)
  • Neither may succeed (the cause of your error).

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 ifs:

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);

1 comment

0

Sorry i can't give you a point, I am in the negetives... again

Variables

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

Functions

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.

Lighting

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.

Fix

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)

This discussion is preserved as it was. New answers, comments, and votes are closed.