- Home /
How can I reference/import one C# script from another?
Umm, this time I'm going to start with some background.
I come from a Python background, and when working on a large project, you'll break it up into files, I often do one per major class, and import them back into my main file. For example:
from assets.scripts.classes import controller, settings
from assets.scripts.functions import logging
class GameController():
myController = controller.Controller()
mySettings = settings.Settings()
logging.log("Everything is fine and dandy")
Now, those import scripts are simply living on disk in /assets/scripts/classes/controller.py etc, and they get loaded at run or compile time.
Now, in Unity/C#, the only way I can see to replicate this behaviour, is to create dummy GameObjects in my scene, attach the scripts to them, and then access these GameObjects/scripts from my main script using
Classes = GameObject.Find("Classes")
myController = Classes.GetComponent(Controller).Controller()
But, is this really the "right" way to do it?
Any feedback on how you guys are writing scripts like this would be really fantastic
Thanks Dave
Answer by whydoidoit · Feb 27, 2013 at 08:28 AM
Well the classes are available from anywhere within the same namespace - so you don't need to import them as you do in Python.
What you need is a way of accessing the variables of those classes or the instances of the classes attached to another object. You have a few choices (Unity Gems has a number of articles we wrote on this).
You can:
Add static singleton variables to your classes to access a singleton component (perhaps Controller is like this).
Use GetComponent to access the components on another object (probably not for singletons)
Use the inspector to assign references to the other components that exist between individual objects
There are other methods when you are coding for collisions etc, but those are the primaries.
This ^
Using Find methods to get objects is slow, but is an option also. But the "correct" way is what @whydoidoit suggests. Note that GetComponent is relatively slow, so its a good idea to cache the result if its an object you will use a lot.
Aah, that's awesome, thanks a lot whydoidoit!
Reading your answer, I think it's become more clear that I need to change my way of thinking, rather than replicating the behaviour from another language.
And that link looks fantastic, will be good for some weekend reading :)
And thanks Tarlius, I'll definitely be caching these :)
Another big deal about the unity way, is how it deals with Resources. Although again, you can use the traditional way if you prefer for most things.
The "Unity Way" tends to be the fastest way, and thats what Unity is mostly about. Letting us do annoying things more quickly so we can spend more time doing interesting things (game logic). But if you want to do more complicated things, Unity can usually accommodate that too (although the way is less well-trodded, so expect more headaches)
Answer by Tarlius · Feb 27, 2013 at 09:26 AM
It is probably worth mentioning that you don't need to attach things to GameObjects though. You can use regular C# classes too, by not inheriting from MonoBehaviour (which will let you use constructers/etc as per "normal" C#).
I personally prefer to have "dummy" GameObjects in the scene that I can tweak visually, but it is an option. The main bonus of doing it the Unity way is that Unity will save all the public and Serialised values for you, which makes initialisation much easier, as well as all the editor extensions/inspector/etc.
Obviously, if you don't use MonoBehaviour you also won't benefit from/(be cursed by?) the Awake() Start() OnEnable() etc model, and you also will not be able to StartCoroutine without a reference to a MonoBehaviour to start one on (although you might be able to use threads for some behaviour, although a lot Unity functionality is not thread-safe which will limit what you can do)
Edit: All values was a lie. It will save the ones it knows how to Serialise, which is not "all". You can't do more complex datatypes, but Arrays (of supported types), instances of [Serialisable] custom classes, most primatives, and most structs (Vector2/3, etc) will work.