I need to add additional logic to TileAssets, mainly to track the terrain type. I can add a TileMapCollider2D to a TileMap and prevent a sprite from moving through the tile, but if I set the TileMapCollider2D to IsTriggerr and add a script component that handles OnTriggerEnter2D, I am getting nothing.
Of course, I can accomplish this by creating a prefab and painting with the prefab brush, but this is hardly ideal as I can’t just click within the TilePalette to select a new prefab where a preview of what it looks like would be.
You can make your own subclass of TileBase if you want to add additional functionality to tiles. I too wanted to store the terrain type to later know what sounds to play when a character walked over each tile. However, I totally cheated and just set tile.name = “grass” to avoid making my own class for now.
Thank you - I will try to wire that up at some point tomorrow during working hours and see if it will work. Another alternative that I found while poking around the 2D Extras GitHub package is to change the PrefabBrush in that repository. Currently it basically takes an array of gameobjects and randomly selects a prefab to paint into the grid. This would be easy enough to change and have it place the desired prefabs.
I use a Prefab tile object. You can simply assign the prefab to the tile object
This should work by inheriting from Tile or TileBase instead of AdvancedTile.
using UnityEngine;
using UnityEngine.Tilemaps;
// ReSharper disable once CheckNamespace
public class PrefabTile : AdvancedTile
{
public Sprite TileSprite;
public GameObject TileAssociatedPrefab;
public float PrefabLocalOffset = 0.5f;
public float prefabZOffset = -1f;
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
//This prevents rogue prefab objects from appearing when the Tile palette is present
#if UNITY_EDITOR
if (go != null)
{
if (go.scene.name == null)
{
DestroyImmediate(go);
}
}
#endif
if (go != null)
{
//Modify position of GO to match middle of Tile sprite
go.transform.position = new Vector3(position.x + PrefabLocalOffset
, position.y + PrefabLocalOffset
, prefabZOffset);
}
return true;
}
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
tileData.sprite = TileSprite;
if (TileAssociatedPrefab && tileData.gameObject==null)
{
tileData.gameObject = TileAssociatedPrefab;
}
}
}
Yes, this works perfectly! I did modify it slightly so that it can be placed under the Assets menu in the Editor. It also inherits from TileBase as you suggested.
using UnityEngine;
using UnityEngine.Tilemaps;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class PrefabTile : UnityEngine.Tilemaps.TileBase
{
public Sprite TileSprite;
public GameObject TileAssociatedPrefab;
public float PrefabLocalOffset = 0.5f;
public float prefabZOffset = -1f;
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
//This prevents rogue prefab objects from appearing when the Tile palette is present
#if UNITY_EDITOR
if (go != null)
{
if (go.scene.name == null)
{
DestroyImmediate(go);
}
}
#endif
if (go != null)
{
//Modify position of GO to match middle of Tile sprite
go.transform.position = new Vector3(position.x + PrefabLocalOffset
, position.y + PrefabLocalOffset
, prefabZOffset);
}
return true;
}
#if UNITY_EDITOR
[MenuItem("Assets/Create/Prefab Tile")]
public static void CreatePrefabTiles()
{
string path = EditorUtility.SaveFilePanelInProject("Save Prefab Tile", "New Prefab Tile", "asset", "Save Prefab Tile", "Assets");
if (path == "")
return;
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<PrefabTile>(), path);
}
#endif
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
tileData.sprite = TileSprite;
if (TileAssociatedPrefab && tileData.gameObject == null)
{
tileData.gameObject = TileAssociatedPrefab;
}
}
}
@spryx Thanks for your code. I’ve just started looking at the Tilemap system and it seems incredible to me that this functionality is not built-in.
Any how, your code works great but the sprite also gets rendered together with the prefab. Is there a way to render the sprite only on the Tile Palette window and not on the actual game (without disabling the TilemapRenderer)?
Also, I’d like to be able to see and edit the prefab on the scene view once it’s added. Currently it stays hidden on the hierarchy under the Tilemap GameObject.
The following is an updated version of the prefabTile. This is kind of a hacky workaround as the tile sprite is removed at runtime, but it works. If you want to separate the prefab instance (you may be required to do this - having a prefab tile effectively makes the prefab dependant on the tile “instance”.), I suggest doing this in a custom tile brush (See included custom brush as an example of this - this is not required for the prefab tile).
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Tilemaps;
// ReSharper disable once CheckNamespace
[CreateAssetMenu]
public class PrefabTile : AdvancedTile
{
public Sprite TileSprite;
public GameObject TileAssociatedPrefab;
public float PrefabLocalZOffset = 0f;
public bool UseAbsoluteZOffset = false;
public float PrefabAbsoluteZOffset = 0f;
public bool TileIsEditorObjectOnly = false;
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
//This prevents rogue prefab objects from appearing when the Tile palette is present
#if UNITY_EDITOR
if (go != null)
{
if (go.scene.name == null || go.scene.name == "Preview Scene")
{
DestroyImmediate(go);
}
}
#endif
if (go != null)
{
if (UseAbsoluteZOffset)
{
//Modify position of GO to match middle of Tile sprite
go.transform.position = new Vector3(position.x + Globals.PrefabXyOffset
, position.y + Globals.PrefabXyOffset
, PrefabAbsoluteZOffset);
return true;
}
//Modify position of GO to match middle of Tile sprite
go.transform.position = new Vector3(position.x + Globals.PrefabXyOffset
, position.y + Globals.PrefabXyOffset
, position.z);
//Set Z
go.transform.localPosition =
new Vector3(go.transform.localPosition.x, go.transform.localPosition.y, PrefabLocalZOffset);
}
return true;
}
#if UNITY_EDITOR
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
//Always show sprite when we are not running
if (!Application.isPlaying)
tileData.sprite = TileSprite;
else
{
//Remove sprite if we intend the sprite to be in-editor only!
tileData.sprite = TileIsEditorObjectOnly ? tileData.sprite : TileSprite;
}
if (TileAssociatedPrefab && tileData.gameObject == null)
{
tileData.gameObject = TileAssociatedPrefab;
}
tileData.flags = TileFlags.InstantiateGameObjectRuntimeOnly;
}
#endif
#if !UNITY_EDITOR
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
//Remove sprite if we intend the sprite to be in-editor only!
tileData.sprite = TileIsEditorObjectOnly ? tileData.sprite : TileSprite;
if (TileAssociatedPrefab && tileData.gameObject == null)
{
tileData.gameObject = TileAssociatedPrefab;
}
}
#endif
}
using System;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using Object = UnityEngine.Object;
[CustomEditor(typeof(PrefabTile))]
public class PrefabTileEditor : UnityEditor.Editor, IEditorPreviewsTiles
{
private PrefabTile Tile { get { return (target as PrefabTile); } }
public override void OnInspectorGUI()
{
AdvancedTileEditor.OnCustomInspectorGUI(Tile);
EditorGUI.BeginChangeCheck();
Tile.TileIsEditorObjectOnly = EditorGUILayout.Toggle("Tile Used In Editor Only", Tile.TileIsEditorObjectOnly);
Tile.PrefabLocalZOffset = EditorGUILayout.FloatField("Prefab Local Z Offset", Tile.PrefabLocalZOffset);
Tile.UseAbsoluteZOffset = EditorGUILayout.Toggle("Use Absolute Z Offset", Tile.UseAbsoluteZOffset);
Tile.PrefabAbsoluteZOffset = EditorGUILayout.FloatField("Prefab Absolute Z Offset", Tile.PrefabAbsoluteZOffset);
Tile.TileSprite = (Sprite) EditorGUILayout.ObjectField("Sprite", Tile.TileSprite, typeof(Sprite), false, null);
Tile.TileAssociatedPrefab =
(GameObject) EditorGUILayout.ObjectField("Prefab", Tile.TileAssociatedPrefab, typeof(GameObject), false);
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(Tile);
}
//For Static Preview - Start Here
public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)
{
if (GetEditorPreviewSprite() != null)
{
Type t = GetType("UnityEditor.SpriteUtility");
if (t != null)
{
MethodInfo method = t.GetMethod("RenderStaticPreview", new[] { typeof(Sprite), typeof(Color), typeof(int), typeof(int) });
if (method != null)
{
object ret = method.Invoke("RenderStaticPreview", new object[] { GetEditorPreviewSprite(), Color.white, width, height });
if (ret is Texture2D)
{
return ret as Texture2D;
}
}
}
}
return base.RenderStaticPreview(assetPath, subAssets, width, height);
}
public Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null)
return type;
if (typeName.Contains("."))
{
var assemblyName = typeName.Substring(0, typeName.IndexOf('.'));
var assembly = Assembly.Load(assemblyName);
if (assembly == null)
return null;
type = assembly.GetType(typeName);
if (type != null)
return type;
}
var currentAssembly = Assembly.GetExecutingAssembly();
var referencedAssemblies = currentAssembly.GetReferencedAssemblies();
foreach (var assemblyName in referencedAssemblies)
{
var assembly = Assembly.Load(assemblyName);
if (assembly != null)
{
type = assembly.GetType(typeName);
if (type != null)
return type;
}
}
return null;
}
//Static Preview - End Here
public Sprite GetEditorPreviewSprite()
{
return Tile.TileSprite;
}
}
using System;
using System.Reflection;
using UnityEngine.Tilemaps;
using Object = UnityEngine.Object;
public class AdvancedTile : AdvancedTileBase {
}
using UnityEngine;
using UnityEngine.Tilemaps;
public abstract class AdvancedTileBase : TileBase
{
public bool hasCollider = false;
public bool colliderDoesNotCastShadows = false;
}
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(AdvancedTile), true)]
public class AdvancedTileEditor : UnityEditor.Editor
{
public static void OnCustomInspectorGUI(AdvancedTile advancedTileObject)
{
EditorGUI.BeginChangeCheck();
advancedTileObject.hasCollider = EditorGUILayout.Toggle("Has Collider", advancedTileObject.hasCollider);
advancedTileObject.colliderDoesNotCastShadows = EditorGUILayout.Toggle("Doesn't Cast Shadows", advancedTileObject.colliderDoesNotCastShadows);
// (Sprite)EditorGUILayout.ObjectField("Sprite " + (i + 1), tile.m_AnimatedSprites[i], typeof(Sprite), false, null);
//advancedTileObject.editorSprite = (Sprite)EditorGUILayout.ObjectField("Editor Sprite", advancedTileObject.editorSprite, typeof(Sprite), false, null);
if (EditorGUI.EndChangeCheck())
{
Debug.Log("Modified advanced tile");
EditorUtility.SetDirty(advancedTileObject);
}
}
}
using System;
using UnityEngine;
using Object = UnityEngine.Object;
public interface IEditorPreviewsTiles
{
Sprite GetEditorPreviewSprite();
Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height);
Type GetType(string typeName);
}
#if UNITY_EDITOR
using System;
using Extensions;
using Tiles;
using UnityEditor;
using UnityEngine;
using UnityEngine.Tilemaps;
[CustomGridBrush(true, true, true, "DataTile Brush")]
public class DataTileBrush : GridBrush
{
public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
{
//Determine if the tile is editor only
//PrefabTile prefabTileRef = cells[0].tile as PrefabTile;
//bool tileIsEditorOnly = prefabTileRef != null && prefabTileRef.TileIsEditorObjectOnly;
//Paint the TileBase first if it is not an editor only tile
//if (!tileIsEditorOnly)
//{
base.Paint(gridLayout, brushTarget, position);
//}
//Determine if the grid selection is in the palette or is part of the scene.
bool tileWasPaintedInScene = brushTarget.gameObject.scene.name != null;
//Get Selection Tilemap
Tilemap paintTilemap = brushTarget.GetComponent<Tilemap>();
//Get GridInformation
GridInformation paintGridInfo = paintTilemap.gameObject.GetComponent<GridInformation>();
//Get the TileBase associated with the painted object
TileBase paintTile = paintTilemap.GetTile(position);
//If Painting occurs in scene, Erase all current TileBase properties
if (tileWasPaintedInScene)
{
//Erase all properties at position
paintGridInfo.EraseAllPositionPropertiesAtPosition(position);
//Check if TileBase contains properties
var tileInfo = paintTile as IDataTile;
//If TileBase contains properties, copy properties to the TileBase
if (tileInfo != null)
{
foreach (var prop in tileInfo.GetDataTileProperties())
{
switch (Globals.TypeCodes[prop.PropertyType])
{
case 0:
paintGridInfo.SetPositionProperty(position, prop.Name, (string)prop.GetValue(tileInfo, null));
break;
case 1:
paintGridInfo.SetPositionProperty(position, prop.Name, (int)prop.GetValue(tileInfo, null));
break;
case 2:
paintGridInfo.SetPositionProperty(position, prop.Name, (float)prop.GetValue(tileInfo, null));
break;
case 3:
paintGridInfo.SetPositionProperty(position, prop.Name, (double)prop.GetValue(tileInfo, null));
break;
case 4:
paintGridInfo.SetPositionProperty(position, prop.Name, (Color)prop.GetValue(tileInfo, null));
break;
case 5:
paintGridInfo.SetPositionProperty(position, prop.Name,
(UnityEngine.Object)prop.GetValue(tileInfo, null));
break;
case 6:
paintGridInfo.SetPositionProperty(position, prop.Name, (bool)prop.GetValue(tileInfo, null));
break;
}
}
}
////Instantiate Objects on tilemap
//Debug.Log("PFtilref: " + prefabTileRef?.name + " isEonly: " + tileIsEditorOnly);
//if (prefabTileRef != null && tileIsEditorOnly)
//{
// if (prefabTileRef.TileAssociatedPrefab != null)
// {
// Debug.Log("Trying to instantiate prefab");
// Instantiate(prefabTileRef.TileAssociatedPrefab, position.Fixed3DPosition(),Quaternion.identity,paintTilemap.transform);
// }
//}
}
}
public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
{
//Get Selection Tilemap
Tilemap paintTilemap = brushTarget.GetComponent<Tilemap>();
//Get GridInformation
GridInformation paintGridInfo = paintTilemap.gameObject.GetComponent<GridInformation>();
if (paintGridInfo)
{
//Erase all properties at position
paintGridInfo.EraseAllPositionPropertiesAtPosition(position);
}
//Erase Tile
base.Erase(gridLayout, brushTarget, position);
}
//Prevent moving tiles until we can find a good way to do it. (i.e. I'm too lazy to move IDataTile Properties)
public override void Move(GridLayout gridLayout, GameObject brushTarget, BoundsInt from, BoundsInt to)
{
throw new NotImplementedException();
}
public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
{
throw new NotImplementedException();
}
public override void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
{
throw new NotImplementedException();
}
}
[CustomEditor(typeof(DataTileBrush))]
public class DataTileBrushEditor : GridBrushEditor
{
public override void OnSelectionInspectorGUI()
{
//Prevents errors when leaving VS
if (!GridSelection.active || target == null)
{
return;
}
//Guistyle for informational text
GUIStyle infoGuiStyle = new GUIStyle
{
normal = new GUIStyleState
{
textColor = Color.white
},
alignment = TextAnchor.UpperCenter
};
//Get selection position
Vector3Int selectionPosition = GridSelection.position.position;
//Get Selection Tilemap
Tilemap selectionTilemap = GridSelection.target.GetComponent<Tilemap>();
//Get GridInformation
GridInformation gridInfo = selectionTilemap.gameObject.GetComponent<GridInformation>();
//Determine if the grid selection is in the palette or is part of the scene.
bool selectionIsInScene = GridSelection.grid.gameObject.scene.name != null;
#region Tile Palette
//Stop and do other things when selection is part of TileBase palette
if (!selectionIsInScene)
{
GUILayout.Label("Palette Options:");
TileBase selectedPaletteTile = selectionTilemap.GetTile(selectionPosition);
if (selectedPaletteTile == null)
{
GUILayout.Label("Selection: - N/A -");
}
else
{
//Tile has been selected
GUILayout.Label("Selection: " + selectedPaletteTile.name);
//Check for TileInfo
var tileInfo = selectedPaletteTile as IDataTile;
if (tileInfo != null)
{
GUILayout.Label("-------------------- Properties --------------------", infoGuiStyle);
var propIndex = 1;
foreach (var prop in tileInfo.GetDataTileProperties())
{
//Handle each TileBase of property
switch (Globals.TypeCodes[prop.PropertyType])
{
//String
case 0:
prop.SetValue(
tileInfo,
EditorGUILayout.TextField(
propIndex + ". " + prop.Name,
(string)prop.GetValue(tileInfo, null)),
null
);
break;
//Int
case 1:
prop.SetValue(
tileInfo,
EditorGUILayout.IntField(
propIndex + ". " + prop.Name,
(int)prop.GetValue(tileInfo, null)),
null
);
break;
//Float
case 2:
prop.SetValue(
tileInfo,
EditorGUILayout.FloatField(
propIndex + ". " + prop.Name,
(float)prop.GetValue(tileInfo, null)),
null
);
break;
//Double
case 3:
prop.SetValue(
tileInfo,
EditorGUILayout.DoubleField(
propIndex + ". " + prop.Name,
(double)prop.GetValue(tileInfo, null)),
null
);
break;
//Color
case 4:
prop.SetValue(
tileInfo,
EditorGUILayout.ColorField(
propIndex + ". " + prop.Name,
(Color)prop.GetValue(tileInfo, null)),
null
);
break;
//Object
case 5:
prop.SetValue(
tileInfo,
EditorGUILayout.ObjectField(
propIndex + ". " + prop.Name,
(UnityEngine.Object)prop.GetValue(tileInfo, null),
prop.PropertyType,
true
),
null
);
break;
//Bool
case 6:
prop.SetValue(
tileInfo,
EditorGUILayout.Toggle(
propIndex + ". " + prop.Name,
(bool)prop.GetValue(tileInfo, null)),
null
);
break;
default:
GUILayout.Label(propIndex + ". " + "Unknown Property Type");
GUILayout.Label("\tName: " + prop.Name);
GUILayout.Label("\tType: " + prop.PropertyType);
break;
}
//Increment Property Index
propIndex++;
}
}
else
{
GUILayout.Label("Not an info TileBase");
}
}
return;
}
#endregion Tile Palette
#region Scene
//Selection is in the scene
GUILayout.Label("Scene Options:");
//Get TileBase associated with selection
TileBase selectedTile = selectionTilemap.GetTile(selectionPosition);
if (selectedTile == null)
{
GUILayout.Label("Selection: - N/A -");
}
else
{
//Selected TileBase is in a scene tilemap and is not null
GUILayout.Label("Selection: " + selectedTile.name);
}
//Check if position has properties
if (gridInfo.PositionHasProperties(selectionPosition))
{
//Check if selected TileBase is a dataTile
IDataTile tileTemplateData = selectedTile as IDataTile;
if (tileTemplateData != null)
{
var propIndex = 1;
foreach (var prop in tileTemplateData.GetDataTileProperties())
{
int propertyCode = Globals.TypeCodes[prop.PropertyType];
switch (propertyCode)
{
//String
case 0:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, "-1"));
break;
//Int
case 1:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, -1));
break;
//Float
case 2:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, -1f));
break;
//Double
case 3:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, -1.0d));
break;
//Color
case 4:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, new Color(-1f, -1f, -1f)));
break;
//Object
case 5:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, new UnityEngine.Object()));
break;
//Bool
case 6:
EditorGUILayout.LabelField(propIndex + ". " + prop.Name + " : " + gridInfo.GetPositionProperty(selectionPosition, prop.Name, false));
break;
default:
GUILayout.Label(propIndex + ". " + "Unknown Property Type");
GUILayout.Label("\tName: " + prop.Name);
GUILayout.Label("\tType: " + prop.PropertyType);
GUILayout.Label(propIndex + ". " + "Cannot retrieve a value for this property");
break;
}
propIndex++;
}
}
//GUILayout.Label("Properties found here:");
////Show current properties
//foreach (var property in gridInfo.GetAllPositionPropertiesAtPosition(selectionPosition))
//{
// GUILayout.Label(property.Key + ":" + property.Value);
//}
if (GUILayout.Button("Remove"))
{
gridInfo.EraseAllPositionPropertiesAtPosition(selectionPosition);
}
if (GUILayout.Button("Clear All"))
{
gridInfo.Reset();
}
}
else
{
GUILayout.Label("No Properties Found Here");
}
//if (GUILayout.Button("Create String Data 1"))
//{
// gridInfo.SetPositionProperty(selectionPosition, "test", "1");
//}
//if (GUILayout.Button("Create String Data 2"))
//{
// gridInfo.SetPositionProperty(selectionPosition, "test2", "2");
//}
#endregion Scene
}
}
#endif
using System.Reflection;
namespace Tiles
{
public interface IDataTile
{
PropertyInfo[] GetDataTileProperties();
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEngine.Tilemaps
{
[Serializable]
public enum GridInformationType
{
Bool,
Integer,
String,
Float,
Double,
UnityObject,
Color
}
[Serializable]
[AddComponentMenu("Tilemap/Grid Information")]
public class GridInformation : MonoBehaviour, ISerializationCallbackReceiver
{
internal struct GridInformationValue
{
public GridInformationType type;
public object data;
}
[Serializable]
internal struct GridInformationKey
{
public Vector3Int position;
public String name;
}
private Dictionary<GridInformationKey, GridInformationValue> m_PositionProperties = new Dictionary<GridInformationKey, GridInformationValue>();
internal Dictionary<GridInformationKey, GridInformationValue> PositionProperties
{
get { return m_PositionProperties; }
}
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionIntKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<int> m_PositionIntValues = new List<int>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionBoolKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<bool> m_PositionBoolValues = new List<bool>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionStringKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<String> m_PositionStringValues = new List<String>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionFloatKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<float> m_PositionFloatValues = new List<float>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionDoubleKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<Double> m_PositionDoubleValues = new List<Double>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionObjectKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<Object> m_PositionObjectValues = new List<Object>();
[SerializeField]
[HideInInspector]
private List<GridInformationKey> m_PositionColorKeys = new List<GridInformationKey>();
[SerializeField]
[HideInInspector]
private List<Color> m_PositionColorValues = new List<Color>();
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
Grid grid = GetComponentInParent<Grid>();
if (grid == null)
return;
m_PositionIntKeys.Clear();
m_PositionIntValues.Clear();
m_PositionBoolKeys.Clear();
m_PositionBoolValues.Clear();
m_PositionStringKeys.Clear();
m_PositionStringValues.Clear();
m_PositionFloatKeys.Clear();
m_PositionFloatValues.Clear();
m_PositionDoubleKeys.Clear();
m_PositionDoubleValues.Clear();
m_PositionObjectKeys.Clear();
m_PositionObjectValues.Clear();
m_PositionColorKeys.Clear();
m_PositionColorValues.Clear();
foreach (var kvp in m_PositionProperties)
{
switch (kvp.Value.type)
{
case GridInformationType.Integer:
m_PositionIntKeys.Add(kvp.Key);
m_PositionIntValues.Add((int)kvp.Value.data);
break;
case GridInformationType.Bool:
m_PositionBoolKeys.Add(kvp.Key);
m_PositionBoolValues.Add((bool)kvp.Value.data);
break;
case GridInformationType.String:
m_PositionStringKeys.Add(kvp.Key);
m_PositionStringValues.Add(kvp.Value.data as String);
break;
case GridInformationType.Float:
m_PositionFloatKeys.Add(kvp.Key);
m_PositionFloatValues.Add((float)kvp.Value.data);
break;
case GridInformationType.Double:
m_PositionDoubleKeys.Add(kvp.Key);
m_PositionDoubleValues.Add((double)kvp.Value.data);
break;
case GridInformationType.Color:
m_PositionColorKeys.Add(kvp.Key);
m_PositionColorValues.Add((Color)kvp.Value.data);
break;
default:
m_PositionObjectKeys.Add(kvp.Key);
m_PositionObjectValues.Add(kvp.Value.data as Object);
break;
}
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
m_PositionProperties.Clear();
for (int i = 0; i != Math.Min(m_PositionIntKeys.Count, m_PositionIntValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.Integer;
positionValue.data = m_PositionIntValues[i];
m_PositionProperties.Add(m_PositionIntKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionBoolKeys.Count, m_PositionBoolValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.Bool;
positionValue.data = m_PositionBoolValues[i];
m_PositionProperties.Add(m_PositionBoolKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionStringKeys.Count, m_PositionStringValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.String;
positionValue.data = m_PositionStringValues[i];
m_PositionProperties.Add(m_PositionStringKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionFloatKeys.Count, m_PositionFloatValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.Float;
positionValue.data = m_PositionFloatValues[i];
m_PositionProperties.Add(m_PositionFloatKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionDoubleKeys.Count, m_PositionDoubleValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.Double;
positionValue.data = m_PositionDoubleValues[i];
m_PositionProperties.Add(m_PositionDoubleKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionObjectKeys.Count, m_PositionObjectValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.UnityObject;
positionValue.data = m_PositionObjectValues[i];
m_PositionProperties.Add(m_PositionObjectKeys[i], positionValue);
}
for (int i = 0; i != Math.Min(m_PositionColorKeys.Count, m_PositionColorValues.Count); i++)
{
GridInformationValue positionValue;
positionValue.type = GridInformationType.Color;
positionValue.data = m_PositionColorValues[i];
m_PositionProperties.Add(m_PositionColorKeys[i], positionValue);
}
}
public bool SetPositionProperty(Vector3Int position, String name, int positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.Integer, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, string positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.String, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, float positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.Float, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, double positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.Double, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, bool positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.Bool, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, UnityEngine.Object positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.UnityObject, positionProperty);
}
public bool SetPositionProperty(Vector3Int position, String name, Color positionProperty)
{
return SetPositionProperty(position, name, GridInformationType.Color, positionProperty);
}
public bool SetPositionProperty<T>(Vector3Int position, String name, T positionProperty)
{
Debug.Log(name + " - Called generic set position property");
throw new NotImplementedException("Storing this type is not accepted in GridInformation");
}
private bool SetPositionProperty(Vector3Int position, String name, GridInformationType dataType, System.Object positionProperty)
{
Grid grid = GetComponentInParent<Grid>();
if (grid != null && positionProperty != null)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
positionValue.type = dataType;
positionValue.data = positionProperty;
m_PositionProperties[positionKey] = positionValue;
return true;
}
return false;
}
public T GetPositionProperty<T>(Vector3Int position, String name, T defaultValue) where T : UnityEngine.Object
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.UnityObject)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return positionValue.data as T;
}
return defaultValue;
}
public int GetPositionProperty(Vector3Int position, String name, int defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.Integer)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (int)positionValue.data;
}
return defaultValue;
}
public bool GetPositionProperty(Vector3Int position, String name, bool defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.Bool)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (bool)positionValue.data;
}
return defaultValue;
}
public string GetPositionProperty(Vector3Int position, String name, string defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.String)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (string)positionValue.data;
}
return defaultValue;
}
public float GetPositionProperty(Vector3Int position, String name, float defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.Float)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (float)positionValue.data;
}
return defaultValue;
}
public double GetPositionProperty(Vector3Int position, String name, double defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.Double)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (double)positionValue.data;
}
return defaultValue;
}
public Color GetPositionProperty(Vector3Int position, String name, Color defaultValue)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
GridInformationValue positionValue;
if (m_PositionProperties.TryGetValue(positionKey, out positionValue))
{
if (positionValue.type != GridInformationType.Color)
throw new InvalidCastException("Value stored in GridInformation is not of the right type");
return (Color)positionValue.data;
}
return defaultValue;
}
public bool ErasePositionProperty(Vector3Int position, String name)
{
GridInformationKey positionKey;
positionKey.position = position;
positionKey.name = name;
return m_PositionProperties.Remove(positionKey);
}
public virtual void Reset()
{
m_PositionProperties.Clear();
}
public Vector3Int[] GetAllPositions(string propertyName)
{
return m_PositionProperties.Keys.ToList().FindAll(x => x.name == propertyName).Select(x => x.position).ToArray();
}
// Added for Delve
public bool PositionHasProperties(Vector3Int position)
{
return m_PositionProperties.Keys.Any(k => k.position.Equals(position));
}
public Dictionary<string, string> GetAllPositionPropertiesAtPosition(Vector3Int position)
{
Dictionary<string, string> resultList = new Dictionary<string, string>();
foreach (var key in m_PositionProperties.Keys.Where(k => k.position.Equals(position)).ToList())
{
//TODO: Refactor method to pull correct types
resultList.Add(key.name, GetPositionProperty(key.position, key.name, null));
}
return resultList;
}
public void EraseAllPositionPropertiesAtPosition(Vector3Int position)
{
foreach (var key in m_PositionProperties.Keys.Where(k => k.position.Equals(position)).ToList())
{
ErasePositionProperty(position, key.name);
}
}
}
}
The method defined in that interface is used to get properties about the tile and copy them to the tile on the tilemap. It requires a modified version of GridInformation. (Included above). It is rather difficult to store information per tile, so this has to be done in a helper class (i.e. GridInformation) that lives on the tilemap.
Object refs are a bit odd and don’t seem to work well.
Extension methods are a way to add functionality to objects without having to modify the class declaration itself. You can use them to add behavior to predefined unity objects. I will share some of mine as examples.
In this example, I add the method DirectlyMoveNonTileMapPosition to the GameObject class.
using General;
using UnityEngine;
namespace Extensions
{
public static class GameObjectExtensions
{
//public static void NudgeNonTileMapObject(this GameObject go, Vector2Int delta)
//{
// MapMovement.NudgeNonTileMapObject(go, delta.x, delta.y);
//}
//public static void AdjustNonTileMapPosition(this GameObject go)
//{
// MapMovement.AdjustNonTileMapObjectPosition(go);
//}
public static void DirectlyMoveNonTileMapPosition(this GameObject go, Vector2Int pos)
{
MapMovement.DirectMoveNonTileMapObject(go, pos);
}
}
internal static class MapMovement
{
//internal static void NudgeNonTileMapObject(GameObject go, int dX, int dY)
//{
// var goPos = go.transform.position;
// go.transform.position = new Vector3(dX * (goPos.x + dX + Globals.PrefabXyOffset),
// dY * (goPos.y + dY + Globals.PrefabXyOffset), goPos.z);
//}
//internal static void AdjustNonTileMapObjectPosition(GameObject go)
//{
// var goPos = go.transform.position;
// go.transform.position = new Vector3(goPos.x + Globals.PrefabXyOffset,
// goPos.y + Globals.PrefabXyOffset, goPos.z);
//}
internal static void DirectMoveNonTileMapObject(GameObject go, Vector2Int position)
{
go.transform.position = new Vector3(position.x + Globals.PrefabXyOffset,
position.y + Globals.PrefabXyOffset, go.transform.position.z);
}
}
}
To call the method, I need a GameObject reference. Then I can simple use reference.DirectlyMoveNonTileMapPosition(new Vector2Int(x,y);
Here is another example:
using Elements;
using UnityEngine;
using UnityEngine.Tilemaps;
using Object = UnityEngine.Object;
namespace Extensions
{
public static class TileBaseExtensions
{
public static void InstantiateMapObject(this TileBase baseTile, Tilemap instanceTileMap,
Vector2Int instancePosition)
{
InstantiateTileOrMapObject(baseTile, instanceTileMap, instancePosition);
}
private static void InstantiateTileOrMapObject(TileBase baseTile, Tilemap instanceTileMap,
Vector2Int instancePosition)
{
NonTileMapObjectTileBase nonMapTile = baseTile as NonTileMapObjectTileBase;
if (nonMapTile)
{
//Instantiate GO
GameObject nonTileMapObject = Object.Instantiate(nonMapTile.TileAssociatedPrefab,
instanceTileMap.gameObject.transform);
//Move GO
nonTileMapObject.gameObject.DirectlyMoveNonTileMapPosition(instancePosition);
//Attach non tilemap object script
NonTileMapObject objectProperties =
(NonTileMapObject)nonTileMapObject.AddComponent(typeof(NonTileMapObject));
//Get tile association to set properties
AdvancedTile advTileVersion = (AdvancedTile)baseTile;
//Set properties
objectProperties.colliderDoesNotCastShadows = advTileVersion.colliderDoesNotCastShadows;
objectProperties.hasCollider = advTileVersion.hasCollider;
}
else
{
//Instantiate TileBase if found
instanceTileMap.SetTile(new Vector3Int(instancePosition.x, instancePosition.y, 0), baseTile);
}
}
}
}
This is an example of calling one of these methods from another script:
VisualTileDefinition first = mapVisualInfo.tileDefinitions.FirstOrDefault(g => g.name == (CellTypeMatrix.First(v => v.Value == cell.CellType).Key));
VisualTileDefinition second = hasCompanionCell ? mapVisualInfo.tileDefinitions.FirstOrDefault(g => g.name == (CellTypeMatrix.First(v => v.Value == companionCell.CellType).Key)) : null;
TileBase cellTranslationTile = first != null ? first.translationTile : mapVisualInfo.defaultTile;
Tilemap instanceLocation = first != null ? first.tilemap : mapVisualInfo.defaultTileMap;
TileBase companionCellTranslationTile = hasCompanionCell ? (second != null ? second.translationTile : mapVisualInfo.defaultTile) : null;
Tilemap companionInstanceLocation = hasCompanionCell ? (second != null ? second.tilemap : mapVisualInfo.defaultTileMap) : null;
//Instantiate tile if found here. Remember that Karcero is stupid and swaps x and y coords
if (cellTranslationTile != null)
{
cellTranslationTile.InstantiateMapObject(instanceLocation, new Vector2Int(y, x));
}
Sorry to bring up this necro but I can’t seem to find any information on what I want to achieve and this is the closest there is I was able to find.
I’m using prefab tile:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace Assets.Scripts.Tiles
{
public class PrefabTile : TileBase
{
public GameObject TilePrefab;
public Sprite TileSprite => this.TilePrefab.GetComponent<SpriteRenderer>()?.sprite;
public float TileHeight = 2.56f;
public float prefabZOffset = -1f;
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
var actualTilemap = tilemap.GetComponent<Tilemap>();
var worldPosition = actualTilemap.layoutGrid.CellToWorld(position);
#if UNITY_EDITOR
if (go != null)
{
if (go.scene.name == null)
{
DestroyImmediate(go);
}
}
#endif
if (go != null)
{
// set cell position
go.GetComponent<GameTileBase>().CellPosition = position;
//Modify position of GO to match middle of Tile sprite
go.transform.position = new Vector3(
worldPosition.x,
worldPosition.y - this.TileHeight / 2,
prefabZOffset);
}
return true;
}
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
tileData.sprite = this.TileSprite;
if (this.TilePrefab && tileData.gameObject == null)
{
tileData.gameObject = this.TilePrefab;
}
}
#if UNITY_EDITOR
[MenuItem("Assets/Create/Custom/Prefab Tile")]
public static void CreatePrefabTiles()
{
string path = EditorUtility.SaveFilePanelInProject("Save Prefab Tile", "New Prefab Tile", "asset", "Save Prefab Tile", "Assets");
if (path == "")
{
return;
}
AssetDatabase.CreateAsset(CreateInstance<PrefabTile>(), path);
}
#endif
}
}
the base class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Tilemaps;
using Random = UnityEngine.Random;
namespace Assets.Scripts.Tiles
{
public class GameTileBase : MonoBehaviour, IGameTile
{
public MapManager MapManager;
public CameraControl CameraControl;
public Sprite[] PossibleStartingSprites;
public Sprite CurrentSprite;
public SpriteRenderer SpriteRenderer;
public GameObject LinkedCity { get; set; }
public GameObject GameObject => this.gameObject;
public int Income { get; set; }
public Vector3Int CellPosition;
public virtual void UpgradeTile()
{
}
public virtual void Start()
{
this.MapManager = GameObject.Find("MapManager").GetComponent<MapManager>();
this.CameraControl = Camera.main.GetComponent<CameraControl>();
this.CurrentSprite = this.PossibleStartingSprites[Random.Range(0, this.PossibleStartingSprites.Length)];
this.SpriteRenderer.sprite = this.CurrentSprite;
}
}
}
What I’m trying to do is when I click a tile it “gets upgraded” as in I remove a “PlainPrefabTile” and create a new “FarmPrefabTile” at it’s place.
I’ve tried to make a custom brush:
using Assets.Scripts.Tiles;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor.Tilemaps;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace Assets.Scripts.Extensions
{
public class PrefabTileBrush : PrefabBrush
{
public float TileHeight = 2.56f;
public float prefabZOffset = -1f;
public void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position, Object prefab)
{
Debug.Log(prefab);
base.Paint(grid, brushTarget, position);
var tilemap = brushTarget.GetComponent<Tilemap>();
var tile = tilemap.GetTile(position) as PrefabTile;
var worldPosition = tilemap.layoutGrid.CellToWorld(position);
if (tile != null)
{
var go = Instantiate(prefab);
Debug.Log(go);
//go.transform.position = new Vector3(
// worldPosition.x,
// worldPosition.y - this.TileHeight / 2,
// prefabZOffset
// );
//go.transform.rotation = Quaternion.identity;
//tile.TilePrefab = go;
}
}
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
{
var tilemap = brushTarget.GetComponent<Tilemap>();
var tile = tilemap.GetTile(position) as PrefabTile;
if (tile.TilePrefab != null)
{
DestroyImmediate(tile.TilePrefab, false);
}
base.Erase(grid, brushTarget, position);
}
}
}
and try to create it like so:
public Object CreateTile(TileTypes type, Vector3 position, Quaternion quaternion, Vector3Int cellPosition)
{
var originalTile = this.GetTile(cellPosition);
Debug.Log(originalTile);
if (originalTile != null)
{
this.Brush.Erase(this.GameMap, this.GameMap.gameObject, cellPosition);
}
Object result = null;
if (type == TileTypes.Farm)
{
this.Brush.Paint(this.GameMap, this.GameMap.gameObject, cellPosition, this.farmPrefabTile);
//result = Instantiate(this.farmPrefabTile, position, quaternion, this.GameMap.gameObject.transform);
}
else if (type == TileTypes.Forester)
{
result = Instantiate(this.foresterPrefabTile, position, quaternion, this.GameMap.gameObject.transform);
}
Debug.Log(result);
return result;
}
It won’t let me erase it (seems like the original prefab isn’t an instance, but the prefab itself) and it won’t allow me to destroy assets, if I change the tile to instantiate the prefab there are then 2 objects on the grid, and the instantiation of the farmPrefabTile returns null (inside the PrefabTileBrush.Paint() method). Any ideas or clues how to achieve this
EDIT: I painted the game with a Tile Palette (dragged the PrefabTileAssets (one for each tile type):
I haven’t messed with gameobjects on tiles, but it appears that you’re missing modifying the tileData of the tile. There’s a gameobject field there, which should give you the instance of the prefab on that tile. If you were to destroy that gameobject, and assign your own new “upgrade” gameobject to that field with your brush, you may find that’s sufficient to fix the problem. To do that, it might be easiest to swap the tile w/ .SetTile(…) with the brush to a different tile associated with the “upgrade” prefab.
The thing is I created the asset for each tile type, so when upgrading plainTile it’s of that type and I don’t want to just change the gameobject but the whole thing. I could revert it to have one asset with different prefabs attached but I couldnt then have each in the tile palette to easily create levels. I’m missing something and its hard to find similar solutions to this
Have you tried Tilemap.GetTile.GetTileData
Then gameObject from the TileData?
This should be enough to get the go ref on the tile and you can destroy it or do whatever. I’m pretty sure though if you set the tile again Unity will destroy it, assuming you are allowing Unity to handle the instantiation.
Also, are you manually instantiating the prefabs? You shouldn’t have to do that if you assign the
tileData.gameObject, Unity will instantiate them for you (most likely why you are seeing two).
You seem to already be doing what you need to for Unity to instantiate it (PrefabTile, Line 55).
EDIT: You are instantiating the prefabs twice.
Unity is handling one for you and you are also doing it in
brush.paint() (Line 28) var go = Instantiate(prefab);
Also, why are you using so many GameObjects? Fair enough if they need behavior, but that is going to create a lot of overhead. Tiles and GameObjects are two separate things - if you can get away with just tiles, you should try to do that.
Sorry, I’m rather new. What would the paint method look like please? I’m passing an Object, but it’s null (the instantiation), if I pass it from the create method, I don’t know how to properly instantiate it there
EDIT: yeah most of them need the behavior as most of them can be level/changed (that’s the part I can’t seem to get to work)
I’d really need to see more about where [quote]
public Object CreateTile…
[/quote] came from.
My point is that you don’t need to worry about instantiating the prefabs at all or even using a prefab brush if you are already assigning TilePrefab to the PrefabTile asset. Unity will handle this for you. (See TileData.gameObject).
If you use a prefab tile brush (like you are currently), you are just instantiating the gameobjects again. (unneeded).
My advice: try using the standard GridBrush (or whatever is default) to paint the tiles. Any prefabs you have assigned to the tile asset should be instantiated for you when Unity creates the tile instance (after you click play of course).
You can still have your game logic scripts on the prefab that is instantiated.
Yes when I play the scene it correctly instantiates the proper tiles and everything works fine, but I can’t seem to make it work when I want to “repaint” a tile.
How can I paint a tile in runtime, using just the grid brush? How do I pass in the asset?
I passed the asset as object to my script:
How do I pass it to the paint though?
public Object farmPrefabTile;
public Object foresterPrefabTile;
public GridBrush Brush => ScriptableObject.CreateInstance<GridBrush>();
private List<IGameTile> AllGameTiles { get; set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this.gameObject);
}
else
{
Instance = this;
}
}
public void Start()
{
this.AllGameTiles = FindObjectsOfType<MonoBehaviour>()
.OfType<IGameTile>()
.ToList();
}
public void RemoveTile(Object tile)
{
Destroy(tile);
}
public void CreateTile(TileTypes type, Vector3 position, Quaternion quaternion, Vector3Int cellPosition)
{
var originalTile = this.GetTile(cellPosition);
if (type == TileTypes.Farm)
{
this.Brush.Paint(this.GameMap, this.GameMap.gameObject, cellPosition); // farmPrefabTile ???
}
else if (type == TileTypes.Forester)
{
}
}
Thanks for your input mate, I’m so lost in here for days