How do I make member structs accessible in the editor?

Suppose I have a class Foo and some member data that I wish to encapsulate in a struct Bar, like so:

using UnityEngine;
using System.Collections;

public class Foo : MonoBehaviour
{	
	public struct Bar { public int a; public float b; }
	public Bar m_bar;
}

Is there a way for me to make the members of m_bar editable through the Inspector of Foo?

Hi, try putting [System.Serializable] before your struct :

using UnityEngine; 
using System.Collections; 

public class Foo : MonoBehaviour 
{  
   [System.Serializable]
   public struct Bar { public int a; public float b; } 
   public Bar m_bar; 
}

That way worked for me with classes, I think it should work with structs too.

–
oxl

17 Likes

That doesn’t appear to work for structs, but I can live with Bar being a class instead. Thanks!

Hm, thats odd. I wonder why it’s not possible to expose every type to the inspector. Byte turns out as a boolean for example.

–
oxl

Struct wasn’t visible in the editor, but a class worked fine. Thanks for the help.

Yeah, the [Serializable] attribute doesn’t work with structs; they can’t be viewed in the inspector or saved with the scene (AFAIK, at least).

I’m sure there’s a technical reason for this, but I’ll admit that I don’t know what it is. Since Unity’s own struct types (Vector3 and so on) serialize just fine, presumably there’s some way to do it.

It would definitely be useful to be able to serialize struct types in C#, but as far as I know this functionality isn’t available.

structs are by val, never by reference.

that reduces their use greatly.

stuff you intend to store within the editor are optimally extends of ScriptableObject

You can easily work with them and setdirty from custom editor will mark them for storage towards unity if you have them on a corresponding GO.

I’ve written a few task specific custom editors for levels, enemy templates and similar that use that approach and they work all fine :slight_smile: (and good thing is if you forget the editor you can always doubleclick them as they will appear in the editor and they show up in an own editor with their values, for example if you have them in an array of xxxx :slight_smile: that can be important for designers for example for fast changes etc)

No one said otherwise.

Not sure what you mean by this. How does making a type a value type reduce its usefulness?

What about classes that you intend to use within a class that inherits from Monobehaviour? Something like:

public class MyComponent : MonoBehaviour
{
    [Serializable]
    public class MyClass
    {
        // Stuff...
    }

    public MyClass myStuff;
}

I assume there’s nothing wrong with doing this?

Anyway, I’m curious as to why you think being able to serialize (custom) value types wouldn’t be useful. I know it would’ve been useful to me on more than one occasion, but maybe I’m missing something.

[Oops, this is an old thread…]

In this case a lot as the editor would have to dublicate it everytime it has to update that object as the interface would need to serialize / reflect it as it can not just hold a reference to it. And you would want a lot but not make the ram situation any worse than it gets with some reasonable amounts of media actually.

Don’t see anything wrong directly, but would explicitely extend it from System.Object there likely to prevent its rooting to UnityEngine.Object if you don’t intend to use any of the aspects from that end.

Not being able to expose custom structs in the editor (afaik) has been a recurrent annoyance for me too. Built-in structs such as matrices, vectors and quaternions are serialized properly, without that being a noticeable problem. I’m not sure I follow your serialization/reflection/RAM logic, though. Do you mind elaborating?

I might be wrong on that end, but to my understanding, you would want customeditor support too, otherwise the exposure would be halfbaken / nil baken and for custom editors to operate on it, they need to aquire a reference to it which with structs won’t go anywhere. to explain that better: I expect it to pass it between properties and real functions 1+ times, and each of that cases will result in a copy, every time the data is updated

Question is what are you using structs for, whats the direct benefit for you using by val and copying it on every passing on over having it as a class? (the only benefit I’m aware off is commonly avoiding cache misses when the cpu goes through the content of a struct, but anything that could be editor exposed can’t be large enough to trigger such a thing independent of class or struct likely)

it might also potentially be related to UnityScript which has no structs

How is this different from exposed custom classes? I don’t see why you need a reference to it rather than working directly with a copy/the value itself. I might not have thought this through thoroughly, though.

Structs are useful for small “container”-type value types that you copy around a lot, much like you would use a primitive like a float or int (which I guess is why they’re used for vectors and alike), and they are handy because they are copied on assignment so you don’t have to worry about copying each component manually or create copy constructors. There’s also the benefit of them not ending up on the heap for the garbage collector when using them in intermediate calculations.

You UnityScript argument seems valid, and that might be the reason :slight_smile:

Edit: Did you edit your post recently, or did I screw up when quoting? :slight_smile: Anyway, I think the main points still stand.

classes are by reference so passing around a class is a managed pointer, 4byte
passing around a struct is x bytes where x is the size of the struct.
You commonly don’t pass single values through the whole editor, it will work with the object and extract the values from that one.

if you naturally want them to copy around its an easy and performant way to do so :slight_smile:

Damn, you are quick on these forums, I should have guessed looking at your post count :smile:

I just wanted to add that there is the possibility of passing structs around using the “ref” keyword, in which case it will not result in a copy but a reference pass. I can’t help thinking that most structs are small enough to this not really being an issue. It would just be nice and handy with serializable/editor exposed structs at times, that’s all :slight_smile:

agreed, it would be nice if it “ate them all” given you don’t hang [Serializable()] in for a unityengine object in which case it will not work (as they are not serializable)

the ref is a valid point otherwise, but in this case its the same path both go, object and structs so unsure if ref would really solve more problems than it creates.

but in the end there are ways to achieve nearly everything aside of structs and generics at all in the editor (it was built around unity scripting and .net 1.1 logics a lot from what I’ve seen so far. the new gadgets etc from 2.5+ don’t change anything on that end)

To be clear, I’m sure there’s a good technical reason why serialization isn’t supported for structs. I don’t know how Unity’s serialization system works under the hood, so I wouldn’t presume to say that struct serialization should or should not be supported.

What I remain curious about though is how/why Unity’s own value types such as Vector3 are serializable. I’m guessing they’re just handled as a special case internally, and that whatever provisions are made for them can’t easily be extended to other custom value types.

I do have to question though the assertion that one should just use classes or that being able to serialize structs wouldn’t be useful. C# has both reference and value types for a reason (IMO), and both have their place.

I think the most effective way to make my argument might be to ask the following questions:

  1. Does it make sense that UnityEngine.Vector3 is a value type rather than a reference type?

  2. Is it useful to be able to serialize UnityEngine.Vector3?

If your answer to both of these questions is yes, then I’d think you’d have to concede that being able to serialize value types can be useful. (Again though, maybe I’m missing something.)

1 Like

Ack. I really needed to show a struct. I don’t want to send a reference to a target when it is hit by a weapon, I want to send a struct that holds the relevant information. I want to set this in the inspector though too…back to the drawing board.

Are you sure? I can’t think of a reason why you wouldn’t use a class. It hold relevant information just as much as a struct does. It sounds like you should use a class anyway; structs should be used for very simple data only (such as a Vector3).

I know this post is almost a year old, but it’s still wrong. :slight_smile: UnityScript has structs and has had them since before Unity 3; making a class extend System.ValueType makes it a struct. Kind of ugly (would be nice if you could just write “struct”), but it works fine.

–Eric

Yea, when I ran across this thread I was thinking the exact same thing, well said. The crucial difference is reference types require indirection, and indirection costs CPU. In the vast majority of cases, you shouldn’t concern yourself with that, but ‘vast majority’ is not the same as ‘all’, and in some cases the CPU cost of that indirection is substantial. The value types used by Unity are structs for a very good reason, and that’s that they are closer to ‘primitives’ than ‘classes’. They’re generally small, often put into arrays, and almost never would you want them to actually be reference based (vector3 for instance, you almost invariably want embedded). The idea that only Unity’s constructs are valid as structs is pretty naive, IMO. Note, Unity’s particles are also structs, far from a ‘small’ class by most standards, but it’s still a struct for good reason.

I’m pretty sure this is not a design choice by Unity, but a production choice, supporting this is likely just being out prioritized, for better or worse.

Necropost, but still a current issue (as of Unity 4.3.1).

Structs are undeniably useful. One thing you can do with structs that you can’t do with classes is allocate a large array of them as a single consecutive block of memory. You can then pass around references (ref parameters) into this pool to avoid the copy-to-pass-value semantics of struct. It’s not as clean as class semantics, but gives you better control over memory management, which is occasionally important. (Sure, you can allocate an array of classes, but all you get is an array of null references to classes, you still need to allocate each instance. If you allocate an array of structs, you’ve got the structs themselves.)

As to why Unity can serialize Vector3’s but not our structs, it’s because Vector3 (and Vector2 and Vector4 and a few other types) are special-cased, as is evident from, for example, the existence of SerializedProperty.vector3Value.

1 Like