- Home /
Does every c# class need to have its own script with the class' name?
Hey guys, could you please give me a hand? PLEASE DON'T BE AFRAID BY THE CODE, it is working :D.
The following code runs smoothly, but for it to work, I have to split each class into a separate c# file. The CreateInstance() refuses otherwise. The error it gives is: "there is no script with name (ClassOne)" or classTwo
So for it to work, I have to split them into three scripts and reload assets.
Question is: Can I have two classes in a same file, or c# needs each class to be in its own script with the same name as the class? Or is it a casting problem? Thank you! :D
//Say I have three classes. First one is a parent of the second one. The third class
//uses the first two to display it through an editor class window(not shown here).
//THIS CODE WORKS FINE :D
using System;
using System.Collections
using System.Generic.Collections;
using UnityEngine;
using UnityEditor;
[Serializable]
public class ClassOne : ScriptableObject{ //this is the base class, out of which 2nd class inherits
[SerializeField]
private int CO_int;
public void OnEnable(){
hideFlags = HideFlags.HideAndDontSave;
}
public virtual void OnGUI(){
CO_int = EditorGUILayout.IntSlider("Int Field", CO_int, 0, 10);
}
}
[Serializable]
public class ClassTwo : ClassOne{ //second class inherits from base class ClassOne
[SerializeField]
private float CT_float;
public override void OnGUI(){
base.OnGUI();
CT_float = EditorGUILayout.Slider("FloatField", CT_float, 0f, 10f);
}
}
[Serializable]
public class Central : ScriptableObject { //Third Class which uses first two in OnGUI function
[SerializeField]
private List<ClassOne> COandCT_instances;
public void OnEnable(){
if(COandCT_instances == null)
CoandCT_instances = new List<ClassOne>();
hideFlags = HideFlags.HideAndDontSave;
}
public void OnGUI(){
foreach(var instance in COandCT_instances)
instance.OnGUI();
if(GUILayout.Button("Add ClassOne"))
COandCT_instances.Add(CreateInstance<ClassOne>());
else if(GUILayout.Button("Add ClassTwo"))
COandCt_instances.Add((CreateInstance<ClassTwo>());
}
}
Answer by softrare · Jul 22, 2013 at 02:56 PM
Yes they have to be in seperate files, which also increases project hierarchy maintainability.
There is still a way to bury multiple classes in one parent class but it can only be done if you dont want to expose the child classes to the rest of the project.
class X {
class Y {
}
class Z {
}
}
Y and Z can be exposed, if you add public. Then anyone can declare: X.Y someY;
It's really just a na$$anonymous$$g convention. If you have a class $$anonymous$$achine, with several "Parts," then you could make a regular class named Part or $$anonymous$$achinePart. Or could make a nested class Part. In the last case, everyone else calls it $$anonymous$$achine.Part
, while you can use just "Part."
If two people want a slightly different Part class, they might make normal $$anonymous$$achinePart and normal TreePart. Or each declare their own nested Part class (external names would be $$anonymous$$achine.Part and Tree.Part.) Being able to reuse the name that way is kind of fun.
The one difference in nested classes is that Y and Z can use constants (and statics?) from X. That might be "bad design," but it can come in handy.
Answer by Owen-Reynolds · Jul 22, 2013 at 03:47 PM
Multiple classes in a single file works just fine, if you use normal C# to make them.
For example, Cat_t c1 = new Cat_t(); Dog_t[] D = new Dog_t[12];
works just fine, and can have Cat_t and Dog_t declared together in a file (named animalsTypes?)
But, as noted above, Unity magic (adding classes as Components, and I assume CreateInstance [have never used it]) requires the class be alone in a file, with the same name. I'd say that anytime you aren't performing the new and maintaining your own var/pointer, you probably need to follow Unity's class rules.
ScriptableObjects stored as assets need to have their class in separate files (of corresponding names) as well. The serialization mechanism seems to identify classes by path...
Answer by gardian06 · Aug 02, 2013 at 10:18 PM
only MonoBehavior, ScriptableObject, and the children of either MUST have their own files, but any class that starts at .Net.object can all exist in the same file if you would like.
EditorWindow!
Anything that derives from UnityEngine.Object needs its own file, anything that derives from System.Object can be wherever.
Is NetworkBehaviour lumped in to this category as well?
Yes. Since NetworkBehaviour is derived from $$anonymous$$onoBehaviour the same rules apply.
Actually only classes which represent concrete classes need to be inside their own file with matching filename. So if you have a baseclass that is derived from $$anonymous$$onoBehaviour and you only use classes that are derived from that baseclass, the baseclass doesn't need to be in it's own file. However the derived classes have to.
We could summarize the rules like this:
A class need to be in a file with matching filename if those two rules apply:
the class is indirectly derived from UnityEngine.Object. That includes any deeper derived classes as well. So classes derived from $$anonymous$$onoBehaviour or ScriptableObject. The same applies to editor classes. The Editor class as well as the EditorWindow class are actually derived from ScriptableObject.
the class is ment to be instantiated. Classes which serve only as (abstract) baseclass don't need to be in their own file.
So pure base classes could be included in a different file. You can also include as many .NET classes within a $$anonymous$$onoBehaviour / ScriptableObject file as you like as long as the two rules don't apply for that classes.
Even though it's possible to include other classes within the same file, it should only be used when the classes actually belong together and those additional files are mainly / only used by other classes in the same file. So they represent some kind of package. In most cases it's better to place every class in it's own file. That makes it easier to find a certain class within the project.
Why?!?
Classes derived from UnityEngine.Object always represent assets. Assets can be serialized inside the editor. The serialization system links those classes to $$anonymous$$onoScript instances in the editor. A $$anonymous$$onoScript represents the scriptfile-asset itself and the underlying class has to match the filename. A scriptfile can only represent one class from the editor point of view.
Answer by Arsonistic · Jan 22, 2019 at 11:58 PM
Only classes deriving from MonoBehaviour and ScriptableObject need to be alone in script files.
C# Object-derived classes do not need to be put in separate files and can be added to the same file as a MonoBehaviour/ScriptableObject.
Putting ScriptableObject classes in the same file as other ScriptableObjects or a MonoBehavior will work in the editor, BUT WILL BREAK IN BUILDS.
Your answer
Follow this Question
Related Questions
Can't get script to access other script/class (c#) 1 Answer
c# - void method from external class. 2 Answers
Distribute terrain in zones 3 Answers
Set default length for an array of elements of a custom class in inspector 0 Answers
If there is only 1 instance of a class, should it be Static? - C# 2 Answers