Search Unity

How can I get rid of a specific tile in a tilemap?

Discussion in '2D' started by j7stin, Jan 12, 2020.

  1. j7stin

    j7stin

    Joined:
    Jan 7, 2020
    Posts:
    22
    Good day everyone!

    I'm making a game similar to Diggy and Motherload and I've created a tilemap for my game. It has all the different textures I need it in, grass, dirt, ores etc.. I've already made my player move using a joystick and not go through the floor with colliders but how do I make it so that when my player is touching a tile and presses a key, the tile beneath my player breaks?
    upload_2020-1-12_11-7-47.png
    This is what my game looks like so far if it helps to understand what I'm trying to say.
    What I basically want to do is to make my player have the ability to dig.

    Thanks :)
     
  2. Deleted User

    Deleted User

    Guest

    I hope it doesn't inconvenience you too much that I join you here? I'd like to know about that as well since I'm going to need my player to be able to break tiles in my game. :)
     
  3. j7stin

    j7stin

    Joined:
    Jan 7, 2020
    Posts:
    22
    Sure, I searched around the internet for a bit but sadly found nothing so now I'm just going to my last resort of asking on the forum :)
     
  4. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @j7stin

    "how do I make it so that when my player is touching a tile and presses a key, the tile beneath my player breaks?"

    Get your player position.
    Get position below player by adding an offset to player position.
    Convert this world position into Tilemap position, see Tilemap API worldToCell, worldToLocal.
    Now that you have tile position, get a tile at that position from Tilemap.
    Remove or replace the tile.

    Check out the API docs, tilemap has many useful methods:
    https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap.html
     
    j7stin likes this.
  5. j7stin

    j7stin

    Joined:
    Jan 7, 2020
    Posts:
    22
    @eses

    Thanks for the reply. I'm quite the noob at this though so I still need more help. I know how to get my player position and by adding an offset do you just mean doing something like 'positionx = playerObj.transform.position.x - 15' ?
    I've only been using Unity for a couple of days so please excuse me for the silly questions
     
    Last edited: Jan 12, 2020
  6. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    "I've only been using Unity for a couple of days so please excuse me for the silly questions"

    It is not a silly question, you just need to do more reading / watch tutorials first.

    I don't have time right now to explain this in more detail, I really recommend you go through all the basics tutorials, until you get the grasp how all of the most often used things work.

    But calculating offset is just that add another vector to your current player position:

    var offsetPos = player.transform.position + Vector3.down;
     
    maulib likes this.
  7. Deleted User

    Deleted User

    Guest

  8. Deleted User

    Deleted User

    Guest

    The script below attached to the tilemap works rather well.

    I use new Vector3(0f, -0.5f, 0f) instead of Vector3.down because Vector3.down has the unwanted result of deleting tiles that are under the tile that should be destroyed, like on the image:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Tilemaps;
    3.  
    4. public class DestroyTile : MonoBehaviour
    5. {
    6.     private Tilemap map;
    7.  
    8.     private void Start()
    9.     {
    10.         map = GetComponent<Tilemap>();
    11.         Debug.Log("map is " + map);
    12.     }
    13.  
    14.     private void OnCollisionEnter2D(Collision2D other)
    15.     {
    16.         GameObject player = GameObject.FindGameObjectWithTag("Player");
    17.  
    18.         Vector3 hitPosition = player.transform.position + new Vector3(0f, -0.5f, 0f);
    19.  
    20.         if(other.gameObject == player)
    21.         {
    22.             map.SetTile(map.WorldToCell(hitPosition), null);
    23.         }
    24.     }
    25. }
    Capture.JPG
     
  9. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @APSchmidt

    Yes - Vector3.down is an alias for Vector3(0, -1, 0). So it goes one unit down, when you actually want to go a half unit down to make sure you are somewhere in the tile below.

    But anyway I think this could only happen if your player's pivot is on the bottom edge of its bounding box, I guess if you move your character with physics, it might sink a bit into tile and this will happen.
     
  10. Deleted User

    Deleted User

    Guest

    Yes, that's the case. :)
     
  11. j7stin

    j7stin

    Joined:
    Jan 7, 2020
    Posts:
    22
    Hello :) Thanks so much for the replies. I just returned to working on my game but I'm getting the error
    'NullReferenceException: Object reference not set to an instance of an object
    DestroyTile.OnCollisionEnter2D (UnityEngine.Collision2D other) (at Assets/Scripts/DestroyTile.cs:18)'

    Could you please help?

    EDIT: Figured it out myself but no tile blocks destroy on collision :( Wait yes they do just have to jump lol

    EDIT2:
    My game is an android game and I want to make it so that it only digs down when the player is pulling the joystick down, does anyone know how I can do that?

    I have one C# script called PlayerMovement.cs which has verticalMove inside of it which detects where the playing is holding the joystick in terms of the vertical axis. I want to know how I can access this value in my other DestroyTile.cs script. The reason for needing to know this is because I want to be able to make it so that the block only breaks when my character is touching it and when the player goes down on the joystick.

    This is what I've done so far:

    Code (CSharp):
    1.  
    2.     using UnityEngine;
    3.     using UnityEngine.Tilemaps;
    4.  
    5.     public class DestroyTile : MonoBehaviour
    6.     {
    7.         private Tilemap map;
    8.         public Joystick joystick;
    9.  
    10.  
    11.     private void Start()
    12.         {
    13.             map = GetComponent<Tilemap>();
    14.             Debug.Log("map is " + map);
    15.         }
    16.  
    17.         private void OnCollisionEnter2D(Collision2D other)
    18.         {
    19.             float verticalMove = joystick.Vertical;
    20.  
    21.             GameObject player = GameObject.FindGameObjectWithTag("Player");
    22.  
    23.             Vector3 hitPosition = player.transform.position + new Vector3(0f, -0.5f, 0f);
    24.  
    25.             if(other.gameObject == player && verticalMove >= 0.5f)
    26.             {
    27.                 map.SetTile(map.WorldToCell(hitPosition), null);
    28.             }
    29.         }
    30.     }
    31.  
    I'm getting the error NullReferenceException: Object reference not set to an instance of an object. Same error I got earlier but I forgot how to fix it :/

    I'm thinking of an alternate solution of making it so you just have to push a button and the tile beneath will break as it may be easier but I'm not sure.
     
    Last edited: Jan 18, 2020
  12. j7stin

    j7stin

    Joined:
    Jan 7, 2020
    Posts:
    22
    I have completely remade my game and am now using prefabs instead of tilemaps and when I use the same system, I just want to remove the prefab the player is touching but the Destroy(other.gameObject) isn't working anymore.

    It works if I change the if statement from if (other.gameObject == player) to if (other.gameObject.name = "TileGrass(Clone)") but I don't want to have to do that for every tile. Is there a better way to do this?
     
    Last edited: Jan 19, 2020