I have the following class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PixelSystem
{
public GameObject pixelPrefab;
public Texture2D[] style;
public List<Chunk> chunks;
public GameObject mGameObject;
public PixelSystem(GameObject _mGameObject)
{
mGameObject = _mGameObject;
chunks = new List<Chunk>();
}
}
Chunk
and Pixel
are structs but I don't think they are relevant.
I would like pixelPrefab
and style
to be serialized but cannot seem to be able to make that work. This script is not attatched to a GameObject.
I have looked into getting the assets at runtime with Resources
or Addressables
but I would like to be able to set these fields from the editor.
I have tried making the class inherit from MonoBehaviour
and having [SerializeField] public GameObject pixelPrefab;
and [SerializeField] public Texture2D[] style;
, but the result of this is that pixelPrefab
is settable from the editor but instead of showing style
it shows mGameObject
, for some reason... ¯\_(ツ)_/¯
Edit: Turns out that the [SerializeFields]
do nothing here, the result is the same without them.
I've also tried puting [System.Serializable]
before the class, but as far as I can tell this does nothing at all.
Someone plz help.
Edit:
Due to some misunerstandings I would like to clarify a few things:
pixelPrefab
would work fine as a static
property, however, style
would not.get {load();}
This is what I want to see in the editor when I select my script:
And this is the closest thing to what I want so far:
Which I get by setting the class to inherit from MonoBehaviour
, I'd rather not inherit from anything, and idk if you are meant to have MonoBehaviour
classes that aren't attatched to gameObjects, but if this is necessary then so be it.
A few things here. I'm going to assume this point is the most important:
- I want to select the assets in the editior
So, in order to be able to do this, every field you want to see has to be able to be serialized by Unity and also Unity needs to be able to draw the GUI for that thing. You said,
I would like
pixelPrefab
andstyle
to be serialized but cannot seem to be able to make that work.
and again here I'm taking "serialized" to really mean that you just want those fields exposed in the Editor so you can stick things into them. So when you give me the following snippet I immediately see several issues:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PixelSystem
{
public GameObject pixelPrefab;
public Texture2D[] style;
public List<Chunk> chunks;
public GameObject mGameObject;
public PixelSystem(GameObject _mGameObject)
{
mGameObject = _mGameObject;
chunks = new List<Chunk>();
}
}
The first is that PixelSystem
itself isn't serialized. You either need to tag the class with [System.Serializable]
to use Unity's serializer or you need to inherit from something that Unity already knows should be serialized, like Component
or MonoBehaviour
(MonoBehaviour
inherits Component
). The issue with Component
and subclasses is that they need to exist on a GameObject, so you can't new
a Component
, you have to .AddComponent<YourComponent>()
.
Now as you've discovered, when you have your script inherit MonoBehaviour
, you see
that
pixelPrefab
is settable from the editor but instead of showing style it showsmGameObject
, for some reason... ¯\_(ツ)_/¯
And the reason it's showing mGameObject
can be seen in your class' member variables:
public GameObject pixelPrefab;
public Texture2D[] style;
public List<Chunk> chunks;
public GameObject mGameObject;
You can see that pixelPrefab
is a public GameObject
. Great! (1) your class is inheriting MonoBehaviour
, so Unity knows to serialize it, (2) pixelPrefab
is public
, so the Editor knows to show it, and GameObject
is itself a serializable object that Unity knows how to draw, so the end result is that Unity adds pixelPrefab
to the Editor GUI for your class.
Then you get to style
, which is public
, so the Editor knows it should show it, but it's an array and Unity doesn't know how to draw the Editor GUI for an array. It's an array of Texture2D
, which it does know how to draw, but it doesn't know how to handle the array aspect, so it doesn't add style
to your GUI.
Then you get to chunks
, which is public
, so the Editor knows it should show it, and it's a List
, which Unity does know how to handle, but it's a List of Chunk
, which I'm betting is not inheriting MonoBehaviour
and is also not tagged with [System.Serializable]
, so Unity doesn't know that it's supposed to be serializing Chunk
. This means that it does know it's supposed to be drawing a list, but it think it's not supposed to be drawing any contents for the list, so it skips the list completely.
Finally you get to public GameObject mGameObject
, which gets drawn for all the same reasons that pixelPrefab
gets drawn, and finally you get what you see in the Editor in your last screenshot: Only pixelPrefab
and mGameObject
are drawn in your class GUI:
So, what to do if you want to view your class in an Editor pane and you also want to see pixelPrefab
and style
?
MonoBehavior
, hold a reference to PixelSystem
OR have PixelSystem
inherit MonoBehavior
.PixelSystem
is not a MonoBehavior
then it needs to have [System.Serializable]
on the line above public class PixelSystem
.public GameObject pixelPrefab
.style
from an array to a list so Unity knows how to draw it.You should wind up with the following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PixelSystem
{
public GameObject pixelPrefab;
public List<Texture2D> style = new List<Texture2D>();
public List<Chunk> chunks;
public GameObject mGameObject;
public PixelSystem(GameObject _mGameObject)
{
mGameObject = _mGameObject;
chunks = new List<Chunk>();
}
}
You can also have Chunk
be serialized and shown in your Editor pane if you tag that class with [System.Serializable]
, and you only need the [SerializeField]
tag for fields that aren't already public
. You can still add that tag to public fields just like you can add [System.Serializable]
to a MonoBehaviour
but it's redundant. Not required.