Unity. Some fields go to null on Play - c#

I Mean those fields.
[SerializeField]
public Type gameStateType;
[SerializeField]
public IGameStateParams gameStateParams;
I made in Editor methods to set those fields up, but, when click Play they go null.
I can deal with Type(all supported by my system types stored in dictionary, so i can just use their ID to get Type), but not with IWhatever implemented instance.
Can it be solved?
If not, is there any way to store in scene game object any IWhatever implemented instance?

These types (Type and interfaces) are not serializable .. so while you can of course use editor scripts to pass in values these fields will not be serialized => not saved => Not be initialized on runtime.
When you enter PlayMode all objects in the scene are reloaded => deserialized from scratch => since your values were never serialized they are also not deserialized.
See Script Serialization -> Serialization Rules

Related

What do people mean when they talk about serialization in Unity?

I hear people talking about serializing variables among things in their unity projects and quite don't understand it. I see them using
[SerializeField]
and don't know why or what it does.
I looked up the definition of data serialization: Serialization is the process of converting the state information of an object into a form that can be stored or transmitted.
During serialization, objects write their current state to temporary or persistent storage. Later, the object can be recreated by reading or deserializing the state of the object from the store.
Objects are created as the program runs, and then reclaimed when unreachable, with a short lifespan. But what if we want to store the contents of the object permanently?
Convert it into a sequence of bytes and save it on a storage medium. Then serialization is required. [SerializeField] is to force Unity to serialize a private field. This is an internal Unity serialization function. Sometimes we need to Serialize a private or protected attribute. In this case, the [SerializeField] attribute can be used.
The above is some information I found, I hope it is correct and can bring you some help
Say, you have a field _speed and you want to set it using inspector. It means we want it to be serialized - stored somewhere in a human-readable and flexible format(e.g. xml), not directly in code. So when you edit fields in inspector, you edit the serialized data. During compilation, it's being deserialized and assigned to a field. This is how serialization/desearialization works. It is used to store non-static or just big amounts of data. In case of Unity it is used to show you everything in inspector. Transform has position and scale variables serialized and you can edit them.
In Unity there are two common ways to make fields assignable in inspector: using public fields or using [SerializedField] attribute for private ones.
Making fields public just to edit them with inspector is bad practice. If you can edit field in inspector, it means every other component can too, which is insecure. There is no good architecture that allows such things. If you want other components to edit the field, make it a property or make a set method. If you just need to assign fields by hand, don't use public fields. Avoid them.
When you use the [SerializeField] attribute, you create a private field that is accessible to this component only and you can assign it in inspector at the same time. If you need other components to read it, you can make a public property without set (public float Speed => _speed;).
This all is not an obligatory usage. Just good practice.
Any values set in the Unity inspector for any public fields or private/protected fields that use the attribute [SerializeField] are saved with the current scene file.
If you open up a Unity.scene file you will find a hierarchy of data that matches the scene hierarchy along with lists of what script or component classes are attached to that game object and what the field values of those classes/components should be.
When loading a level in Unity, the scene file is deserialized meaning that a program walks the data structure creating game objects. It then creates component and script class instances attached to those components and initializes them with the serialized data in the scene file. After that you end up with a level more or less the same as it was when saved in the unity editor.
In addition to your own Monobehaviour scripts having this ability, all the default unity components work this way. Transform uses serialized Vector3s for position, rotation and scale. MeshFilter components serialize a reference to a mesh asset and the MeshRenderer component references Materials that are used by the GPU to draw the mesh etc etc.
In short, serialisation is a process by which computers transform data so that it can be written to a file (or sent across a network via a protocol stream) and then later transformed back into the original set of objects it was to begin with (or as close as matters).

Property forwarding to child properties

I have a many objects of the same type (the base type is DisplayTool) in a list. The type is not determined at compile time but could be any type that has been added via a plugin system.
Let's assume I have a property called IsActive I currently need to go through all properties in the list an set the value. Additionally a single value of one object can be set.
Currently I need to do this for every property but I don't know them in advance so I was thinking of some WrapperObject that bundles the attached objects in a list and builds the properties dynamically. The ExpandoObject would be useful in this case but it doesn't bundle the properties into one.
The WinForms Property Inspector is a good example for the behavior I want. If the properties of a property of a all attached objects are the same, the value is shown, if not all values are the same it is not shown.
I have created my own MockObject derived from ExpandoObject that collects the properties and displays them. I only wanted to ask if there is already an implementation from the framework that does the same?

Creating a GameObject or Component based off of an instanced Object

I am using factories to generate Objects, however I am having trouble figuring out how to add these created object instances to the unity scene.
If I add a component of the type, it's a new instance and doesn't have the created data.
If I try and instantiate, It won't work because it's a custom class and has no gameObject.
Is there a common way to do this? or do I have to redesign how this is working?
So far the only thing I can think of is creating an Initialize method in the objects that sets all the properties, and then after the object is created and generated, I create a new Component, and call the initialize method on the GetComponent that I just added, setting the values to the values from the generated object.
Seems like a headache and bad way to do it though.
Basically I'm generating Items, using some Randomization functions to get their rarity/itemType etc, and then creating said Item using factories as I won't know what type they are until the game is already running.
I'm, in theory, trying to generate everything without any need for a database, except a sprite > object connection. But, the more and more I get into this the more I think i'm going to have to have some sort of database.
Long story short, I need the instances in the Unity scene so that when a player clicks on them he can "equip them, disenchant them, etc"

Automapper transform source just temporarily

I write a generic possibility to convert from database object to business object.
My business object contains custom attributes and depending on them, I like to make specific operations on them.
On reading from db its quite easy because I can use aftermap (not perfect solution, cause I have to do it by reflection and set the value depending on it)
But on writing back to the database I have to do it beforeMap but this would change the source permanent, but I just like it in a transient way. So do the operation with Source on the fly but do not change source object.
It's a generic option so I can't work with properties.
protected static T MapFromDatabaseWithConversion<T, TSource>(TSource source) where T : MappingModel, new()
{
var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, T>().AfterMap((src, dest) => dest.ConvertFromDatabase()));
return config.CreateMapper().Map<T>(source);
}
Do you have any solution for the check on the fly the attribute of a property and change the value depending on it - or you have any idea to change source only on the fly, so not write the result of source operation to src obj?
Thank you very much.
I think you have to include value tracking in your objects. For each class member you would need a boolean to reflect if the value changed, and a method that checks them all at once such as isObjectChanged(). You can hard code this or wrap your object in a Proxy object at runtime, which is more complicated, but does not clutter you class with value tracking data/methods. On the other hand, Java Data Objects (https://db.apache.org/jdo/) can do this for you by re-compiling your class files to include value tracking within the class about changing values. It takes a bit to set up and may be overkill for your specific question, but I have used it many times when targeting multiple data sources in the same project such as a database or spreadsheet. JDO allows me to use the same code with a different data type manager that can be swapped at runtime. You can also target a No-SQL database and other data stores as well.

How to implement delta compression of an object in C#?

I'm working on a server-based multiplayer game written in C#. The server and the client shares code and each object has the same int ID. I want to make the networking to be light as possible, by sending only the changed data.
The game has classes, which have numerous fields/properties, and they often change.
I'm seeking a way to detect when these values change and send these values to the client side.
Basically, this algorithm:
Flag object when it's changed
With the changed objects at network Tick:
Compare each property with their previous state
Send only the changed values
Store old values
Receive them on the client side
Instantiate the same type of object, or find it by ID
Set the new values
Of course, .NET Reflection may be eable to solve this problem, but iterating throuh 1000 object and their properties in each Tick, would be a bottleneck in performance.
I can send the basic types (int, float, vector), and maintain connection. My questions are these:
What's the best approach to send an object's Class and instantiate it?
How should I detect property change and how to serialise properties so I can find their "pair" on the client when receiving.
You can create something like this:
class Mob {
private int _health;
public int Health
{
get { return _health; }
set { _health = value; DirtyFlags |= MobDirtyFlags.Health
}
}
this means a lot of code for each property
Or you can have some custom dictionary and every change in that dictionary would be tracked, so
mob.Properties["Health"] = 10; would track that you changed something.
This is how Mooege (Diablo 3 emulator) does this.
First approach can be rewritten with aspects (probably some custom code that will generate all that code that is written above at runtime via Reflection.Emit or something similar).
Or if you know what will all your entities look like, you can generate classes for them from some templates (using something like T4)
as for serialization, this is good enough:
(key: int, value: object)
where key would be some enum like ActorProperties { Health, Strength, ...}

Categories