I’m making a 2d game with a level editor integrated into the game, the script was made with Chatgpt, at first it worked fine, now I select the tile (Debug indicates the correct selected tile), after adding it to the scene/Level unity crashes, I also tried it after compiling the game also crashes. Whatever it may be, the script has an erase and fill function. The script has a variable where I add the tiles that unity creates with the tile palette and that creates category buttons and buttons for each tile. At first it added the tiles by clicking and dragging, but out of nowhere after some modifications it makes unity crash. Can anyone help me why this happens, I’m a beginner, I don’t find many tutorials about 2d level editor, the ones I find are not what I want.
code
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using TMPro;
public class TileButton : MonoBehaviour
{
[System.Serializable]
public class TileCategory
{
public string categoryName; // Nome da categoria
public TileBase[] tiles; // Conjunto de telhas da categoria
}
public Tilemap tilemap; // Referência ao Tilemap no qual as telhas serão colocadas
public TileCategory[] tileCategories; // Array de categorias de telhas
public GameObject categoryButtonPrefab; // Prefab do botão da categoria
public Transform categoryContainer; // Transform do objeto que conterá os botões de categoria
public TMP_Dropdown categoryDropdown; // Dropdown para selecionar a categoria
private List<TMP_Dropdown.OptionData> categoryOptions; // Opções do Dropdown
private List<Button> tileButtons; // Lista de botões de seleção de telha
private TileBase selectedTile; // Telha atualmente selecionada
private Vector3Int previousCellPos;
// Erase Tile Tool
public Button eraseButton; // Botão para ativar/desativar a ferramenta de apagar
private bool eraseMode; // Indica se a ferramenta de apagar está ativada
// Bucket Fill Tool
public Button bucketButton; // Botão para ativar/desativar a ferramenta de preenchimento em balde
private bool bucketMode; // Indica se a ferramenta de preenchimento em balde está ativada
private void Start()
{
tileButtons = new List<Button>();
categoryOptions = new List<TMP_Dropdown.OptionData>();
CreateCategoryButtons();
CreateTileButtons(tileCategories[0]);
eraseButton.onClick.AddListener(ToggleEraseMode);
bucketButton.onClick.AddListener(ToggleBucketMode);
}
private void CreateCategoryButtons()
{
// Cria as opções do Dropdown
categoryOptions.Clear();
// Para cada categoria, cria uma opção no Dropdown
for (int i = 0; i < tileCategories.Length; i++)
{
TileCategory category = tileCategories[i];
// Cria a opção do Dropdown para a categoria atual
TMP_Dropdown.OptionData categoryOption = new TMP_Dropdown.OptionData(category.categoryName);
categoryOptions.Add(categoryOption);
}
// Configura as opções do Dropdown
categoryDropdown.ClearOptions();
categoryDropdown.AddOptions(categoryOptions);
categoryDropdown.onValueChanged.AddListener(SelectCategory);
// Seleciona a primeira categoria por padrão
SelectCategory(0);
}
private void CreateTileButtons(TileCategory category)
{
// Remove os botões de seleção de telha anteriores
foreach (Button tileButton in tileButtons)
{
Destroy(tileButton.gameObject);
}
tileButtons.Clear();
// Para cada tipo de telha na categoria, cria um botão de seleção
for (int i = 0; i < category.tiles.Length; i++)
{
TileBase tile = category.tiles[i];
Button tileButton = Instantiate(categoryButtonPrefab, categoryContainer).GetComponent<Button>();
// Configura o botão e atribui a telha correspondente
Sprite tileSprite = GetTileSprite(tile);
tileButton.image.sprite = tileSprite;
tileButton.onClick.AddListener(() => SelectTile(tile));
tileButtons.Add(tileButton);
}
}
private Sprite GetTileSprite(TileBase tile)
{
if (tile is Tile tileObject)
{
return tileObject.sprite;
}
return null;
}
private void SelectTile(TileBase tile)
{
selectedTile = tile;
}
private void SelectCategory(int categoryIndex)
{
TileCategory category = tileCategories[categoryIndex];
// Atualiza os botões de seleção de telha com base na categoria selecionada
CreateTileButtons(category);
}
private void Update()
{
// Verifica se o mouse está sobre um elemento de UI
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
if (selectedTile != null && Input.GetMouseButton(0))
{
Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3Int cellPos = tilemap.WorldToCell(mouseWorldPos);
Debug.Log("Mouse World Position: " + mouseWorldPos);
Debug.Log("Cell Position: " + cellPos);
if (eraseMode)
{
Debug.Log("Erasing Tile at Cell: " + cellPos);
tilemap.SetTile(cellPos, null);
}
else if (bucketMode)
{
Debug.Log("Filling Tiles using Bucket Fill at Cell: " + cellPos);
FillTilesWithBucket(cellPos);
}
else if (cellPos != previousCellPos)
{
Debug.Log("Drawing Tiles from Cell: " + previousCellPos + " to Cell: " + cellPos);
Vector3Int minPos = Vector3Int.Min(cellPos, previousCellPos);
Vector3Int maxPos = Vector3Int.Max(cellPos, previousCellPos);
for (int x = minPos.x; x <= maxPos.x; x++)
{
for (int y = minPos.y; y <= maxPos.y; y++)
{
Vector3Int currentPos = new Vector3Int(x, y, cellPos.z);
Debug.Log("Drawing Tile at Cell: " + currentPos);
tilemap.SetTile(currentPos, selectedTile);
}
}
}
previousCellPos = cellPos;
}
else
{
previousCellPos = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
}
}
private void ToggleEraseMode()
{
eraseMode = !eraseMode;
Debug.Log("Erase Mode: " + eraseMode);
}
private void ToggleBucketMode()
{
bucketMode = !bucketMode;
Debug.Log("Bucket Mode: " + bucketMode);
}
private void FillTilesWithBucket(Vector3Int startCellPos)
{
if (selectedTile == null)
{
return;
}
Queue<Vector3Int> fillQueue = new Queue<Vector3Int>();
HashSet<Vector3Int> filledCells = new HashSet<Vector3Int>();
fillQueue.Enqueue(startCellPos);
while (fillQueue.Count > 0)
{
Vector3Int cellPos = fillQueue.Dequeue();
if (filledCells.Contains(cellPos))
{
continue;
}
filledCells.Add(cellPos);
tilemap.SetTile(cellPos, selectedTile);
Vector3Int leftCell = cellPos + Vector3Int.left;
Vector3Int rightCell = cellPos + Vector3Int.right;
Vector3Int upCell = cellPos + Vector3Int.up;
Vector3Int downCell = cellPos + Vector3Int.down;
if (IsFillableTile(leftCell))
{
fillQueue.Enqueue(leftCell);
}
if (IsFillableTile(rightCell))
{
fillQueue.Enqueue(rightCell);
}
if (IsFillableTile(upCell))
{
fillQueue.Enqueue(upCell);
}
if (IsFillableTile(downCell))
{
fillQueue.Enqueue(downCell);
}
}
}
private bool IsFillableTile(Vector3Int cellPos)
{
if (tilemap.GetTile(cellPos) == null)
{
return true;
}
return false;
}
}