Hello, I’m searching for a solution to show variables in the inspector without saving them in a prefab.
I have the same prefab multiple times in my scene and I want to manipulate 2 int variables (horizontal and vertical) in each prefab without actually saving them in a prefab. Creating multiple prefabs is not worth it because they all should be identical except these two variables.
How can I achieve this?
// Gets shown in inspector
public int Horizontal = 0;
// Gets shown
[SerializeField] private int _horizontal = 0;
// Doesn't get shown in inspector
[System.NonSerializable] public int Horizontal = 0;
// Doesn't shows as well
private int _horizontal = 0;
After looking up how to create a variable that doesn’t get shown in the inspector I found the [System.NonSerializable] attribute. This deserializes the variable, but also hides it in the inspector.
Unless I’m mistaken, isn’t this workflow already supported in prefabs? If you change values in prefab instances they become overrides and unless you apply them to the prefab they won’t affect anything else.
The only time that multiple instances would have their values changed would be if you changed the values in the prefab itself, then any instances that haven’t got overridden values would change to the new prefab value. (In this case you could write a custom inspector that prevents editing those fields directly in the prefab if you wanted to prevent that).
If you need to Spawn your Objects etc. or you need to work on your Prefab anyway.
You can create a ScripableObject config file, and assign that to your dedicated script/Prefab and use its values, that way you can work with your Prefab outside of the restriction “not to override” your prefab and be dynamic on your values.
Also spiney suggested prefab variants, if you dont have “too many” entities or whatever its needed for, i would suggest that as well.
Thank you for all the suggestions. I have multiple rooms in my scene which are the same prefab. It would be a bad idea to just create multiple prefabs because they all are basically the same only 2 variables of a script on the prefab are different. Of course I can just change the variables and never apply the changes to the prefab, but that is not what I want.
I should look into prefab variants, scriptable object files and custom editors. Thank you.
Update: I kinda did it guys! For anyone searching for a solution here is the script room script I was talking about earlier. Note the NonSerialized attribute.
using UnityEngine;
namespace Map
{
public class MapRoom : MonoBehaviour
{
[field: System.NonSerialized] public int Horizontal { get; set; } = 0;
[field: System.NonSerialized] public int Vertical { get; set; } = 0;
public void ButtonFunctionCall()
{
Debug.Log("Hello World");
}
}
}
And here is the custom editor I wrote for this script.
using UnityEditor;
using UnityEngine;
namespace Map
{
[CustomEditor(typeof(MapRoom))]
[ExecuteInEditMode]
public class MapRoomEditor : Editor
{
public override void OnInspectorGUI()
{
var mapRoom = target as MapRoom;
mapRoom.HorizontalStore = EditorGUILayout.IntField("Horizontal", mapRoom.Horizontal);
mapRoom.VerticalStore = EditorGUILayout.IntField("Vertical", mapRoom.Vertical);
}
}
}
Sadly the values reset after I press play, which means I’m at a worse point than where I started, but hey I can see NonSerialized variables in the inspector.
[field: System.NonSerialized]
public int HorizontalStore
{
get
{
return HorizontalStore;
}
set
{
Horizontal = value;
}
}
[SerializeField] public int Horizontal { get; private set; } = 0;
[field: System.NonSerialized]
public int VerticalStore
{
get
{
return VerticalStore;
}
set
{
Vertical = value;
}
}
[SerializeField] public int Vertical { get; private set; } = 0;
I tried to fix this by manipulating the getters and setters but to no success. If anyone has a solution for this I’m eager to hear it.
Properties are not serialized by default, so you wouldn’t need the attribute. But anything that isn’t serialized is going to reset to its initial value when entering play mode.
Like @Munchy2007 said - if you override the Horizontal and Vertical values in the prefab instance, but don’t apply them, then don’t you get the functionality you need? You can selectively apply changes to prefabs in the inspector.
I see certain contradictions in your explanation that make me think that you’ve not clear serialization concept.
Serialize is not synonymous the same than show the variable in the inspector, although working with unity without knowing the concept may lead you to think that it is so. There are ways to both observe non-serialized variables from the inspector and hide serialized ones. I will not stop to explain what serialization is because it is a concept that can be complicated to understand with a simple and short definition and there are many detailed explanations online.
I would venture to say from this comment that you want both of your variables to be serialized. An unserialized variable will not survive anyway between unity reloading, and Unity makes one each time when you switch from Editor Mode to Play Mode or vice versa.
Why don’t you want to save your serialized variables? Are you sure about it? I invite you to leave us an explanation without using concepts such as [quote=“getmyisland_dev, post:1, topic: 897127, username:getmyisland_dev”]
Manipulate 2 variables in each prefab without actually saving them in a prefab
[/quote] or [quote=“getmyisland_dev, post:1, topic: 897127, username:getmyisland_dev”]
They all should be identical except these two variables.
[/quote] because I think they are confusing both you and us.
Ok so I’m now trying to explain exactly what I want to achieve.
I have many different prefabs one for each room. For example “Break Room”, “Test Room”, "2 Way Hallway, “3 Way Hallway”, … Every room prefab has the MapRoom (see above posts) script attached with 2 public variables Horizontal and Vertical. Every combination of Horizontal and Vertical is unique. An object with Horizontal = 1 and Vertical = 2 is only valid if there is no other object with the same values.
I’m now creating a map and some room prefabs appear multiple times for example “2 Way Hallway”. The problem is that these rooms that appear multiple times share the values of Horizontal and Vertical. I can change the values, but then I can’t press the apply prefab button, because it will safe the values.
My solution to this problem is not to safe these 2 variables in the prefab and only set them for each room in the editor.
I tried to achieve this with the above solution, but the values get reset when I press Play.
TL;DR
I want to prevent 2 variables from being saved into a prefab, but I want to be able to set the variables in edit mode and use them in play mode.
I think that now I have understood you and I think that the problem is not in what you want to serialize or not, but in the structure that you are following.
From what you say rooms can be in multiple positions, you can have an instance of hall1 in position (2, 5) and also in position (3, 4). Each room will have its properties such as the color of its floor or its dimensions. However the position should not be a feature of the room: The position is only relevant when they are placed in a context, which is the map you are creating.
A vague implementation of the structure that you might be able to follow, if I’m not misunderstanding you:
using UnityEngine;
class Room : MonoBehaviour
{
//Just some example variables a room could have
[SerializeField] Vector2 _dimensions;
[SerializeField] Color _color;
//All your Room stuff
}
class Map : MonoBehaviour
{
[SerializeField] RoomWithPosition[] _rooms;
//All your map stuff
[System.Serializable]
struct RoomWithPosition
{
public Room room;
public Vector2Int position;
public bool HasSamePosition(RoomWithPosition other) => position == other.position;
}
}