0
\$\begingroup\$

I am trying to create a game where one scene would be the "Past" and one scene would be the "Future". The player can travel through a portal to move between the past and future scenes.

In the past scene, the player makes a wooden house and in the future scene it will be turned into something else.

There can be multiple instances of these buildings in different places in the scene.

So far, I've tried...

  1. Using DontDestroyOnLoad to carry the object through from the past to future when loading between scenes.

  2. Using singletons to avoid duplicating the object multiple times when loading back and forth.

    But that has a problem: using singletons causes restricts me to just one instance of the building per scene, and I want to have several.

The reason why I wouldn't want to unload the old object when the scene unloads is because I wanted the player to be able to build in any area available within the scene. Something like the Fallout 4 building mechanics, where you can build in certain areas and keep those buildings, but I want it to become a different prefab in the future scene.

How can I implement a feature like this?

\$\endgroup\$
0
0
\$\begingroup\$

It sounds to me like what you want is something like a BuildingManager that keeps track of what has been built where.

When a new scene loads, the BuildingManager can look through its list of building placements, and spawn the appropriate prefabs for the current time period in those locations.

This could look something like this, using a static list to persist placement information between scenes/instances, and an Awake method that runs through that list and spawns appropriate prefabs.

You can place an instance of the BuildingManager in the scene for each time period, populating it with its date (so it knows which buildings to skip because they haven't been built yet / were already destroyed) and a list of prefabs so it knows what each building type should look like in its time period.

public class BuildingManager : MonoBehaviour {

    public struct Placement {
        public BuildingType buildingType;
        public Vector3 position;
        public Quaternion orientation;
        public int dateBuilt;
        public int dateRemoved;

        public Placement(BuildingType buildingType, Vector3 position,
                         Quaternion orientation, int date) {
            this.buildingType = buildingType;
            this.position = position;
            this.orientation = orientation;
            dateBuilt = date;
            dateRemoved = int.MaxValue;
        }
    }

    static List<Placement> _placements = new List<Placement>();


    [System.Serializable]
    public struct Builable {
        public BuildingType buildingType;
        public Transform prefab;
    }

    // Use this to set the time period for this scene, so you don't
    // show buildings that haven't been built yet, or buildings that
    // were removed in the past.
    public int date;

    // Populate this in the inspector with the list of prefabs
    // for each building type in this time period.
    public List<Buildable> buildables;

    // Call this to place a new building, and remember it for the future.
    public void Build(BuildingType buildingType, Vector3 position, Quaternion orientation) {
        if (Spawn(buildingType, position, orientation) == null )
            return;

        var placement = new Placement(buildingType, position, orientation, date);

        _placements.Add(placement);
    }

    // When the scene loads, spawn prefabs corresponding to each building placed.
    void Awake() {
        foreach (var placement in _placements) {
            if (placement.dateBuilt > date || placement.dateRemoved <= date) continue;
            
            Spawn(placement.buildingType, placement.position, placement.orientation);
        }
    }        

    // Look up the right prefab for this building, and spawn it.
    // Return null if no prefab has been set up for this type.
    Transform Spawn(BuildingType buildingType, Vector3 position, Quaternion orientation) {

        int index = buildables.FindIndex(b => b.buildinType == buildingType);
        if (index < 0) {
            Debug.LogError($"No prefab assigned for the building type {buildingType}");
            return null;
        }

        return Instantiate(buildables[index].prefab, position, orientation);
    } 
}
\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$
    – DMGregory
    May 13 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.