Unity-Technologies / 2d-extras

Fun 2D Stuff that we'd like to share!
Other
1.54k stars 342 forks source link

AntiColliderTile #321

Open superfrantv opened 2 years ago

superfrantv commented 2 years ago

Hello, i need a option for a Negative Collider Tile, the function should be, there where this tile is placed, all tilemap colliders are removed on that point. so i can place it on special areas.

is this possible?

ChuanXin-Unity commented 2 years ago

You can turn off the TilemapCollider2D component with a script. You could do that with the StartUp function of the Tile, or through a GameObject attached to the Tile.

ChuanXin-Unity commented 2 years ago

Here's a script you can add to the TilemapCollider GameObject to check for the Tile and enable/disable the TilemapCollider:

` using System; using UnityEngine; using UnityEngine.Tilemaps;

[RequireComponent(typeof(Tilemap))] [RequireComponent(typeof(TilemapCollider2D))] public class DisableCollider : MonoBehaviour { private Tilemap m_Tilemap; private TilemapCollider2D m_TilemapCollider2D; private TileBase[] m_UsedTiles;

public TileBase m_DisableTile;

// Start is called before the first frame update
void Start()
{
    m_Tilemap = GetComponent<Tilemap>();
    m_TilemapCollider2D = GetComponent<TilemapCollider2D>();
}

// Update is called once per frame
void Update()
{
    if (m_DisableTile == null)
        return;

    var tileCount = m_Tilemap.GetUsedTilesCount();
    if (m_UsedTiles == null || m_UsedTiles.Length != tileCount)
    {
        Array.Resize(ref m_UsedTiles, tileCount);
    }
    m_Tilemap.GetUsedTilesNonAlloc(m_UsedTiles);

    var enableTilemapCollider = true;
    foreach (var tile in m_UsedTiles)
    {
        if (m_DisableTile == tile)
        {
            enableTilemapCollider = false;
            break;
        }
    }

    if (enableTilemapCollider != m_TilemapCollider2D.enabled)
        m_TilemapCollider2D.enabled = enableTilemapCollider;
}

} `

superfrantv commented 2 years ago

i tested it but i need to paint the whole tilemap with anticollidertiles. my problem is, that i have a

Wall-Tile with z = -1 there are some stairs on z = 0 but i cant walk down the stairs because the wall-tile generates a collider, this cant be disabled because the tile must have the collider but should disable it on places where other tiles are above. tileprpblem

ChuanXin-Unity commented 2 years ago

We do have a script that does something like this in 2d-techdemos: https://github.com/Unity-Technologies/2d-techdemos/blob/master/Assets/Tilemap/IsometricZAsY/Scripts/ToggleHeightLevel.cs, which you could add onto a GameObject for the top of the stair Tile.

This would require that the level is separated to different Tilemap Layers for a TilemapCollider2D for each height level.

superfrantv commented 2 years ago

I´am currently have 2 Tilemaps (Terrain & Objects), each in own RenderLayer. The Tiles each self has differend z-Heights. The Stairs and Walls are on the Terrain Map.

So i should add the Stairs to the Objects layer and the script?

superfrantv commented 2 years ago

I think the best option is, changing the code where the collider of the tilemap is build up. Like make a boolean field in ruleTile for each Tile to set true or false when a Tile is one z-height over this tile, this should also make performance faster for collider build up.

RuleTile A is checked "noColliderWhenOver", this means if any tile is at the same x & y coordinates but one z height higher, than this tiles collider is set to none at this place only.

ChuanXin-Unity commented 2 years ago

So i should add the Stairs to the Objects layer and the script?

That is possible. This will allow you to link the Tilemap Collider you want in the Scene to the script.

I think the best option is, changing the code where the collider of the tilemap is build up. Like make a boolean field in ruleTile for each Tile to set true or false when a Tile is one z-height over this tile, this should also make performance faster for collider build up.

Yes, that can be done. You could change the TileData.colliderType from Sprite to None to prevent a Tile from generating a collider, by comparing the height of the Tile with the height of your player for example. Recreating the collider from Tiles is quite expensive though, compared to enabling/disabling existing colliders from different Tilemap Layers.

superfrantv commented 2 years ago

The Second Option should be better, because the collider is only build once, but i need to check the next tile at higher z-axis.

superfrantv commented 2 years ago

i added a boolean field to the ruleTile, and inside the GetTileData Method i added this: `
if (disableColliderWhenUnder) {

                    if (tilemap.GetTile(position + new Vector3Int(0, 0, 1))) {
                        tileData.colliderType = Tile.ColliderType.None;
                    }
                }`

but it's not working.

ChuanXin-Unity commented 2 years ago

You could try to print out the Tile that is at tilemap.GetTile(position + new Vector3Int(0, 0, 1)) using Debug.Log.

I suspect that the Tile above would be at position + new Vector3Int(0, 1, 1) instead of just being at the same place with a higher Z.

superfrantv commented 2 years ago

Nice its works 👯

Here the Code if you want to make a Final-Tile with 100 of Functions. I think if you write 1 Tile for all Things with a Box where People can select a Form like TerrainTile, PipelineTile, FenceTile this forms sets the rules into the tile like a prefab of rules. I think 1 Tile with maximum Performance gets best, because Unitys Joby System can threat million of scripts of the same type.

i changed:

RuleTile.cs -> Add Top of Script

public bool disableColliderWhenUnder;

-> GetTileData()

Add Line under tileData.colliderType = rule.m_ColliderType;:

if (disableColliderWhenUnder) {
 if (tilemap.GetTile(position + new Vector3Int(0, 1, 1))) {
  tileData.colliderType = Tile.ColliderType.None;
 }
}

RuleTileEditor.cs -> OnInspectorGUI()

Add Line under EditorGUI.BeginChangeCheck():

tile.disableColliderWhenUnder = EditorGUILayout.Toggle("Disable Collider when under Tile", tile.disableColliderWhenUnder);

ChuanXin-Unity commented 2 years ago

Nice its works 👯

Great news!