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.
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.
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 (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 that can be important for designers for example for fast changes etc)
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.
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
Edit: Did you edit your post recently, or did I screw up when quoting? 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
Damn, you are quick on these forums, I should have guessed looking at your post count
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
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:
Does it make sense that UnityEngine.Vector3 is a value type rather than a reference type?
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.)
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. 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.
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.