- Home /
Are namespaces supported in Unity 4?
So apparently MonoBehaviours should be able to be in a namespace in U4. However, I get a lot of warnings about the "The class defined in script file 'x' does not match the filename" - is there something I can do about this?
EDIT: Just to be clear
The warning only happens if the class is in a namespace
With the namespace:
Without the namespace:
The code (with the namespace):
Here's the code:
using System;
using UnityEngine;
namespace RadicalLibrary
{
public class ActivatedObject : StateMachineBehaviour, IMessage, IAmActivated
{
public string message;
public string activatedMessage;
public string Name = "Take 001";
public bool touchEnabled = true;
public float Speed = 1;
private StateMachine _sm;
public GameObject targetObject;
public bool IsActivated()
{
return Activated;
}
private bool _activated;
public bool Activated {
get {
return _activated;
}
set {
_activated = value;
var go = targetObject == null ? gameObject : targetObject;
if (!String.IsNullOrEmpty (Name)) {
if (value) {
go.animation [Name].speed = Speed;
go.animation.Play (Name);
} else {
if (go.animation [Name].time == 0) {
go.animation [Name].time = go.animation [Name].length;
}
go.animation [Name].speed = -Speed;
go.animation.Play (Name);
}
}
}
}
void TouchActivated()
{
Activated = !Activated;
}
#region IMessage implementation
public string GetMessage ()
{
return Activated ? activatedMessage : message;
}
#endregion
}
public class WaitForRelease : State
{
private Action _action;
public WaitForRelease (Action actionOnRelease = null)
{
_action = actionOnRelease;
}
public override void OnUpdate ()
{
if (TouchInterface.TouchCount == 0) {
SetState (StateMachine.Inactive);
if (_action != null) {
_action ();
}
}
}
}
}
Ugh I've totally messed this question up trying to fiddle with it, apologies!!! :S
So YES there are two classes in that file (I can't actually read my own indentation, WaitForRelease is supposed to be a child class of ActivatedObject).
If there are two classes in a file then it works fine without a namespace
If there are two classes in a file then putting them both in a namespace fails
If I put WaitForRelease as a child of ActivatedObject it works fine
If the people who were answering/helping on this would like to post answers again - I can tick and upvote where necessary! Thanks!
Argh, I'm still getting comment notifications on an answer which (for me at least) is invisible! @doug__ if you can "see" your answer can you make sure that it is undeleted? Otherwise could you post it again.
@Shrandis & @$$anonymous$$arkFinn - I've also lost your comments - I'm having a bad morning in all respects!
I haven't said much other than making a pun about this interesting behavior and asking if it was possible that you are getting a warning because you have 2 classes in a single file (which means one of them obviously doesn't match the file name)
So, reading your new comment, is the conclusion "we cannot have 2 same-level classes in a namespace in the same file" ?
Yes that is it exactly... 2 classes are fine with no namespace, but broken when there is one.
Answer by Philipp · Jan 08, 2013 at 02:57 PM
Here's one more that took us a long time to figure out: MonoBehaviours inside namespaces break, if they have a method with a default parameter (such as public void Foo(bool bar=true)).
Oh man, thanks for that! This one was killing me to the point where I gave up on namespaces for my monobehaviour derived classes and made sure they all had a company-specific name prefix to avoid collisions with middleware.
This is the same issue I found myself. I have posted this as a bug to the Unity $$anonymous$$m.
Amazing. Just changed a bunch of stuff and got this error -- never thought to check the default parameter. Crazy. Thanks for spotting this!
Answer by KyleStaves · Jan 04, 2013 at 04:54 PM
I just wanted to add that anything can break it; I had an enum in one of mine driving me crazy trying to fix.
One more thing, [ExecuteInEditMode] breaks the class as well - I wouldn't be surprised if other, similar flags break things.
Good points - and also I noticed that ScriptableObject behaviour in namespaces is dubious - can't quite work out what the rules are yet - but I had to move some out (but not all).
Also, I noticed that the object picker doesn't work with ScriptableObject in namespaces (the object selection window you get when you use EditorGUI.ObjectField() for instance)
Very annoying that, having to write my own right now...
Answer by whydoidoit · Dec 11, 2012 at 09:53 AM
Here's the answer:
If there are two classes in a file then it works fine without a namespace
If there are two classes in a file then putting them both in a namespace fails
If, in the example, I put WaitForRelease as a child of ActivatedObject it works fine, so nested classes work
If the class has methods with default parameters it fails [Added due to answer below]
I too am having this problem. Some $$anonymous$$onoBehaviour-derived classes inside of namespaces seem to work fine, while others do not.
Have you made sure that there is only one class definition of any kind inside the file with the namespaced $$anonymous$$onoBehaviour - that fixed it for me...
@whydoidoit: can you update the answer of this to say it is the one below. The default parameter is the real culprit in this case.
Answer by vexe · May 18, 2014 at 10:42 PM
So for me it wasn't just default params, but also named params! (i.e. namespaces AND named params - if you use either one alone you shouldn't have problems)
This will fail:
namespace MyNamespace
{
public class Settings : ScriptableObject
{
public static void IntMethod(int x) { }
public static void Test()
{
IntMethod(@x: 10); // <-- Named param
}
}
}
// Somewhere else...
Debug.Log(ScriptableObject.CreateInstance<Settings>()); // prints "()"
This will succeed:
namespace MyNamespace
{
public class Settings : ScriptableObject
{
public static void IntMethod(int x) { }
public static void Test()
{
IntMethod(10); // <-- Pass arg normally
}
}
}
// Somewhere else...
Debug.Log(ScriptableObject.CreateInstance<Settings>()); // prints a valid value
Answer by SonicBloomEric · Jul 13, 2015 at 01:40 PM
What Works (4.5.5+)
I came across this issue in testing with versions of Unity between 4.5.5 and 5.1.1. It seems that the following are no longer limitations (in at least 4.5.5+):
Two classes in the same file, both within a namespace.Having a method with a default parameter within theMonoBehaviour
/ScriptableObject
subclass that's in a namespace.
I have not tested with named parameters and therefore cannot speak to them.
What Doesn't Work (as late as 5.1.1)
However, I did run afoul of an issue with namespaces and MonoBehaviour
s/ScriptableObject
s. The following WILL NOT WORK:
A non-
MonoBehaviour
/ScriptableObject
class that has a method with a default parameter appears before theMonoBehaviour
/ScriptableObject
subclass in the script file.
The following examples are expected to be in a file called TestClass.cs
.
Works: No Namespaces
The SupportClass is simply a wrapper for an int
. This works.
using UnityEngine;
[System.Serializable]
public class SupportClass
{
public int anInt;
public void SetTheInt(int i = 1)
{
anInt = i;
}
}
public class TestClass : MonoBehaviour
{
public SupportClass someVal;
public int TestMethod(int i = 1)
{
return i;
}
}
Doesn't Work: Add a Namespace
Both classes are within the namespace.
using UnityEngine;
namespace TestNamespace
{
[System.Serializable]
public class SupportClass
{
public int anInt;
public void SetTheInt(int i = 1)
{
anInt = i;
}
}
public class TestClass : MonoBehaviour
{
public SupportClass someVal;
public int TestMethod(int i = 1)
{
return i;
}
}
}
Works: Reorder Classes Within the Namespace
Simply changing the order of the classes causes this to work again.
using UnityEngine;
namespace TestNamespace
{
public class TestClass : MonoBehaviour
{
public SupportClass someVal;
public int TestMethod(int i = 1)
{
return i;
}
}
[System.Serializable]
public class SupportClass
{
public int anInt;
public void SetTheInt(int i = 1)
{
anInt = i;
}
}
}
Works: Remove the Default Parameter from the Support Class
Simply removing the default parameter from the support class when it appears first, also fixes the problem.
using UnityEngine;
namespace TestNamespace
{
[System.Serializable]
public class SupportClass
{
public int anInt;
public void SetTheInt(int i)
{
anInt = i;
}
}
public class TestClass : MonoBehaviour
{
public SupportClass someVal;
public int TestMethod(int i = 1)
{
return i;
}
}
Final Note
You can have multiple support classes defined before the MonoBehaviour
/ScriptableObject
subclass. This will work 100% fine until you add a default parameter to any method in any support class that appears in the script file before the MonoBehaviour
/ScriptableObject
subclass. In fact, if you have multiple support classes, you can put those without default parameters in their methods before the MonoBehaviour
/ScriptableObject
subclass and those with them after. This also works fine.
Wow a very detailed answer! I was a bit unsure of what works and doesn't with namespaces these days, thanks for clearing it up for me!
Your answer
Follow this Question
Related Questions
XML Serialization problem 0 Answers
Adding a script to a prefab 1 Answer
Get Monobehaviour play mode instance from editor instance 0 Answers
Leaves, Branches disappear in viewport on Tree Creator Object 1 Answer
Does the Shuriken Particle System in Unity 4 not allow particles to render prior to collision? 1 Answer