Hi, I guess I am asking a silly question, but I really want to know the answer.
I was thinking it should be a public function, as I suppose it should allow others to access it, like some collision manager:
XCollisionManager
for (var g : gameObjects) {
if (isCollided(g)) {
g.OnCollisionEnter();
}
}
Does anyone know how it was called, and help me picture why private function works?
And I also have a question about which place declare such function. I search around through the inherit tree, I could not find it through Visual studio.
Unity has special access to this. Itâs the one in the Monobehaviour that you define thatâs actually called and it doesnât matter if you define it private or not.
Theyâre your scripts, you can call whatever you like. Make them public if you like.
You wonât have the relevant arguments to pass though so itâs unclear what youâre trying to do here.
To clarify a little further, this is one example of what are known as âmagic methodsâ. They arenât public because Unity isnât accessing them the way one typically would via a standard function call. Instead, itâs using something known as reflection to effectively scan any datatypes in your project that derive from MonoBehaviour for these specific methods so that it can invoke them indirectly. There are plenty of good arguments to be made about why this is not a great design but at the time Unity was created it probably made sense from an accessibility point of view so here we are twenty years later.
Iâm not sure what you expect this to do that would be constructive though? Why not just make your own function and call it? Itâs not like calling OnCollisionEnter is going to cause a collision or something.
Usually when you want some kind of events / callbacks that can be called on your own class, you would define them in the base class as a virtual or abstract method and have your own class override those methods so whatever system (Unity) would simply call the method on the base class and your own implementation would be called. Of course an abstract method would require the derived class to implement this method while a virtual method doesnât need to be overridded.
This is generally called polymorphism and as a design pattern related to the Strategy pattern. This is usually a great way to allow polymorphic code / behaviour in a system. Such methods are usually declared protected or public, depending on who / which system will call those methods.
However when you look at the MonoBehaviour class, it doesnât implement any virtual or abstract methods. As it was already mentioned, Unity essentially uses âmagic methodsâ that the engine will call directly.from the C++ core. One of the main reasons is optimisation. Calling the method directly from C++ has very little to no overhead compared to pure managed code reflection. Also Unity has additional optimisations as it analyses and checks the class which magic method are implemented and doesnât even try to call methods that donât exist in the class. Given the number of potential callbacks / âmessagesâ this is a huge improvement as an empty MonoBehaviour class has almost no overhead. So always remove empty magic methods when you donât need them. Just having an empty Update method in a class will subscribe every class instance of this class to the update cycle and causes overhead.
Since the methods are called from outside the managed C# environment, the access modifies are pretty irrelevant. Itâs generally good practice to declare magic methods private or at least protected (never public) since those methods should never be called manually. They are invoked by Unity. You would declare them protected when you want to have further subclasses of that class and override the method.
Interesting, I always assumed it was just reflected at creation and then marshaled across to something the C+±side could store and access later. I guess if you are already doing the heavy lifting on the C+±side though that kinda makes sense. Iâm probably thinking too much in terms of user-code rather than engine code due to my experience.