- Home /
Probably Dumb Question: Update(), Start(), etc. Don't Work Inside Classes (JavaScript)...?
I fully expect that this is simply because I've never tried to put Update() or Start() inside of one of my own classes before. There is probably some simple thing I'm missing. I have, however, worked fairly extensively with classes for a while now - I've just never tried to do this.
I have the following code:
#pragma strict
public class test1 {
public function test1() {
// Stuff
}
public function Start() {
// Stuff, including a Debug.Log()
}
public function Update() {
// Stuff, including a Debug.Log()
}
}
public static class test2 {
public function Start() {
// Stuff, including a Debug.Log()
}
public function Update() {
// Stuff, including a Debug.Log()
}
}
function Start() {
new test1();
}
I have placed the script on a GameObject in the scene. None of the Debug.Log()s from the Start()s and Update()s are showing up. To my understanding, both test1 and test2 inherit from MonoBehaviour, which means they should automatically run these types of functions. But am I wrong? Do I really have to call them from a script's Update, Start, Awake, etc. functions manually?
I tried to find this question on the internet, because I'm sure it's common, but Google doesn't like me today. Feel free to link if you can find an existing answer.
PS: This is probably a related issue in my understanding. If I try to have a script that only has #pragma strict followed by a single class (no functions or variables outside the class), Unity won't recognize the script as a resource. Is that normal? This is Unity 4.6.x.
Answer by meat5000 · Oct 05, 2015 at 10:19 AM
Whats that random extra Start at the end?
It shouldnt be there. Also, your classes dont derive from MonoBehaviour as you dont implement/extend it. This is why your Mono functions are not running.
public class test1 extends MonoBehaviour
{
}
Another thing that doesn't make UnityScript an easier language ^^, UnityScript hides the fact that each script file becomes automatically a class derived from $$anonymous$$onoBehaviour with the name of the script file. So when you declare other classes inside the script (which aren't $$anonymous$$onoBehaviours or have other names) they are simply nested classes. You still get the automatically created class which however is empty in that case.
To me it almost looks like he deliberately uses nested classes and actually did not want them to be $$anonymous$$onoBehaviours in the first place since he creates an instance with "new". $$anonymous$$onoBehaviours can't be created with "new", only with AddComponent. I'm not sure why he thinks that an ordinary class that defines an Update method would have the method called somehow "automatically" ^^.
Also the instance created in the Start method (at the very bottom) will be up for garbage collection as soon as you leave Start since no reference is keeping it alive.
Indeed, I think it would make more sense if Unity gave us a Complete Template for a JS class ins$$anonymous$$d what we currently get.
In my first Unity days this would have baffled me for days, had I not been lucky enough to encounter this information by accident. Learning from scratch there is so much information to take it its difficult to get ones head around it all. Of course, once that part is done its difficult to remember a time when you didnt understand it :P
I had already tried the "extends $$anonymous$$onoBehaviour" addition, but it did not cause the Debug.Log()s to fire, either in Start() or in Update(). I will try something like var t : test1 = new test1(); to see if it was the garbage collection.
I was thinking they should work because I've seen several examples on Unity Answers where they appear to work like that.
The extra Start() is just a part of the normal script (I guess of the $$anonymous$$onoBehaviour that's created when you make a new UnityScript file.) It's not part of either class, and just serves to create an instance of test1 because test1 is not static.
I can't use AddComponent (I don't think), because there is no GameObject to which I want to attach these classes.
I will try some things based on your suggestions when I get home today.
because there is no GameObject to which I want to attach these classes
$$anonymous$$onoBehaviours will only run on an instance I do believe. This mean they must exist on a GameObject.
Just make an Empty Object if need be.
I would, but this is a fairly high-intensity application, and it is unfortunately not feasible to make 50,000+ GameObjects to attach them to. Not sure about adding 50,000+ instances of a $$anonymous$$onoBehavior to a single GameObject; that could be equally unfeasible. So if that's the way a $$anonymous$$onoBehaviour has to work, then I guess I'll just directly call the update functions from a single $$anonymous$$onoBehaviour, or some such. Fortunately, those 50,000 instances do not have update functions inside them; it's just a single instance of another class that does.
Answer by Bunny83 · Oct 06, 2015 at 10:52 AM
Well, if you need non MonoBehaviour classes (not attached to any gameobject) you have to call any methods in those classes yourself. Unity's won't automatically call any method of ordinary classes. Unity itself (the engine core) doesn't even know those class instances exist and doesn't really care about what classes you create on your own.
Classnames should always start with a capital letter. Here's an example in UnityScript:
public class Test1
{
public function Test1() {
Debug.Log("Test1::constructor");
}
public function Start() {
Debug.Log("Test1::Start")
}
public function Update() {
Debug.Log("Test1:Update");
}
}
var instances : Test1[];
function Start() {
instances = new Test1[3]; // array with 3 elements
for(var i = 0; i < instances.Length; i++)
{
instances[i] = new Test1(); // create 3 instances and store them in the array
instances[i].Start(); // call the Start method of each the new instance
}
}
function Update() {
for(var i = 0; i < instances.Length; i++)
{
// each Update of the MonoBehaviour we call the Update of our 3 instances
instances[i].Update();
}
}
When you create a "normal" class instance you have to store the reference that is returned by the constructor somewhere. If you don't you can't interact with your class. Furthermore Mono uses a garbage collector. So once there's no reference to an instance the object is automatically removed.
Note: Unity classes that are derived from UnityEngine.Object (like MonoBehaviour and others) have a native code counter part in the engine code (which is written in C++). Those instances are managed by the engine itself and you can use methods like FindObjectOfType to "regain" access to an instance since Unity internally manages those instances.
"Normal" classes are just plain .Net / Mono classes. They don't do anything on their own. Unity and the Unity editor can only work with classes derived from MonoBehaviour. Those are actual "assets" in the Unity sense. There's no problem putting your Test1 class into it's own file called "Test1.js". The class will still be available to your other classes. However as i said Unity can't do anything on it's own with them. The usage is completely up to you.
All right, that's basically what I figured. (In my case, I'd be using a List. for resizability, but it's the same thing.) Can I assume it works the same way for static classes as well? (Having to call, for instance, Test2.Update() from some $$anonymous$$onoBehaviour's Update() function, etc.) Luckily, I only really have to do it on a couple of static classes, and mostly only with their Start() functions.
About having the class in its own script, that's something I'd like to be able to do, but as I said above, Unity doesn't recognize the script anymore if it's solely the #pragma strict followed by imports and the class. Is that because the class isn't a $$anonymous$$onoBehaviour, causing Unity to think that nothing is there? (Putting an empty Start() or Update() function in there outside of the class fixes the issue; presumably, unity considers these (part of the $$anonymous$$onoBehaviour represented by the script) to be "something.") Alternatively, is it important that the filename be the same as the class, in the case of UnityScript, as you wrote above? (I know it is with C#.)
Thank you, everyone, for answering. It helps explain how and why a number of things work in Unity.
Well, i don't use UnityScript i only use C# ^^- In general no, the file name doesn't need to match the classname for non $$anonymous$$onobehaviour classes. However if you put each class into a seperate file you usually name it like the class it contains.
I guess the problem might be that UnityScript automatically turns each file into a $$anonymous$$onoBehaviour with the filename. I didn't really test out all the quirks of UnityScript since i don't use it. Ever ^^.
Is there any reason you stick with UnityScript? I mean the syntax is actually closer to C# than to actual JavaScript since it's also a .NET based language but with tons of little "gotchas" ^^.
Oh, just habit and existing projects of $$anonymous$$e with multiple thousands of lines of code I don't want to deal with converting. I probably should, and I'm restructuring a number of things now anyway, so I might.