Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Instantiate with an index

Discussion in 'Scripting' started by antoniomiguelferreiraaires, Jun 28, 2018.

  1. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Hello unity fellas. I am instantiating a player inside a floor using this code:
    Code (CSharp):
    1. private void GenerateTower(int numberOfFloors)
    2.     {      
    3.         int currentTime = dateValue.GetWeekOfMonth();
    4.  
    5.         Tower.transform.localScale = new Vector3(0.78f, 0.78f, 0f);
    6.  
    7.         int numberOfMiddleFloors = numberOfFloors - 2;
    8.        
    9.         Transform bottomFloorObj = Instantiate(bottomFloor, new Vector3(positionXClose, positionYClose, 0f), Quaternion.identity);
    10.        
    11.         bottomFloorObj.transform.SetParent(gameObject.transform, false);
    12.         positionYClose += floorHeigth;
    13.  
    14.         /*if (currentTime == 1)
    15.         /{
    16.         /    GeneratePlayer(bottomFloorObj);
    17.         }
    18.         */
    19.  
    20.         List<Transform> middleFloorList = new List<Transform> { middleFloor01, middleFloor02 };
    21.  
    22.         Random random = new Random();
    23.  
    24.         for (int i = 0; i < numberOfMiddleFloors; i++)
    25.         {
    26.             int index = random.Next(middleFloorList.Count);
    27.  
    28.             Transform middleFloorObj = Instantiate(middleFloorList[index], new Vector3(positionXClose, positionYClose, -10f), Quaternion.identity);
    29.            
    30.             middleFloorObj.transform.SetParent(gameObject.transform, false);
    31.            
    32.             positionYClose += floorHeigth;
    33.            
    34.             //GeneratePlayer(middleFloorObj);
    35.         }
    36.  
    37.         Transform topFloorObj = Instantiate(topFloor, new Vector3(positionXClose, positionYClose, -20f), Quaternion.identity);
    38.  
    39.         topFloorObj.transform.SetParent(gameObject.transform, false);
    40.  
    41.         //GeneratePlayer(topFloorObj);
    42.              
    43.     }
    44.  
    45.     //Each time a floor is created, call this function
    46.     private void GeneratePlayer(Transform floor)
    47.     {
    48.         Player.transform.localScale = new Vector3(0.7f, 0.7f, 0f);
    49.  
    50.         Transform playerSpawn = Instantiate(Player);
    51.        
    52.         playerSpawn.transform.SetParent(floor, false);
    53.  
    54.         playerSpawn.transform.localPosition = new Vector3(-4.2f, 0f, -10f);
    55.     }
    What I want to do is assign an index to the floor when instantiated and then create a logic like this: if the index is 0 meaning we are at bottom floor I spawn the player at bottom floor, if index is 2 I spawn the player only at second floor, and so on. What I had was spawning it in every floor but I just want to spawn in one floor acording the the floor index that is defined by the week number of the month e.g: week 1 = player spawns bottom floor

    I had the idea of creating:
    Code (CSharp):
    1.         List<Transform> allFloors = new List<Transform> { bottomFloorObj, middleFloorObj, bottomFloorObj};
    And use this list to archive what I want? Apreciate new ideas :)
     
  2. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    890
    So, if your week is number 3, spawn the player on a third position, right? Why not generate instantiate points (Vector3) and place them in your floors as well as adding them to an array, and if week 4, take 4th item of array and use it as transform.position point?
     
  3. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    You already have the floor instantiation and player instantiation split in methods.
    You could have a method that runs an initialization

    Fair warning: I have not tested this code.

    Code (CSharp):
    1. // List that defines your tower
    2. private List<Transform> TowerFloors = new List<Transform>();
    3.  
    4. // Prefabs that are used for building the tower
    5. public GameObject BottomFloorPrefab;
    6. public List<GameObject> MiddleFloorPrefabs;
    7. public GameObject TopFloorPrefab;
    8.  
    9.  
    10. public void Initialize()
    11. {
    12.     GenerateTower(numberOfFloors);
    13.     var weekBasedFloorTransform = GetFloorBasedOnWeek(dateValue.GetWeekOfMonth());
    14.     GeneratePlayer(weekBasedFloorTransform);
    15. }
    16.  
    17. private Transform GetFloorBasedOnWeek(int week)
    18. {
    19.     // some logic based on the week
    20.     // Depending on what GetWeekOfMonth returns it should still be an index between 0 [inclusive] ~ TowerFloors.Count[exclusive]
    21.     // Change this logic to your own liking
    22.     return TowerFloors[week];
    23. }
    24.  
    25. private void GenerateTower(int numberOfFloors)
    26. {
    27.     // Create a bottom floor
    28.     var bottomFloorPosition = new Vector3(positionXClose, positionYClose, 0f);
    29.     var bottomFloor = Instantiate(BottomFloorPrefab, bottomFloorPosition, Quaternion.identity, transform);
    30.     // Add the floor to the list
    31.     TowerFloors.Add(bottomFloor.transform);
    32.    
    33.     // Not sure why you have this in your code, you could also move this inside the for loop, start with it if need be
    34.     positionYClose += floorHeight;
    35.    
    36.     for (int i = 0; i < numberOfFloors - 2; i++)
    37.     {
    38.         // UnityEngine.Random.Range that returns an integer
    39.         var randomIndex = Random.Range(0, MiddleFloorPrefabs.Count);
    40.         // Random prefab from the list of prefabs (I guess you have a list of different middle floors)
    41.         var middleFloorPrefab = MiddleFloorPrefabs[randomIndex];
    42.         var middleFloorPosition = new Vector3(positionXClose, positionYClose, -10f);
    43.         // Clone the prefab as Instance
    44.         var middleFloorInstance = Instantiate(middleFloorPrefab, middleFloorPosition, Quaternion.identity, transform);
    45.         // Add it to the list
    46.         TowerFloors.Add(middleFloorInstance.transform);
    47.         // Increase Y position
    48.         positionYClose += floorHeight;
    49.     }
    50.    
    51.     // Now to finish the tower floors, create a top floor
    52.     var topFloorPosition = new Vector3(positionXClose, positionYClose, 0f);
    53.     var topFloor = Instantiate(TopFloorPrefab, topFloorPosition, Quaternion.identity, transform);
    54.     TowerFloors.Add(topFloor.transform);
    55. }
     
    astracat111 likes this.
  4. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Could you please give an insight in terms of code please?
     
  5. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Thanks.GetWeekOfMonth is here:
    Code (CSharp):
    1.    public static int GetWeekOfMonth(this DateTime time)
    2.     {
    3.         DateTime first = new DateTime(time.Year, time.Month, 1);
    4.         return time.GetWeekOfYear() - first.GetWeekOfYear() + 1;      
    5.     }
    6.  
    So what should I put in GetFloorBasedOnWeek?
     
  6. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Can't I just add private List<Transform> TowerFloors = new List<Transform>(); to my code and add the elements?
    The logic that is missing is assigning current week to index of TowerFloors..
     
  7. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    So basically that static integer method is returning the current week. You're probably using that method for UI as well I presume?

    Passing that value to the GetFloorBasedOnWeek method will fetch the Transform of the floor from the List.
    And then pass that transform to your GeneratePlayer method.

    But looking at your first post when the returned integer value is 1 you want it to be the bottom floor right?
    The index should then be 0. because a List index starts with 0.
    If you're going to use the static method for UI as well you might just want to pass the value to the GetFloorBasedOnWeek but with a -1. But that is a presumption.

    so:
    Code (csharp):
    1.  
    2. public void Initialize()
    3. {
    4.     GenerateTower(numberOfFloors);
    5.     var weekBasedFloorTransform = GetFloorBasedOnWeek(dateValue.GetWeekOfMonth() - 1);
    6.     GeneratePlayer(weekBasedFloorTransform);
    7. }
    8.  
    Week 1 returned from GetWeekOfMonth will then be 0, picking the first index of the list which is the bottom floor.
     
  8. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    719
    You need to use classes.

    Code (CSharp):
    1.  
    2.  
    3. namespace Adventure {
    4.  
    5. class GameObjects {
    6.  
    7.     [System.Serializable]
    8.     public abstract class Base {
    9.        public int ID { get; set; }
    10.        public string Name { get; set; }
    11.        public GameObject gameObject { get; set; }
    12.     }
    13.  
    14.     [System.Serializable]
    15.     public class Floor : Base {
    16.      
    17.        public Floor Create(int newID, string newName, GameObject gameObject_ToCopy) {
    18.            Floor floor = new Floor();
    19.            floor.ID = newID;
    20.            floor.Name = newName;
    21.            floor.gameObject = GameObject.Instantiate(gameObject_ToCopy.transform,gameObject_ToCopy.transform.parent);
    22.        }
    23.  
    24.     public List<Floor> GenerateFloorToList(int prefabIndex, string floorName, List<Floor> scene_Floors) {
    25.             Floor newFloor = new Adventure.GameObjects.Floor();
    26.             newFloor = adventureGameObjects.floor.Create(0,floorName, floorPrefab[prefabIndex]);
    27.             scene_Floors.Add(newFloor);
    28. }
    29.  
    30.     }
    31.     public Floor floor;
    32.  
    33. }
    34.  
    35. public GameObjects gameObjects;
    36.  
    37. }

    Now use it like this:

    Code (CSharp):
    1. public class MyNewScript_ThatsAttached_ToA_GameObject_InTheEditor : MonoBehaviour {
    2.  
    3. //A 'prefab' in this case refers actually to a Unity 'GameObject'. 'GameObjects' is different than 'GameObject' and is in
    4. // our adventure class above.
    5.  
    6. using Adventure;
    7. using UnityEngine;
    8.  
    9. Adventure.GameObjects adventureGameObjects;
    10. public List<GameObject> floorPrefabs;
    11.  
    12. //this is where instances of your floors get added to:
    13. public List<Floor> scene_Floors = new List<Floor>();
    14.  
    15. Start() {
    16.    //test out creating a floor
    17.      adventureGameObjects.floor.generateFloor(0,"The Gates of Hell",scene_Floors); //adds prefab 0 with name of 'The Gates of Hell' to your scene_Floors list.
    18.  
    19. }
    20.  
    21. }


    This is all untested, so sorry if it doesn't work but see if you get the idea.

    Due to being a very stupid person, it took me like...a year or more of programming full time in C# to realize the very basic idea that you've got like a front end and a back end. Your back end of your code is gonna be the messy part, while on the front end your goal is to create methods that will accomplish high level tasks.

    In other words, you want to be able to do like:

    adventureGameObjects.floor.Create(floor name goes here, id, etc...)

    In the case above I tried to have it where you have a scene list of game objects. I make it public so you can see it and debug it in the interpreter. The prefab list is so that you can click and drag prefabs into the list after modifying it's count in your inspector inside the unity editor.


    The idea is that you want to get it so that you are just calling methods:

    floors.Create
    floors.GetID(string floorName)

    Really simple sh*t on the front end, and then on your messy back end you want to keep cleaning it up and making it as neat and organized as possible.

    I personally like putting my front end at the top of my scripts and the back end below. The front end will be very short compared to the back end which will be hella long.


    You want to keep your Name and ID of your spawnable objects in an abstract base class.

    Abstract is just a class you inherit from where you can put a fancy pansty 'override' method inside of it, and then your floor would be required to implement it no matter what.

    If you have a base class that has ID and Name, then you can create other 'adventure game objects' (as I've called them in this example) like Wall, Light, Table etc...
     
    Last edited: Jun 28, 2018
  9. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    And yeah you could do that, in my example I only cleaned it up.
    Astracat111's example is valid too but introduces more class structure.
     
  10. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    719
    Yeah I wasn't sure if I was completely understanding what he was asking either...

    As far as spawning goes, I like to have a player start position represented by a 3D arrow, and a scene manager that manages that start position so that when switching between scenes unless overridden it just puts the player wherever the arrow is.... I'm thinking he could just do this as well.
     
  11. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Really appreciate your help guys. Btw take a look at what I said please: "The logic that is missing is assigning current week to index of TowerFloors.", what I mean by this is how to assign each instantiated prefab as gameobject that have a index in the list to a week number?
     
  12. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    if you need a floor by index you just use TowerFloors[index]
    since you have a week number already where the number is always 1 or higher
    just pass the week number - 1

    TowerFloors is a list of your instantiated tower
    index 0 = bottom floor (Week 1 - 1 = 0, so index 0)
     
  13. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    719
    yeah it's something that you need to just get used to.

    0 1 2 3 4 < - what you're actually working with in programming terms
    1 2 3 4 5 < - names
     
  14. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    Sure I know that. I tried an if statement but it doesn't work because middle floor can be 2 or 3, what I tried:
    Code (CSharp):
    1. if (currentTime == 1) //week 1
    2.         {
    3.             GeneratePlayer(TowerFloors[0]);
    4.         }
    or
    Code (CSharp):
    1. for (int i = currentTime; i < 5; i++)
    2.         {
    3.             GeneratePlayer(TowerFloors[currentTime - 1]);
    4.         }
    This doesn't work. I need something like this to check if I am at x week I instantiate the player at that floor x -1
     
  15. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    You shouldn’t spawn your player at floor x - 1 but rather the floor you supply it

    GeneratePlayer(TowerFloors[0]) Should return the bottom floor for the player to be generated on
     
  16. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    That's right. How to check the weeks 2-5?
     
  17. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,057
    Generate a tower that has enough floors
    Then just pass the next index
    TowerFloors[1] should be week 2
    TowerFloors[2] should be week 3
    etc.
     
  18. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53
    That I know lol The tower has been generated what I'm missing is the code for what you've tried to explain :(
    I've been slow in understanding this sorry about that
     
  19. antoniomiguelferreiraaires

    antoniomiguelferreiraaires

    Joined:
    Apr 10, 2018
    Posts:
    53