The learning curve of scripting in Unity 3D is steep to me…
I would like to have a public Javascript which can be accessed by other Javascripts. As far as I have found out I have to create an empty object in Hierarchy window and then attach my public script to it. I call my empty object “GridHolder” and the attached script is called “GameGrid” (for whatever reason I have to act this way). All well so far…
Now I would like to call the function setGrid() and set variables someGlobal of the attached script “GameGrid”. I tried many things:
print (GameGrid.someGlobal);
=> Works fine if someGlobal is static so variable problem is solved (hope that works in iPhone that way too)
GridHolder.GameGrid.setGrid();
=> No way: BCE0005: Unknown Identifier: ‘Gridholder’
=> Making the setGrid() public inside the script (public function setGrid()) doesnt help either: “An instance of type ‘GameGrid’ is required to access non static member ‘setGrid’.”
Why the hell do I need to instantiate the public function but not the public variable???
Another try based on a GetComponent example of Unity’s reference:
var someObject : GameObject;
…
someO= someObject.Find(“GridHolder”);
print("someObject name: " + someO.name);
someO.GetComponent(GameGrid).setGrid();
=> Works fine up to the print (name) but an error by the third line: “NullReferenceException: Object reference not set to an instance of an object”
Great, great, last example I found in Unity’s reference list to make it working:
var script : GameObject;
…
script = GetComponent(GameGrid); // from Project window
script.setGrid();
=> Surprise, surprise, doesn’t work either: “BCE0019: ‘setGrid’ is not a member of ‘UnityEngine.GameObject’.”
I have no idea left what else I could try and I’m confused all those examples from Unity 3D official reference are not working.
Ok, first, if the name isn’t 100% a perfect match to the text you’re looking for with Find(), it’ll return a null object which is causing your null reference exception. Second, GameObject is a container for an object, not a script. GetComponent will return a script variable, so you can’t set GameObject = to it. Third, referring to your first problem, you can’t call a GameObject by using its name. It’s not something you’ve created a variable for.
What you need to do is tag your special script “SpecialScript” or something and do this:
var scriptLink : GameGrid;
function Start()
{
scriptLink = GameObject.FindWithTag("SpecialScript").GetComponent("GameGrid");
scriptLink.SetGrid();
}
The above will only work if the object with the script on it is tagged SpecialScript and active, just so you know. If you tag it something else, replace the word in the quotes inside FindWithTag.
Thanks for your quick answer! In between I somehow sorted it out: my function “setGrid” had an error itself bringing all the time the error not caling it.
But one question still is left:
I need my script always public. I have it now attached to an empty object inside the HIERARCHY window and its working.
Is there a way (and does it make sense) not to attach it to an empty object, so the script remains in PROJECT (asset) window? If that is possible, how do I call a function of that script?
That’s an interesting question. My first impulse is to say no, though. If there is, I haven’t seen anyone talk about it or demonstrate it, and I’ve not managed to do it either.
You can do that actually. But if it is a monobehaviour it still requires a game object to be assigned to.
If it isn’t you can just create a new object instance through new MyClass(); and store it in a global script (bad approach) or actually make all static or create a singleton class if you only need a single one of it.
This works so I’m confused its not working that easy for functions inside that script.
However, I have now a working solution and will work with it.
Another thing now popped up to me. Is there a difference of:
GetComponent(“GameGrid”) and GetComponent(GameGrid)
=> Is there a difference here of using quotation marks?
The quotation marks change the way GetComponent searches for a component. I don’t know the exact details, but it’s supposedly a little slower. However, I’ve never run into it failing to recognize the script type when using the quotes, while I have run into it failing to recognize the script type when not using quotes.
I think the confusion with this is that people believe string comparisons work characterwise like the strcmp function in the C standard library. In fact strings are interned in .NET, so a string comparison is just a pointer comparison and therefore very fast.
There’s actually almost no difference at all in terms of performance between the quoted version and the non-quoted version.
The most significant difference is that without quotes, the component type is checked when the script is compiled, so any errors in it will be picked up before run-time (eg, if you had a typo in the component name). This is generally a good thing.
With quotes, the component type is only checked when that line is executed, so you’re more likely to end up with null reference errors if you made a typo.
Your broader problem seems to stem from a general misunderstanding of the terms ‘public’, ‘private’, ‘static’ and ‘non-static’.
Public and Private are mutually exclusive. Variables or functions can be Public or Private (there are other modes but for simplicity in Unity you only really need to know these two). Public means ‘accessible from other scripts’.
Public and Private do not have anything to do with whether you need to create an instance or not.
Now, in addition to being either Public or Private, variables and functions can also either be ‘Static’ or ‘Non-Static’. These relate to instances.
Non-Static means the variable (or function) is unique for each instance of the script, and you need to have a reference to an instance of the script in order to be able to use them.
Static means that the variable (or function) is not attached to any particular instance. For static variables and functions, you work directly with the ‘script name’ as you have found.
So functions and variables are:
Either Public or Private and
Either Static or Non-Static
In Unity’s Javascript, functions and variables are ‘Public’ and ‘Non-Static’ by default (i.e. if you don’t specify otherwise).
For more information about accessing other objects in unity, see these links:
Thank you for making this so clear. You are absolutely right: Im not very familiar with this! I will keep that all in mind now, which makes sense to me that way.