Drops saved with scene change?

If the drops are saved on the player won’t they be reloaded into another scene if we change scenes?

Say I drop several objects in scene 1 then I move to scene 2 hit save and reload. Won’t my drops from scene 1 be loaded into scene 2?

Sorry for the delay getting to this.
I actually playtested this and you’re quite right, the dropped items to transfer into the new scene. It isn’t immediately obvious since in many scenes the object would be hidden in the new scene under a building or mountain, or far from where we are standing… But I was able to confirm it by examining the RandomDropper and finding it in the dropped items list.

I’ll work on a patch for this, and get it into the course materials.

That actually didn’t take me very long to patch at all…

Note that for now, in this lecture, do not do this patch, it’s meaningless anyways.

When we get to Integration, and start talking about drops and RandomDropper, you’ll want to edit the original ItemDropper.cs…

We’ll start by adding using UnityEngine.SceneManagement; to the Using clauses of ItemDropper.cs

Then we’re going to make some changes to the CaptureState and RestoreState, as the structure we’re using to save…

[System.Serializable]
        private struct DropRecord
        {
            public string itemID;
            public SerializableVector3 position;
            public int number;
            public int scene;
        }

        private List<DropRecord> otherSceneDrops=new List<DropRecord>();

        object ISaveable.CaptureState()
        {
            RemoveDestroyedDrops();
            int currentScene = SceneManager.GetActiveScene().buildIndex;
            //var droppedItemsList = new DropRecord[droppedItems.Count];
            //for (int i = 0; i < droppedItemsList.Length; i++)
            //{
            //    droppedItemsList[i].itemID = droppedItems[i].GetItem().GetItemID();
            //    droppedItemsList[i].position = new SerializableVector3(droppedItems[i].transform.position);
            //    droppedItemsList[i].number = droppedItems[i].GetNumber();
            //    droppedItemsList[i].scene = SceneManager.GetActiveScene().buildIndex;
            //}
            foreach (var droppedItem in droppedItems)
            {
                DropRecord record = new DropRecord();
                record.itemID = droppedItem.GetItem().GetItemID();
                record.position = new SerializableVector3(droppedItem.transform.position);
                record.number = droppedItem.GetNumber();
                record.scene = currentScene;
                otherSceneDrops.Add(record);
            }


            return otherSceneDrops;
        }

        void ISaveable.RestoreState(object state)
        {
            int currentScene = SceneManager.GetActiveScene().buildIndex;
            otherSceneDrops = new List<DropRecord>();
            var droppedItemsList = (List<DropRecord>)state;
            foreach (var item in droppedItemsList)
            {
                if (item.scene==currentScene)
                {
                    var pickupItem = InventoryItem.GetFromID(item.itemID);
                    Vector3 position = item.position.ToVector();
                    int number = item.number;
                    SpawnPickup(pickupItem, position, number); 
                }
                else 
                {
                    otherSceneDrops.Add(item);
                }
            }
        }

So here’s the logic behind the changes…

First, and most obviously, we’re adding a scene variable to the DropRecord. This lets us know which scene (based on buildIndex) the drop is added into.

Then we’re creating a list of “otherSceneDrops” which is a List(); This starts as a new list, because if we’ve never restored, this should be empty, and we want it initialized.

private List<DropRecord> otherSceneDrops = new List<DropRecord>();

Now in CaptureState, we’re going to comment out the whole droppedItemsList… it’s no longer going to be used… I’ve left it in commented only for comparison, you can remove the commented lines.

We then iterate over the list of dropped items from our scene, adding the current scene index to the new drop record we’re creating, and then adding the new drop record to the otherSceneDrops() list.

The otherSceneDrops is what we’ll be returning.
If there are NO drops in any scene, it’s just an empty list. If there are scene drops in this scene but none in other scenes, it will contain just our scene’s drops. If there are drops in other scenes, and drops in this scene our drops in this scene will be merged with the list of otherSceneDrops.

Then in RestoreState, we’re first going to reset otherSceneDrops. This is to prevent duplicates in the event we’re using S and L to save our scene. Then instead of automatically spawning each item in the returned list (which we’ll note we’ve changed the cast from an Array to a List), we check to see if it’s in the current scene. If it’s in the scene, it’s dropped like normal, if it’s not in the scene, then it’s stored in the otherSceneDrops list for use in the next CaptureState().

I tested this in the game and it appears to perform as intended.

7 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms