Beispiel #1
0
    //place each object in the array of objects that should appear in this scene randomly in valid receptacles
    //a seed of 0 is the default positions placed by hand(?)
    public bool RandomSpawnRequiredSceneObjects(
        int seed,
        bool SpawnOnlyOutside,
        int maxPlacementAttempts,
        bool StaticPlacement,
        ObjectTypeCount[] numRepeats,
        ObjectTypeCount[] emptyReceptacleSpots
        )
    {
                #if UNITY_EDITOR
        var Masterwatch = System.Diagnostics.Stopwatch.StartNew();
                #endif

        if (RequiredObjects.Count == 0)
        {
                        #if UNITY_EDITOR
            Debug.Log("No objects in Required Objects array, please add them in editor");
                        #endif

            return(false);
        }

        UnityEngine.Random.InitState(seed);


        List <SimObjType> TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>();
        Dictionary <SimObjType, List <SimObjPhysics> > AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

        int HowManyCouldntSpawn = RequiredObjects.Count;

        // GameObject topLevelObject = GameObject.Find("Objects");
        // PhysicsRemoteFPSAgentController controller = GameObject.FindObjectsOfType<PhysicsRemoteFPSAgentController>()[0];

        // foreach (GameObject go in SpawnedObjects) {
        //  go.SetActive(true);
        //  SimObjPhysics sop = go.GetComponent<SimObjPhysics>();
        //  sop.transform.parent = topLevelObject.transform;
        //  sop.transform.position = new Vector3(0.0f, controller.sceneBounds.min.y - 10f, 0.0f);
        //  go.GetComponent<Rigidbody>().isKinematic = true;
        // }

        //if we already spawned objects, lets just move them around
        if (SpawnedObjects.Count > 0)
        {
            HowManyCouldntSpawn = SpawnedObjects.Count;

            //for each object in RequiredObjects, start a list of what objects it's allowed
            //to spawn in by checking the PlacementRestrictions dictionary

            Dictionary <SimObjType, List <SimObjPhysics> > typeToObjectList = new Dictionary <SimObjType, List <SimObjPhysics> >();

            List <GameObject>            simObjectCopies          = new List <GameObject>();
            List <GameObject>            unduplicatedSimObjects   = new List <GameObject>();
            Dictionary <SimObjType, int> requestedNumRepeats      = new Dictionary <SimObjType, int>();
            Dictionary <SimObjType, int> minFreePerReceptacleType = new Dictionary <SimObjType, int>();
            HashSet <GameObject>         originalObjects          = new HashSet <GameObject>(SpawnedObjects);

            if (numRepeats == null)
            {
                numRepeats = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount repeatCount in numRepeats)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), repeatCount.objectType);
                requestedNumRepeats[objType] = repeatCount.count;
            }

            if (emptyReceptacleSpots == null)
            {
                emptyReceptacleSpots = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount emptyReceptacleSpot in emptyReceptacleSpots)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), emptyReceptacleSpot.objectType);
                minFreePerReceptacleType[objType] = emptyReceptacleSpot.count;
            }

            foreach (GameObject go in SpawnedObjects)
            {
                SimObjPhysics gop = null;
                gop = go.GetComponent <SimObjPhysics>();
                if (!typeToObjectList.ContainsKey(gop.ObjType))
                {
                    typeToObjectList[gop.ObjType] = new List <SimObjPhysics>();
                }
                if (!requestedNumRepeats.ContainsKey(gop.ObjType) ||
                    (typeToObjectList[gop.ObjType].Count < requestedNumRepeats[gop.ObjType]))
                {
                    typeToObjectList[gop.ObjType].Add(gop);
                }
            }


            foreach (SimObjType sopType in typeToObjectList.Keys)
            {
                if (requestedNumRepeats.ContainsKey(sopType) &&
                    requestedNumRepeats[sopType] > typeToObjectList[sopType].Count)
                {
                    foreach (SimObjPhysics gop in typeToObjectList[sopType])
                    {
                        simObjectCopies.Add(gop.gameObject);
                    }
                    int numExtra = requestedNumRepeats[sopType] - typeToObjectList[sopType].Count;

                    for (int j = 0; j < numExtra; j++)
                    {
                        // Add a copy of the item.
                        SimObjPhysics gop  = typeToObjectList[sopType][UnityEngine.Random.Range(0, typeToObjectList[sopType].Count - 1)];
                        SimObjPhysics copy = Instantiate(gop);
                        copy.name    += "_random_copy_" + j;
                        copy.UniqueID = gop.UniqueID + "_copy_" + j;
                        copy.uniqueID = copy.UniqueID;
                        //Randomizer randomizer = (copy.gameObject.GetComponentInChildren<Randomizer>() as Randomizer);
                        //randomizer.Randomize(rnd.Next(0, 2147483647));
                        simObjectCopies.Add(copy.gameObject);
                    }
                }
                else
                {
                    foreach (SimObjPhysics gop in typeToObjectList[sopType])
                    {
                        unduplicatedSimObjects.Add(gop.gameObject);
                    }
                }
            }
            unduplicatedSimObjects.Shuffle_();
            simObjectCopies.AddRange(unduplicatedSimObjects);


            foreach (GameObject go in simObjectCopies)
            {
                AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

                SimObjType goObjType = go.GetComponent <SimObjPhysics>().ObjType;

                bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
                if (typefoundindictionary)
                {
                    TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

                    //remove from list if receptacle isn't in this scene
                    //compare to receptacles that exist in scene, get the ones that are the same

                    // Todo: make a copy of receptacles and remove the ones where things can't be placed. Then clean up the placement code.
                    foreach (SimObjPhysics sop in ReceptaclesInScene)
                    {
                        // don't random spawn in objects that are pickupable to prevent Egg spawning in Plate with the plate spawned in Cabinet....
                        bool allowed = false;
                        if (sop.PrimaryProperty != SimObjPrimaryProperty.CanPickup)
                        {
                            if (SpawnOnlyOutside)
                            {
                                if (ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                                {
                                    allowed = true;
                                }
                            }
                            else if (TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                            {
                                allowed = true;
                            }
                        }
                        if (allowed)
                        {
                            if (!AllowedToSpawnInAndExistsInScene.ContainsKey(sop.ObjType))
                            {
                                AllowedToSpawnInAndExistsInScene[sop.ObjType] = new List <SimObjPhysics>();
                            }
                            AllowedToSpawnInAndExistsInScene[sop.ObjType].Add(sop);
                        }
                    }
                }

                //not found in dictionary!
                else
                {
                                        #if UNITY_EDITOR
                    Debug.Log(go.name + "'s Type is not in the ReceptacleRestrictions dictionary!");
                                        #endif
                    break;
                }

                // Now we have an updated list of receptacles in the scene that are also in the list
                // of valid receptacles for this given game object "go" that we are currently checking this loop
                if (AllowedToSpawnInAndExistsInScene.Count > 0)
                {
                    //SimObjPhysics targetReceptacle;
                    InstantiatePrefabTest       spawner = gameObject.GetComponent <InstantiatePrefabTest>();
                    List <ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

                    //each sop here is a valid receptacle
                    bool spawned = false;
                    foreach (SimObjPhysics sop in ShuffleSimObjPhysicsDictList(AllowedToSpawnInAndExistsInScene))
                    {
                        //targetReceptacle = sop;

                        //check if the target Receptacle is an ObjectSpecificReceptacle
                        //if so, if this game object is compatible with the ObjectSpecific restrictions, place it!
                        //this is specifically for things like spawning a mug inside a coffee maker
                        if (sop.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.ObjectSpecificReceptacle))
                        {
                            ObjectSpecificReceptacle osr = sop.GetComponent <ObjectSpecificReceptacle>();

                            if (osr.HasSpecificType(go.GetComponent <SimObjPhysics>().ObjType))
                            {
                                //in the random spawn function, we need this additional check because there isn't a chance for
                                //the physics update loop to fully update osr.isFull() correctly, which can cause multiple objects
                                //to be placed on the same spot (ie: 2 pots on the same burner)
                                if (osr.attachPoint.transform.childCount > 0)
                                {
                                    break;
                                }

                                //perform additional checks if this is a Stove Burner!
                                if (sop.GetComponent <SimObjPhysics>().Type == SimObjType.StoveBurner)
                                {
                                    if (StoveTopCheckSpawnArea(go.GetComponent <SimObjPhysics>(), osr.attachPoint.transform.position,
                                                               osr.attachPoint.transform.rotation, false) == true)
                                    {
                                        //print("moving object now");
                                        go.transform.position = osr.attachPoint.position;
                                        go.transform.SetParent(osr.attachPoint.transform);
                                        go.transform.localRotation = Quaternion.identity;

                                        go.GetComponent <Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Discrete;
                                        go.GetComponent <Rigidbody>().isKinematic            = true;

                                        HowManyCouldntSpawn--;
                                        spawned = true;

                                        // print(go.transform.name + " was spawned in " + sop.transform.name);

                                        // #if UNITY_EDITOR
                                        // //Debug.Log(go.name + " succesfully placed in " +sop.UniqueID);
                                        // #endif

                                        break;
                                    }
                                }

                                //for everything else (coffee maker, toilet paper holder, etc) just place it if there is nothing attached
                                else
                                {
                                    go.transform.position = osr.attachPoint.position;
                                    go.transform.SetParent(osr.attachPoint.transform);
                                    go.transform.localRotation = Quaternion.identity;

                                    Rigidbody rb = go.GetComponent <Rigidbody>();
                                    rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
                                    rb.isKinematic            = true;

                                    HowManyCouldntSpawn--;
                                    spawned = true;
                                    break;
                                }
                            }
                        }

                        targetReceptacleSpawnPoints = sop.ReturnMySpawnPoints(false);

                        //first shuffle the list so it's raaaandom
                        targetReceptacleSpawnPoints.Shuffle_();

                        //try to spawn it, and if it succeeds great! if not uhhh...

#if UNITY_EDITOR
                        // var watch = System.Diagnostics.Stopwatch.StartNew();
#endif

                        if (spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, go.GetComponent <SimObjPhysics>(), StaticPlacement, maxPlacementAttempts, 90, true, minFreePerReceptacleType)) //we spawn them stationary so things don't fall off of ledges
                        {
                            HowManyCouldntSpawn--;
                            spawned = true;

                                                        #if UNITY_EDITOR
                            // watch.Stop();
                            // var y = watch.ElapsedMilliseconds;
                            //print( "SUCCESFULLY placing " + go.transform.name+ " in " + sop.transform.name);
                                                        #endif

                            break;
                        }

                                                #if UNITY_EDITOR
                        // watch.Stop();
                        // var elapsedMs = watch.ElapsedMilliseconds;
                        // print("time for trying, but FAILING, to place " + go.transform.name + " in " + sop.transform.name + ": " + elapsedMs + " ms");
                                                #endif
                    }

                    if (!spawned)
                    {
                                                #if UNITY_EDITOR
                        Debug.Log(go.name + " could not be spawned.");
                        #endif
                        //go.GetComponent<SimpleSimObj>().IsDisabled = true;
                        if (!originalObjects.Contains(go))
                        {
                            go.SetActive(false);
                            Destroy(go);
                        }
                    }
                }
            }
        }
        else
        {
            throw new NotImplementedException();
        }

        // Debug code to see where every object is spawning
        // string s = "";
        // foreach (GameObject sop in SpawnedObjects) {
        //  s += sop.name + ": " + sop.transform.parent.gameObject.name + ",\t";
        // }
        // Debug.Log(s);

        ///////////////KEEP THIS DEPRECATED STUFF - In case we want to spawn in objects that don't currently exist in the scene, that logic is below////////////////
        // //we have not spawned objects, so instantiate them here first
        // else
        // {
        //  //for each object in RequiredObjects, start a list of what objects it's allowed
        //  //to spawn in by checking the PlacementRestrictions dictionary
        //  foreach(GameObject go in RequiredObjects)
        //  {
        //      TypesOfObjectsPrefabIsAllowedToSpawnIn.Clear();
        //      AllowedToSpawnInAndExistsInScene.Clear();

        //      SimObjType goObjType = go.GetComponent<SimObjPhysics>().ObjType;

        //      bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
        //      if(typefoundindictionary)
        //      {
        //          TypesOfObjectsPrefabIsAllowedToSpawnIn = new List<SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

        //          //remove from list if receptacle isn't in this scene
        //          //compare to receptacles that exist in scene, get the ones that are the same

        //          foreach(SimObjPhysics sop in ReceptaclesInScene)
        //          {
        //              if(SpawnOnlyOutside)
        //              {
        //                  if(ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
        //                  {
        //                      AllowedToSpawnInAndExistsInScene.Add(sop);
        //                  }
        //              }

        //              else if(TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
        //              {
        //                  //updated list of valid receptacles in scene
        //                  AllowedToSpawnInAndExistsInScene.Add(sop);
        //              }
        //          }
        //      }

        //      else
        //      {
        //          #if UNITY_EDITOR
        //          Debug.Log(go.name +"'s Type is not in the ReceptacleRestrictions dictionary!");
        //          #endif

        //          break;
        //      }

        //      // // //now we have an updated list of SimObjPhys of receptacles in the scene that are also in the list
        //      // // //of valid receptacles for this given game object "go" that we are currently checking this loop
        //      if(AllowedToSpawnInAndExistsInScene.Count > 0)
        //      {
        //          SimObjPhysics targetReceptacle;
        //          InstantiatePrefabTest spawner = gameObject.GetComponent<InstantiatePrefabTest>();
        //          List<ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

        //          //RAAANDOM!
        //          ShuffleSimObjPhysicsList(AllowedToSpawnInAndExistsInScene);
        //          //bool diditspawn = false;


        //          GameObject temp = Instantiate(go, new Vector3(0, 100, 0), Quaternion.identity);
        //          temp.transform.name = go.name;
        //          //print("create object");
        //          //GameObject temp = PrefabUtility.InstantiatePrefab(go as GameObject) as GameObject;
        //          temp.GetComponent<Rigidbody>().isKinematic = true;
        //          //spawn it waaaay outside of the scene and then we will try and move it in a moment here, hold your horses
        //          temp.transform.position = new Vector3(0, 100, 0);//GameObject.Find("FPSController").GetComponent<PhysicsRemoteFPSAgentController>().AgentHandLocation();

        //          foreach(SimObjPhysics sop in AllowedToSpawnInAndExistsInScene)
        //          {
        //              targetReceptacle = sop;

        //              targetReceptacleSpawnPoints = targetReceptacle.ReturnMySpawnPoints(false);

        //              //first shuffle the list so it's raaaandom
        //              ShuffleReceptacleSpawnPointList(targetReceptacleSpawnPoints);

        //              //try to spawn it, and if it succeeds great! if not uhhh...

        //              #if UNITY_EDITOR
        //              var watch = System.Diagnostics.Stopwatch.StartNew();
        //              #endif

        //              if(spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, temp.GetComponent<SimObjPhysics>(), true, maxcount, 360, true)) //we spawn them stationary so things don't fall off of ledges
        //              {
        //                  //Debug.Log(go.name + " succesfully spawned");
        //                  //diditspawn = true;
        //                  HowManyCouldntSpawn--;
        //                  SpawnedObjects.Add(temp);
        //                  break;
        //              }

        //              #if UNITY_EDITOR
        //              watch.Stop();
        //              var elapsedMs = watch.ElapsedMilliseconds;
        //              print("time for PlacfeObject: " + elapsedMs);
        //              #endif

        //          }
        //      }
        //  }
        // }

        //we can use this to report back any failed spawns if we want that info at some point ?

                #if UNITY_EDITOR
        if (HowManyCouldntSpawn > 0)
        {
            Debug.Log(HowManyCouldntSpawn + " object(s) could not be spawned into the scene!");
        }

        Masterwatch.Stop();
        var elapsed = Masterwatch.ElapsedMilliseconds;
        print("total time: " + elapsed);
                #endif

        //Debug.Log("Iteration through Required Objects finished");
        SetupScene();
        return(true);
    }
Beispiel #2
0
    //use action.randomseed for seed, use action.forceVisible for if objects shoudld ONLY spawn outside and not inside anything
    // //set forceVisible to true for if you want objects to only spawn in immediately visible receptacles.
    // public bool RandomSpawnRequiredSceneObjects(ServerAction action)
    // {
    //     return RandomSpawnRequiredSceneObjects(action.randomSeed, action.forceVisible, action.numPlacementAttempts, action.placeStationary, action.numDuplicatesOfType, action.excludedReceptacles);
    // }

    //place each object in the array of objects that should appear in this scene randomly in valid receptacles
    //seed- random seed used to pick locations
    //SpawnOnlyOutside - set to true to use only receptacles that are open innately (ie: tables, countertops, sinks) and not ones that require actions to open (drawer, cabinet etc.)
    //maxPlacementAttempts - the max number of times an object will attempt to be placed in within a receptacle
    //StaticPlacement - set to true if objects should be placed so they don't roll around after being repositioned
    //numDuplicatesOfType - used to duplicate the first instance of an object type found in a scene
    //excludedReceptacles -
    public bool RandomSpawnRequiredSceneObjects(
        int seed,
        bool SpawnOnlyOutside,
        int maxPlacementAttempts,
        bool StaticPlacement,
        ObjectTypeCount[] numDuplicatesOfType,
        List <SimObjType> excludedReceptacles
        )
    {
                #if UNITY_EDITOR
        var Masterwatch = System.Diagnostics.Stopwatch.StartNew();
                #endif

        if (RequiredObjects.Count == 0)
        {
                        #if UNITY_EDITOR
            Debug.Log("No objects in Required Objects array, please add them in editor");
                        #endif

            return(false);
        }

        //initialize Unity's random with seed
        UnityEngine.Random.InitState(seed);

        List <SimObjType> TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>();
        Dictionary <SimObjType, List <SimObjPhysics> > AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

        int HowManyCouldntSpawn = RequiredObjects.Count;

        //if we already spawned objects, lets just move them around
        if (SpawnedObjects.Count > 0)
        {
            HowManyCouldntSpawn = SpawnedObjects.Count;

            Dictionary <SimObjType, List <SimObjPhysics> > typeToObjectList = new Dictionary <SimObjType, List <SimObjPhysics> >();

            Dictionary <SimObjType, int> requestedNumDuplicatesOfType = new Dictionary <SimObjType, int>();
            //List<SimObjType> listOfExcludedReceptacles = new List<SimObjType>();
            HashSet <GameObject> originalObjects = new HashSet <GameObject>(SpawnedObjects);

            if (numDuplicatesOfType == null)
            {
                numDuplicatesOfType = new ObjectTypeCount[0];
            }
            foreach (ObjectTypeCount repeatCount in numDuplicatesOfType)
            {
                SimObjType objType = (SimObjType)System.Enum.Parse(typeof(SimObjType), repeatCount.objectType);
                requestedNumDuplicatesOfType[objType] = repeatCount.count;
            }

            //now lets go through all pickupable sim objects that are in the current scene
            foreach (GameObject go in SpawnedObjects)
            {
                SimObjPhysics sop = null;
                sop = go.GetComponent <SimObjPhysics>();

                //add object types in the current scene to the typeToObjectList if not already on it
                if (!typeToObjectList.ContainsKey(sop.ObjType))
                {
                    typeToObjectList[sop.ObjType] = new List <SimObjPhysics>();
                }

                //Add this sim object to the list if the sim object's type matches the key in typeToObjectList
                if (!requestedNumDuplicatesOfType.ContainsKey(sop.ObjType) ||
                    (typeToObjectList[sop.ObjType].Count < requestedNumDuplicatesOfType[sop.ObjType]))
                {
                    typeToObjectList[sop.ObjType].Add(sop);
                }
            }

            //keep track of the sim objects we are making duplicates of
            List <GameObject> simObjectDuplicates = new List <GameObject>();
            //keep track of the sim objects that have not been duplicated
            List <GameObject> unduplicatedSimObjects = new List <GameObject>();

            //ok now lets go through each object type in the dictionary
            foreach (SimObjType sopType in typeToObjectList.Keys)
            {
                //we found a matching SimObjType and the requested count of duplicates is bigger than how many of that
                //object are currently in the scene
                if (requestedNumDuplicatesOfType.ContainsKey(sopType) &&
                    requestedNumDuplicatesOfType[sopType] > typeToObjectList[sopType].Count)
                {
                    foreach (SimObjPhysics sop in typeToObjectList[sopType])
                    {
                        simObjectDuplicates.Add(sop.gameObject);
                    }

                    int numExtra = requestedNumDuplicatesOfType[sopType] - typeToObjectList[sopType].Count;

                    //let's instantiate the duplicates now
                    for (int j = 0; j < numExtra; j++)
                    {
                        // Add a copy of the item to try and match the requested number of duplicates
                        SimObjPhysics sop  = typeToObjectList[sopType][UnityEngine.Random.Range(0, typeToObjectList[sopType].Count - 1)];
                        SimObjPhysics copy = Instantiate(sop);
                        copy.name    += "_random_copy_" + j;
                        copy.ObjectID = sop.ObjectID + "_copy_" + j;
                        copy.objectID = copy.ObjectID;
                        simObjectDuplicates.Add(copy.gameObject);
                    }
                }

                //this object is not one that needs duplicates, so just add it to the unduplicatedSimObjects list
                else
                {
                    foreach (SimObjPhysics sop in typeToObjectList[sopType])
                    {
                        unduplicatedSimObjects.Add(sop.gameObject);
                    }
                }
            }

            unduplicatedSimObjects.Shuffle_(seed);
            simObjectDuplicates.AddRange(unduplicatedSimObjects);

            List <SimObjPhysics> ReceptaclesInScene = new List <SimObjPhysics>();
            ReceptaclesInScene = GatherAllReceptaclesInScene();

            //ok now simObjectDuplicates should have all the game objects, duplicated and unduplicated
            foreach (GameObject go in simObjectDuplicates)
            {
                AllowedToSpawnInAndExistsInScene = new Dictionary <SimObjType, List <SimObjPhysics> >();

                SimObjType goObjType = go.GetComponent <SimObjPhysics>().ObjType;

                bool typefoundindictionary = ReceptacleRestrictions.PlacementRestrictions.ContainsKey(goObjType);
                if (typefoundindictionary)
                {
                    TypesOfObjectsPrefabIsAllowedToSpawnIn = new List <SimObjType>(ReceptacleRestrictions.PlacementRestrictions[goObjType]);

                    //remove from list if receptacle isn't in this scene
                    //compare to receptacles that exist in scene, get the ones that are the same

                    foreach (SimObjPhysics sop in ReceptaclesInScene)
                    {
                        // don't random spawn in objects that are pickupable to prevent Egg spawning in Plate with the plate spawned in Cabinet....
                        bool allowed = false;
                        if (sop.PrimaryProperty != SimObjPrimaryProperty.CanPickup)
                        {
                            if (SpawnOnlyOutside)
                            {
                                if (ReceptacleRestrictions.SpawnOnlyOutsideReceptacles.Contains(sop.ObjType) && TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                                {
                                    allowed = true;
                                }
                            }
                            else if (TypesOfObjectsPrefabIsAllowedToSpawnIn.Contains(sop.ObjType))
                            {
                                allowed = true;
                            }
                        }

                        if (allowed)
                        {
                            if (!AllowedToSpawnInAndExistsInScene.ContainsKey(sop.ObjType))
                            {
                                AllowedToSpawnInAndExistsInScene[sop.ObjType] = new List <SimObjPhysics>();
                            }

                            AllowedToSpawnInAndExistsInScene[sop.ObjType].Add(sop);
                        }
                    }
                }

                //not found in dictionary!
                else
                {
                                        #if UNITY_EDITOR
                    Debug.Log(go.name + "'s Type is not in the ReceptacleRestrictions dictionary!");
                                        #endif
                    break;
                }

                // Now we have an updated list of receptacles in the scene that are also in the list
                // of valid receptacles for this given game object "go" that we are currently checking this loop
                if (AllowedToSpawnInAndExistsInScene.Count > 0)
                {
                    InstantiatePrefabTest       spawner = gameObject.GetComponent <InstantiatePrefabTest>();
                    List <ReceptacleSpawnPoint> targetReceptacleSpawnPoints;

                    bool spawned = false;
                    foreach (SimObjPhysics sop in ShuffleSimObjPhysicsDictList(AllowedToSpawnInAndExistsInScene, seed))
                    {
                        //if the receptacle, sop, is in the list of receptacles to exclude, skip over it and try the other Receptacles
                        if (excludedReceptacles.Contains(sop.Type))
                        {
                            continue;
                        }

                        //check if the target Receptacle is an ObjectSpecificReceptacle
                        //if so, if this game object is compatible with the ObjectSpecific restrictions, place it!
                        //this is specifically for things like spawning a mug inside a coffee maker
                        if (sop.DoesThisObjectHaveThisSecondaryProperty(SimObjSecondaryProperty.ObjectSpecificReceptacle))
                        {
                            ObjectSpecificReceptacle osr = sop.GetComponent <ObjectSpecificReceptacle>();

                            if (osr.HasSpecificType(go.GetComponent <SimObjPhysics>().ObjType))
                            {
                                //in the random spawn function, we need this additional check because there isn't a chance for
                                //the physics update loop to fully update osr.isFull() correctly, which can cause multiple objects
                                //to be placed on the same spot (ie: 2 pots on the same burner)
                                if (osr.attachPoint.transform.childCount > 0)
                                {
                                    break;
                                }

                                //perform additional checks if this is a Stove Burner!
                                if (sop.GetComponent <SimObjPhysics>().Type == SimObjType.StoveBurner)
                                {
                                    if (StoveTopCheckSpawnArea(go.GetComponent <SimObjPhysics>(), osr.attachPoint.transform.position,
                                                               osr.attachPoint.transform.rotation, false) == true)
                                    {
                                        //print("moving object now");
                                        go.transform.position = osr.attachPoint.position;
                                        go.transform.SetParent(osr.attachPoint.transform);
                                        go.transform.localRotation = Quaternion.identity;

                                        go.GetComponent <Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Discrete;
                                        go.GetComponent <Rigidbody>().isKinematic            = true;

                                        HowManyCouldntSpawn--;
                                        spawned = true;

                                        break;
                                    }
                                }

                                //for everything else (coffee maker, toilet paper holder, etc) just place it if there is nothing attached
                                else
                                {
                                    go.transform.position = osr.attachPoint.position;
                                    go.transform.SetParent(osr.attachPoint.transform);
                                    go.transform.localRotation = Quaternion.identity;

                                    Rigidbody rb = go.GetComponent <Rigidbody>();
                                    rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
                                    rb.isKinematic            = true;

                                    HowManyCouldntSpawn--;
                                    spawned = true;
                                    break;
                                }
                            }
                        }

                        targetReceptacleSpawnPoints = sop.ReturnMySpawnPoints(false);

                        //first shuffle the list so it's raaaandom
                        targetReceptacleSpawnPoints.Shuffle_(seed);

                        if (spawner.PlaceObjectReceptacle(targetReceptacleSpawnPoints, go.GetComponent <SimObjPhysics>(), StaticPlacement, maxPlacementAttempts, 90, true))
                        {
                            HowManyCouldntSpawn--;
                            spawned = true;
                            break;
                        }
                    }

                    if (!spawned)
                    {
                                                #if UNITY_EDITOR
                        Debug.Log(go.name + " could not be spawned.");
                        #endif
                        //go.GetComponent<SimpleSimObj>().IsDisabled = true;
                        if (!originalObjects.Contains(go))
                        {
                            go.SetActive(false);
                            Destroy(go);
                        }
                    }
                }
            }
        }

        else
        {
            ///XXX: add exception in at some point
            throw new NotImplementedException();
        }

                #if UNITY_EDITOR
        if (HowManyCouldntSpawn > 0)
        {
            Debug.Log(HowManyCouldntSpawn + " object(s) could not be spawned into the scene!");
        }

        Masterwatch.Stop();
        var elapsed = Masterwatch.ElapsedMilliseconds;
        print("total time: " + elapsed);
                #endif

        SetupScene();
        return(true);
    }
 // Start is called before the first frame update
 void Start()
 {
     osr   = gameObject.GetComponent <ObjectSpecificReceptacle>();
     onOff = gameObject.GetComponent <CanToggleOnOff>();
 }