Can't edit object on its original serialized field after adding it to an array

I have a ScriptableObject with two fields of a Serializable BattleCreature class, and an array of BattleCreatures, with references to the BattleCreature objects at those fields as well, as shown in this Inspector screenshot:

If I try to edit the fields inside the array elements, they also change their respective field (Creature A is at index 0, Creature B is at index 1) as expected, since they are both referencing the same object. In this image, I edit Element 0’s HP to 123:

However if I try the same from Creature A/B fields, it fails to edit the values. I keep typing 4, Backspace, Delete, nothing changes:

Also, if I remove the element from the array, the field from Creature A becomes editable again:

And Creature B / Former Element 0, now Element 1 seem to have become independent objects (does removing an element from an array of Serializable objects in Inspector cause every other element to be replaced by a copied instance?):

This is the code of the Battle class:

using UnityEngine;

public class Battle : ScriptableObject {
	[SerializeField] private BattleCreature creatureA;
	[SerializeField] private BattleCreature creatureB;

	[SerializeField] private BattleCreature[] battleOrder;

	public void SetupBattle(CoreCreature creatureA, CoreCreature creatureB) {
		this.creatureA = new BattleCreature(creatureA);
		this.creatureB = new BattleCreature(creatureB);
		this.battleOrder = new []{
			this.creatureA,
			this.creatureB
		};
	}
}

The SetupBattle function is called by a simple GameObject in the scene:

using UnityEngine;

public class BattleController : MonoBehaviour {
    [SerializeField] private Battle battle;
    [SerializeField] private CoreCreature creatureA;
    [SerializeField] private CoreCreature creatureB;

    void Start() {
        this.battle.SetupBattle(this.creatureA, this.creatureB);
    }
}

And this is the BattleCreature code.

using System;
using UnityEngine;

[Serializable]
public class BattleCreature {
    [SerializeField, Min(0)] private int hp = 0;
    [SerializeField, Min(1)] private int atk = 1;
    [SerializeField, Min(1)] private int def = 1;
    [SerializeField, Min(1)] private int spd = 1;

    private CoreCreature creature;

    public BattleCreature(CoreCreature creature) {
        this.creature = creature;
        this.hp = creature.HP;
        this.atk = creature.Atk;
        this.def = creature.Def;
        this.spd = creature.Spd;
    }
}

In short, the bug I am reporting here is that after the object already on a field is added to an serialized array field, I can only ever edit it through that array.

Unity’s default serialization is by-value. Meaning as soon as you save this asset, or it gets reserialized, all these BattleCreatures will become separate instances.

You can use [SerializeReference] instead to have all these serialized by-reference, which allows multiple references to same object across multiple fields.

Correct, however OP is modifying the array element and that is also modifying the other serialized object outside of the array automatically? If anything, that seems to be the bug, right?

You can assign the same object to multiple [SerializeField]s and they will behave as if by-reference up until a point. Generally up until the asset is reserialized for any number of reasons, such as saving it, or making a change to the SerializedObject structure (such as adding/removing an array element).

Until that point it will behave by-reference and editing it in one field will show in another field bound to the same data.

Interesting, that’s good to know thanks.

Though OP mentions they can only edit the field at the second point where it’s referenced.

So not sure if moving to [SerializeReference] will fix that, but it will be interesting to know if it does or not. If it still can’t be edited, then that would be an inspector bug that would need to be reported via the bug reporter.

Tested the SerializeReference alternative, it worked and allowed editing from both field and array element. Also tested deleting one of the array elements and the other one kept synchronizing. Thanks.

I don’t know why editing the non-array field didn’t work at the SerializeField version, but since it wasn’t supposed to be coded like that, maybe it’s not that important anyway.