Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AntiColliderTile #321

Open
superfrantv opened this issue Nov 9, 2021 · 12 comments
Open

AntiColliderTile #321

superfrantv opened this issue Nov 9, 2021 · 12 comments

Comments

@superfrantv
Copy link

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
Copy link
Collaborator

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
Copy link
Collaborator

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
Copy link
Author

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
Copy link
Collaborator

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
Copy link
Author

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
Copy link
Author

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
Copy link
Collaborator

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
Copy link
Author

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
Copy link
Author

superfrantv commented Nov 18, 2021

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
Copy link
Collaborator

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
Copy link
Author

superfrantv commented Nov 19, 2021

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
Copy link
Collaborator

Nice its works 👯

Great news!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants