Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Caeser_21 · Mar 31 at 08:32 AM · 2dunity 2dgridtilesefficiency

How do I create a grid-based map in the most efficient way?

I'm making a 2D farming (open-world type) game and i need a huge map for it...
Until now I was using the regular In-built Tilemap system in Unity. But, I needed to make it a grid-based map, i.e. I want to be able to select a tile of the grid to plant and break stuff (I think i know how to do this, using Raycasts)


Here is where the problem arises, To make the grid i started instantiating 'Tile' objects like :

 for (int x = 0; x < GridArray.GetLength(0); x++)
 for (int y = 0; y < GridArray.GetLength(1); y++)
 {
     GameObject Tile = Instantiate(TileObject, this.transform);
     SpriteRenderer TileSP = Tile.GetComponent<SpriteRenderer>();
     float Rand = Random.value;
     if (Rand > 0.97f)
     {
         Name = "Flower";
     }
     else if (Rand > 0.8f)
     {
         Name = "Grass";
     }
     else
     {
         Name = "Plain";
     }
 
     switch(Name)
     {
         case "Grass" :
             TileSP.sprite = TileObjectSprites[Random.Range(5, 6)];
             Tile.tag = "Grass";
             break;
         case "Flower" :
             TileSP.sprite = TileObjectSprites[Random.Range(1, 4)];
             Tile.tag = "Flower";
             break;
         case "Plain" :
             TileSP.sprite = TileObjectSprites[0];
             Tile.tag = "Plain";
             break;                    
         default :
             TileSP.sprite = TileObjectSprites[0];
             Tile.tag = "Grass";
             break;
     }
     Tile.transform.position = new Vector3(x, y, 0f);
     Tile.name = "Tile" + NameNumber;
     NameNumber++;
 }

This code alone takes around 1 minute just to process and load into the game, But when i try to instantiate trees and other objects along with the tiles it can anywhere between 5-15 minutes just to process


So, i wanted to know if there was a more efficient and less time consuming method of doing this...
Thanks in advance


EDIT : I checked out some videos on YouTube, but none of them really fit my problem

Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image andrew-lukasik · Mar 31 at 04:31 PM 1
Share

Open up a Profiler window and use it. It will tell you what is taking the most of that time.

My bet is on Instantiate. There are creative ways to work around that.

avatar image Caeser_21 andrew-lukasik · Mar 31 at 05:47 PM 0
Share

Oh ok.. I shall try out a profiler in the morning... if you you don't mind me asking what other way of instantiating are available?

avatar image andrew-lukasik Caeser_21 · Apr 01 at 10:04 AM 1
Share

1000/1000 grid, and it's Instantiate fault:

link text

 using UnityEngine;
 public class LetsTestItOut : MonoBehaviour
 {
     [SerializeField][Min(1)] Vector2Int _numCells = new Vector2Int( 100 , 100 );
     [SerializeField] Sprite[] _spriteFlowers = new Sprite[1];
     [SerializeField] Sprite[] _spriteGrass = new Sprite[1];
     [SerializeField] Sprite[] _spritePlain = new Sprite[1];
     [SerializeField] GameObject _tilePrefab = null;
     void Start ()
     {
         for( int x=0 ; x<_numCells.x ; x++ )
         for( int y=0 ; y<_numCells.y ; y++ )
         {
             GameObject tile = Instantiate( _tilePrefab , transform );
             tile.transform.position = new Vector3(x,y,0);
 
             var sprite = tile.GetComponent<SpriteRenderer>();
             float rando = Random.value;
             if( rando>0.97f )
             {
                 // tile.tag = "Flower";
                 sprite.sprite = _spriteFlowers[ Random.Range(0,_spriteFlowers.Length) ];
             }
             else if (rando > 0.8f)
             {
                 sprite.sprite = _spriteGrass[ Random.Range(0,_spriteGrass.Length) ];
                 // tile.tag = "Grass";
             }
             else
             {
                 sprite.sprite = _spritePlain[ Random.Range(0,_spritePlain.Length) ];
                 // tile.tag = "Plain";
             }
         }
     }
 }


Show more comments
Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by bacon_nugget · Apr 01 at 10:22 AM

If you weren't aware, the tile assets that you use to paint a tilemap are ScriptableObjects (link). I believe the tilemap uses these to achieve something similar to the 'level 3' suggestion from @andrew-lukasik.


You can extend the Tile (link) or TileBase classes to add custom behavior to your tiles. You wouldn't need to instantiate all of those objects because the unity engine already handles initialization for the tilemap. One important thing to know is that copies of the same tile on the map are not individual instances of a scriptable object. You would still need to make a list of objects that contain the data specific to each tile on the map. When you plant or break things on the farm, you can just grab a reference to the custom tile at that position and give it the data container tied to that location, maybe as a parameter to a method call. Methods in the custom tile can modify the data or use the data according to whatever your goals may be.


Obviously, your gameplay is going to require frequent visual changes. You can override GetTileData in order to define how a tile decides which sprite to use. An implementation of this method could fetch the data object for its location and choose a sprite with that information. If a tile needs to change behavior, you can switch it with a new type of custom tile.


Here is a code snippet I use in all of my ScriptableObject implementations. Line 9 adds a menu item under Assets > Create according to the path that you define (As shown in the example, it would be Assets > Create > Custom Tile). An instance of your scriptable object is created and saved into a ".asset" file. These files can be dragged and dropped into serialized fields in the inspector so that they can be referenced in your code. If you want to paint custom tiles onto your tilemap, just drag and drop the file into your tile palette and use the tile brushes as you normally would.


 public class YourCustomTile : Tile
 {
     public void YourTileBehavior(YourTileDataClass data)
     {
         //do farming stuff
     }
 
     #if UNITY_EDITOR
     [UnityEditor.MenuItem("Assets/Create/Custom Tile")]
     public static void Create()
     {
             var name = "Default File Name";
             var path = UnityEditor.EditorUtility.SaveFilePanelInProject(
                     $"Save {name}", name, "asset", $"Save {name}", "Assets/YourFilePath");
     
         if (path == "") return;
                 UnityEditor.AssetDatabase.CreateAsset(CreateInstance<YourCustomTile>(), path);
     }
     #endif
 }
 


Comment
Add comment · Show 10 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Caeser_21 · Apr 01 at 10:43 AM 0
Share

Thats really helpful... Thanks a lot! Although I wanna try instantiating a smaller grid with perlin noise just as a learning experience... But, thanks a lot again this will probably be helpful for me in the future.

avatar image bacon_nugget Caeser_21 · Apr 01 at 10:58 AM 1
Share

Of course! I'm working on my own 2D game at the moment and discovered this when I started working on creating the environment. I haven't invested a whole lot of effort in learning about DOTS just yet, but I get the impression that it might be overkill unless you're still having performance issues after attempting other solutions.


You can definitely still create your own custom tiles to use with your perlin noise experiment. The way tiles are represented and the way the map is generated are two independent things. Best of luck with it!

avatar image Caeser_21 bacon_nugget · Apr 01 at 11:14 AM 0
Share

Thanks a lot mate! Good luck on your game too :)

avatar image andrew-lukasik · Apr 06 at 11:00 AM 1
Share

+1 I think this a better answer. I'm not a 2D guy, so completely forgot that that Unity introduced this tile system that solves this issue for us (I hope). No idea how it performs through. We need to trust @bacon_nugget on that here.

avatar image bacon_nugget andrew-lukasik · Apr 06 at 11:15 AM 2
Share

@andrew-lukasik Thanks! Your answer gave a list of several good solutions, which is incredibly valuable for any beginner developers who might come across this question in the future. I only went into more detail on my favorite option :) This format really should be used more often on technical Q&A forums.


My game is pretty lightweight, but I'm reliably getting 250+ fps while using a couple thousand interactable tiles. It's obviously wise to always test things out and tailor the solution to your own project.

avatar image Caeser_21 bacon_nugget · Apr 06 at 11:29 AM 0
Share

I just finished my Tilemap with Perlin and it looks really cool...
Although the game does run >100fps i still want to try your method as it seems better, but i'm not exactly sure how do edit tiles just yet. @bacon_nugget you know any good tutorials on how to get started?

Show more comments
avatar image
3

Answer by andrew-lukasik · Mar 31 at 06:44 PM


Let me list few possible answers to your question in order of difficulty to implement them:


  • Level 1 difficulty:

Don't instantiate objects you can't see :T


  • Level 2 difficulty:

You can pre-instantiate all those objects ahead of time (ObjectPool or something like that)


  • Level 3 difficulty:

Split your game code into two separate layers:

DATA (actual game world state)

DATA VISUALIZATION (things you see on the screen)


This will allow you to run game world simulation cheaply on some kind of basic WorldCellData[] that contains all the world grid cells with their data. And then, again, only spawn objects to visualize state of cells that be seen by the player and despawn things he can't.


  • Level 4 difficulty:

Go DOTS. 100% or just partially, i.e. player & enemies can stay being GameObjects where the world is mostly entities.


Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Caeser_21 · Mar 31 at 06:53 PM 0
Share

Thanks mate.. I shall try them (If I can xD)

avatar image Caeser_21 Caeser_21 · Apr 01 at 03:15 AM 0
Share

I just went through all the topics and I think I have to use either DOTS or just make them inactive of they are far away from the player...
I don't object pooling will work as they get instantiated in the beginning and don't really get destroyed after that.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

312 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Texture grid displayed oddly when width =/= height 1 Answer

!URGENT! How to make a grid of clickable objects. 1 Answer

Isometric Tile Grid with 2D Sprite Assets 3 Answers

Have huge grid data in a way so a 2d range can be pulled effectively? 1 Answer

which one is more efficient on Android Tiles or a Terrain. 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges