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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Variable in GameObject list keeps changing

Discussion in 'Scripting' started by SuitOne, Apr 25, 2022.

  1. SuitOne

    SuitOne

    Joined:
    Aug 10, 2021
    Posts:
    4
    Hello!

    I am trying to make a script that generates 10x10 chunks of 25x25 tiles. The tiles are gameobjects that hold a Tile script, which contains a boolean saying whether it is a mineral or not. This boolean is randomly assigned in the GenerateChunk() function. Unfortunately, all my tiles all spawn as a mineral or not, with no variation. Through debugging, I've come to the conclusion that within the chunkDict dictionary, the tile boolean is changed through each chunk generation, but overwritten each time, and I can't for the life of me figure out why that's happening. Any help is much appreciated.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public struct Chunk
    5. {
    6.     public Vector2 chunkPos;
    7.     public List<GameObject> tiles;
    8.  
    9.     public Chunk(Vector2 chunkPos, List<GameObject> tiles)
    10.     {
    11.         this.chunkPos = chunkPos;
    12.         this.tiles = tiles;
    13.     }
    14.  
    15.     #region Overrides
    16.     public static bool operator ==(Chunk c1, Chunk c2)
    17.     {
    18.         return c1.Equals(c2);
    19.     }
    20.  
    21.     public static bool operator !=(Chunk c1, Chunk c2)
    22.     {
    23.         return !c1.Equals(c2);
    24.     }
    25.     #endregion
    26. }
    27. public class TileManager : MonoBehaviour
    28. {
    29.     public GameObject tile;
    30.     public int mapSize;
    31.     private Vector2 currentChunkPos;
    32.  
    33.     private Dictionary<Vector2, Chunk> chunkDict = new Dictionary<Vector2, Chunk>();
    34.  
    35.     void Start()
    36.     {
    37.         for (int i = 0; i < mapSize; i++)
    38.         {
    39.             for(int x = 0; x < mapSize; x++)
    40.             {
    41.                 GenerateChunk(new Vector2(i,x));
    42.             }
    43.         }
    44.     }
    45.  
    46.     void GenerateChunk(Vector2 chunkPos)
    47.     {
    48.         List<GameObject> curTiles = new List<GameObject>();
    49.  
    50.         int chunkX = (int)chunkPos.x * 25;
    51.         int chunkY = (int)chunkPos.y * 25;
    52.         for (int i = 0; i < 25; i++)
    53.         {
    54.             for (int x = 0; x < 25; x++)
    55.             {
    56.                 GameObject newTile = tile;
    57.                 bool isMineral = Random.Range(96, 98) >= 97;
    58.                 newTile.transform.position = new Vector3(i + chunkX, x + chunkY, 0);
    59.                 newTile.GetComponent<Tile>().mineral = isMineral;
    60.                 curTiles.Add(newTile);
    61.             }
    62.         }
    63.  
    64.         Chunk curChunk = new Chunk(chunkPos, curTiles);
    65.         chunkDict.Add(chunkPos, curChunk);
    66.         print(chunkDict[new Vector2(0,0)].tiles[27].GetComponent<Tile>().mineral);
    67.     }
    68.  
    69.     public Chunk GetChunk(Vector3 position)
    70.     {
    71.         Vector2 posVec2 = new Vector2((Mathf.Floor(position.x / 25)), (Mathf.Floor(position.y / 25)));
    72.         if(posVec2.x >= mapSize || posVec2.y >= mapSize ||
    73.            posVec2.x < 0 || posVec2.y < 0) { return default(Chunk); }
    74.         return chunkDict[posVec2];
    75.     }
    76.  
    77.     //given a position and diameter, send chunks that should be loaded
    78.     public List<Chunk> GetAreaChunks(int diameter, Vector3 position)
    79.     {
    80.         Vector2 posVec2 = new Vector2((Mathf.Floor(position.x / 25)), (Mathf.Floor(position.y / 25)));
    81.         List<Chunk> chunks = new List<Chunk>();
    82.  
    83.         if (posVec2.x > mapSize || posVec2.y > mapSize ||
    84.             posVec2.x < 0 || posVec2.y < 0) { chunks.Add(default(Chunk)); return chunks; }
    85.  
    86.         chunks.Add(chunkDict[posVec2]);
    87.         for (int i = 1; i < diameter; i++)
    88.          {
    89.             List<Vector2> newPosList = new List<Vector2>();
    90.             newPosList.Add(posVec2 + new Vector2(i,0));
    91.             newPosList.Add(posVec2 + new Vector2(0,i));
    92.             newPosList.Add(posVec2 + new Vector2(i,i));
    93.             newPosList.Add(posVec2 + new Vector2(-i,0));
    94.             newPosList.Add(posVec2 + new Vector2(0,-i));
    95.             newPosList.Add(posVec2 + new Vector2(-i,-i));
    96.             newPosList.Add(posVec2 + new Vector2(i,-i));
    97.             newPosList.Add(posVec2 + new Vector2(-i,i));
    98.             foreach(Vector2 newPos in newPosList)
    99.             {
    100.                 if (newPos.x < mapSize && newPos.y < mapSize &&
    101.                     newPos.x >= 0 && newPos.y >= 0) { chunks.Add(chunkDict[newPos]);
    102.                 }
    103.             }
    104.          }
    105.         return chunks;
    106.     }
    107. }
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Code (CSharp):
    1. GameObject newTile = tile;
    Looks to me based on this code that you literally have one single Tile GameObject that you're just reusing over and over again as every tile in every chunk. Shouldn't you be creating new GameObjects for each tile or something?
     
    SuitOne likes this.
  3. SuitOne

    SuitOne

    Joined:
    Aug 10, 2021
    Posts:
    4
    So there is a GameObject tile, which is a prefab of a default tile. Under the chunk generation, a GameObject called newtile is created as a clone of the tile prefab, and it's position and the Tile script inside of it are modified. When I start the game I know this is working because the chunks are generated and all the tiles have their different positions in the world, but the boolean is always either true or false uniformly across all of them.
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    That's not what your code is doing though. if it was I'd expect to see this:
    Code (CSharp):
    1. GameObject newTile = Instantiate(tile);
    but instead we just see
    Code (CSharp):
    1. GameObject newTile = tile;
    If you actually have GameObjects being spawned, it's being done by some other code entirely. Nothing in the code you shared is spawning any objects.
     
    SuitOne likes this.
  5. SuitOne

    SuitOne

    Joined:
    Aug 10, 2021
    Posts:
    4
    O
    Okay! That definitely made progress. So since this is code for what will be turning into a multiplayer game, there is a player tile manager that queries the main tile manager for the chunk list, and instantiates chunks within a render distance. So I plugged in your Instantiate, and it did randomize the minerals, but it also spawned in all 25x25x10x10 tiles serverside. How do I make the individual tiles in the tile list without spawning them?
     
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    You'd have to separate the code that generates tile data from the code that uses GameObjects to "display" nearby tiles to the player. Basically the GameObject pooling part should be completely independent from the world generation code.
     
    SuitOne likes this.
  7. SuitOne

    SuitOne

    Joined:
    Aug 10, 2021
    Posts:
    4
    Interesting. So basically try to change it to tiles that are being stored in a list instead of GameObjects? Would I run into the same issue of using the same tile over and over again, or does that only apply to GameObjects? Sorry for the constant questions, these are all new concepts to me and I really appreciate your help.