I have a gameObject with both C# and JS scripts attached to it, and the C# script needs to access some variables in the JS script. I am not familiar with c# at all, but after reading some threads on the forum I managed to construct the below line of code:
VehicleBuggy vehicle = gameObject.GetComponent(typeof(VehicleBuggy)) as VehicleBuggy;
Unfortunately, the above line (and as many variations on it as I could think of), throw a “The type or namespace could not be found. Are you missing a using directive or an assembly reference?” error in Unity.
I am sure that I am missing something, but I haven’t figured out exactly what it is yet. Anyone else know?
Unity has different compile steps, most notably the scripts in the Standard Assets folder that get compiled first and all scripts in the Assets folder that get compiled afterwards.
This is important for two reasons:
If you change a script, not only that script but most others will get recompiled too. Since there are different compile steps, moving scripts between them can reduce compile time.
Scripts inside a single step can’t access scripts of another language in the same step. To do so, the script that is being accessed has to be in a earlier step.
This is because inside a single step, when the JS, Boo or C# compilers are compiling their scripts, they don’t yet have the result of the other compilers and can’t know what scripts they will compile. If one script is moved a step above, then the compilers in the steps below will have the generalized .net/mono code they understand and know what classes are available.
It’s not always so simple to move scripts, though. There can be dependencies that break if a single script is moved because scripts in early compile steps can’t know what scripts later steps will compile.
Thought I think thats kind of strange behavior, to have a “c++ makefile” like build order … Does Unity use some kind of hidden namespacing that causes that or the like?
(I only use one scripting language so I most likely won’t see this problem but understanding where the behavior comes from will surely help)
Well, I believe that this is a limitation of the design of .net/mono.
Each language provides their own compiler, that compiles the source to CIL (Common Intermediate Language) bytecode. That bytecode is the actual application and is converted at runtime to the native code of the operating system using a JIT compiler.
The mixing of different languages in Unity is possible, because each compiler understands the CIL language and thus can figure out what classes/methods/properties/etc are defined in (compiled) scripts of other languages.*
At the compilation step of Unity however, the scripts are not yet available in CIL bytecode and the compilers cannot know what scripts of other languages contain.
This is why (I guess) Unity has multiple compile steps. The first step produces CIL bytecode that all compilers can use in the second step. Only this way it’s possible to mix the three languages. Otherwise they could all interact with unity but couldn’t interact with each other.
There’s also the Common Language Infrastructure that makes sure that the design of all languages interpolate.
I assumed that they get converted to a “common” language or similar before the actual CIL bytecode step to be able to merge them into the same namespace and interact with each other nicely and friendly. Or if not, that it has some kind of multipass compiler to make them aware of each other by changing the compile order so that all the permutations (6) are done in case a script was not compileable (perhaps some clever decision making basing on the type of the scripts that did not work) and in the end all scripts should compile fine against each other.
I am very surprised that something as important as the compilation priority of various scripts would be left to something as ambiguous as folder names. Personally, I think it would make a lot more sense if each script object had a dropdown parameter for it’s compilation priority in the inspector. Nonetheless, deorganizing my script folders did appear to get me closer to a solution. The new error given is: “A field initializer cannot reference the nonstatic field, method, or property ‘UnityEngine.GameObject.GetComponent(System.Type)’”
i could be completely missing the point of your issue… but i had a similar error over the weekend.
the problem was being caused by me referencing instances of GameObject and NetworkView from a static function, which Unity didn’t seem to like me doing.
so if you’re running this code from inside a static function, that could be the issue. or i could be totally wrong. one of the two…
@Nekharoth:
Thanks! I wasn’t running the code inside of a static function, but it was a good thought.
I finally figured out a way to avoid needing to communicate between C# and JS, but I believe this was a good discussion and I definitely learned from it. If anyone has any other ideas about the “nonstatic” error, I would be interested in hearing them though.
Maybe your are trying to use GetComponent in a field/variable declaration?
class Example {
// This is not possible since Unity is not ready at this time this is executed.
var myField = GetComponent(MyType);
var myOtherField;
function Start() {
// Here we're ready
myOtherField = GetComponent(MyType);
}
}