Hi all,
I’m contemplating moving my code to C#. I had problems accessing a class I built in separate file. I’m guessing that I should be using the Using statement, but where do I say the class is?
I have all my scripts in a folder marked Scripts in the Project pane and I have the class script attached to the GO in question “Assembly Area”
Any tips or points would be appreciated,
Joe
Is this the same question in the following link? http://forum.unity3d.com/threads/72851-Call-Funtion-or-get-Variables-form-another-Script-(-C-)
There are different ways to access a class depending how you wrote your class. For example, component class which inherits MonoBehaviour and pure class which inherits Object or ScriptableObject. For the component class, you can use GetComponent which is similar to the above link.
It doesn’t matter where the script is, and you don’t need a using statement unless the class is in a namespace (the class is wrapped like so: namespace my_namespace { } )
You cant access MonoBehaviour derived classes which are in a namespace so it’s best only to use namespaces for utility classes (those that don’t derive from Unity-specific types)
I am using SelectList from the Wiki, though I simplified it and made it into a class. I need to call it from Javascript.
using UnityEngine;
using System.Collections;
public class SelectList : MonoBehaviour {
public static object List ( ICollection list, object selected, GUIStyle defaultStyle, GUIStyle selectedStyle )
{
foreach( object item in list )
{
if( GUILayout.Button( item.ToString(), ( selected == item ) ? selectedStyle : defaultStyle ) )
{
if( selected == item )
// Clicked an already selected item. Deselect.
{
selected = null;
}
else
{
selected = item;
}
}
}
return selected;
}
}
My JS code to call currently is:
var sl = GetComponent(SelectList);
currentSelection = sl.List( spacecraftList, currentSelection, GUI.skin.GetStyle( "Button" ), GUI.skin.GetStyle( "Label" ) );
I’ve also tried:
GetComponent(SelectList).List( spacecraftList, currentSelection, GUI.skin.GetStyle( "Button" ), GUI.skin.GetStyle( "Label" ) );
The code is in SelectList.cs and is a component of the same GO as the js calling code.
I keep getting:
What am I doing wrong?
Thanks
Joe
I don’t know Java Script very well but in C# it would be:
SelectList sl = GetComponent<SelectList>();
But that would only work if both scripts are attached to the same object. If the SelectList script is attached to a different object, then you need a reference to that object to call GetComponent on. Eg:
SelectList sl = slObject.GetComponent<SelectList>();
Right,
var sl = GetComponent(SelectList); is the equivalent of your C# line:
SelectList sl = GetComponent();
And that’s the line it fails on. Even thought SelectList.cs is a component of the same game object as AssemblyArea.js is.
The other thing you could try is (sorry my js is poor so I’ll write in C# and you’ll have to change):
public SelectList sl;
Then in the inspector for your game object, you should see an sl variable appear. Drag and drop the SelectList script onto it. Now in your other script you can reference sl.
I do this when I have 2 C# scripts attached to the same GO, and I need to reference one from the other. I don’t know if it will work cross language though.
Actually, it turns out to be the dreaded compilation order issue. Put the C# script in Standard Assets and bang, it works.
Thanks to all for the help and pointers!!!
Joe
Creating this C# class:
using UnityEngine;
using System.Collections;
public class AssemblyArea : MonoBehaviour {
public GameObject spacecraftPrefab;
public GameObject spacecraft;
public SpacecraftClass spacecraftClass;
}
and I get
SpacecraftClass is a js-based class, that is based on another js class which is based on MonoBehaviour. It is not a component of the same GameObject, but is a component of the spacecraftPrefab GameObject and I dragged that into the inspector.
So, what would I have to do to make the C# class know about SpacecraftClass?
As always, thanks!
I guess the real question is what namespace would I use?
I’m not sure why you need to have:
public SpacecraftClass spacecraftClass;
You already have a reference to the prefab. Can’t you just instantiate the prefab then call GetComponent() on the instance?
Yeah, but I cannot even get that far because the above error is choking on this line:
public SpacecraftClass spacecraftClass;
It can’t seem to find “SpacecraftClass” in the declaration. I can’t create an instance if I can’t create the variable, right?
I am soo dense today…
No I mean create an instance of the prefab, then access the prefab’s ‘SpacecraftClass’ script:
public class AssemblyArea : MonoBehaviour {
public GameObject spacecraftPrefab;
public GameObject spacecraft;
GameObject myInstance = Instantiate(spacecraftPrefab, spawnPos, Quaternion.identity);
SpacecraftClass sc = myInstance.GetComponent<SpacecraftClass>();
}
Still chokes on:
It doesn’t know what SpacecraftClass is. So it cannot get a component called SpacecraftClass. So it would seem any way.
I’ll keep digging, but I appreciate the ideas…
Sounds like the same issue you were having before, with the compile order. Your scripts should be able to recognise any other script in your Unity project.
I tried the C# files in the Standard Asset folder, Same issue. Really odd.
Sounds like this is your issue: Unity - Scripting API:
In this case, your SpacecraftClass (JavaScript) needs to be in the “Standard Assets”, or “Pro Standard Assets”, or “Plugins” (preferred) folder. Your C# AssemblyArea class must be outside those folders I believe.
In your first code example you seem to be calling a static method from an instance of the class: sl.List(…)
You don’t need to create an instance, you can simply call the method like so: SelectList.ListI(…)
Although you still probably need to put everything in the right folders to get it working… I’ve never ran in to any problems with .cs files having to be in specific folders… another reason to avoid Unity’s “Javascript”.
On a side note:
I don’t know who wrote that SelectList class but it’s not really a good idea to name a method “List” when C# has the List<> type. It would become even more confusing if you improved the function by making it generic so you wouldn’t have to cast the returned object.
It wasn’t that way originally. I was trying various things and I call it Display or something else now.
Swapping the C# and JS scripts worked. I’m going to work on converting everything to C#, but at least I can work on this one piece of functionality in C#.
Thanks to all!