Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question Selecting/Moving both tiles and gameobjects with one brush via Tile Palette tools... is it possible?

Discussion in '2D' started by sakamoto-kun, May 24, 2023.

  1. sakamoto-kun

    sakamoto-kun

    Joined:
    Dec 11, 2019
    Posts:
    5
    I'm currently painting tiles using the Default Brush and painting GameObjects with the GameObject Brush on to the same tile map. When I need to move/rearrange sections of a level that include both (which is the case 90% of the time) I have to swap between these two brushes, reselect, and realign everything which can become quite tedious, especially if the level needs lots of adjustments. Is it possible to manipulate both using one brush?

    --

    Attempting to work around this, I noticed that in the Default Brush/GridBrush script (2022.2.x) there are comments about using the Default Brush to paint/manipulate both tiles and GameObjects (presumably only when created with the same brush type), but I cannot get it to paint GameObjects. Does this functionality still exist within the Default Brush?

    I can't be the only one experiencing this pain point, am I missing something?

    Unity 2022.2.x
     
  2. vonchor

    vonchor

    Joined:
    Jun 30, 2009
    Posts:
    238
    If you add the gameobject to the tile asset then when you paint the tile the GO will appear. Moving the tile will move both.

    only problems:

    1. Tile sprite can interfere with the gameobject visually but you can compensate for that.

    2. You can’t see the gameobject in the tile palette

    Thats the only native way to do what you ask without some custom software
     
  3. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    You could try this custom brush script which combines both the Default Brush and the GameObject Brush:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Tilemaps;
    3.  
    4. namespace UnityEditor.Tilemaps
    5. {
    6.     [CustomGridBrush(true, false, false, "Default+GameObject Brush")]
    7.     public class DefaultGameObjectBrush : GridBrush
    8.     {
    9.         [SerializeField]
    10.         internal GridBrushBase[] gridBrushes;
    11.  
    12.         public void ValidateBrushes()
    13.         {
    14.             if (gridBrushes == null
    15.                 || gridBrushes.Length == 0
    16.                 || gridBrushes[0] == null)
    17.             {
    18.                 gridBrushes = new GridBrushBase[2];
    19.                 gridBrushes[0] = ScriptableObject.CreateInstance<GridBrush>();
    20.                 gridBrushes[1] = ScriptableObject.CreateInstance<GameObjectBrush>();
    21.             }
    22.         }
    23.        
    24.         public override void Select(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
    25.         {
    26.             ValidateBrushes();
    27.             for (int i = 0; i < gridBrushes.Length; ++i)
    28.                 gridBrushes[i].Select(gridLayout, brushTarget, position);
    29.         }
    30.  
    31.         public override void Move(GridLayout gridLayout, GameObject brushTarget, BoundsInt from, BoundsInt to)
    32.         {
    33.             ValidateBrushes();
    34.             for (int i = 0; i < gridBrushes.Length; ++i)
    35.                 gridBrushes[i].Move(gridLayout, brushTarget, from, to);
    36.         }
    37.  
    38.         public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
    39.         {
    40.             ValidateBrushes();
    41.             for (int i = 0; i < gridBrushes.Length; ++i)
    42.                 gridBrushes[i].MoveStart(gridLayout, brushTarget, position);
    43.         }
    44.  
    45.         public override void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
    46.         {
    47.             ValidateBrushes();
    48.             for (int i = 0; i < gridBrushes.Length; ++i)
    49.                 gridBrushes[i].MoveEnd(gridLayout, brushTarget, position);
    50.         }
    51.  
    52.         public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
    53.         {
    54.             ValidateBrushes();
    55.             for (int i = 0; i < gridBrushes.Length; ++i)
    56.                 gridBrushes[i].Paint(gridLayout, brushTarget, position);
    57.         }
    58.  
    59.         public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
    60.         {
    61.             ValidateBrushes();
    62.             for (int i = 0; i < gridBrushes.Length; ++i)
    63.                 gridBrushes[i].Erase(gridLayout, brushTarget, position);
    64.         }
    65.  
    66.         public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, Vector3Int pickStart)
    67.         {
    68.             ValidateBrushes();
    69.             for (int i = 0; i < gridBrushes.Length; ++i)
    70.                 gridBrushes[i].Pick(gridLayout, brushTarget, position, pickStart);
    71.             base.Pick(gridLayout, brushTarget, position, pickStart);
    72.         }
    73.  
    74.         public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
    75.         {
    76.             ValidateBrushes();
    77.             for (int i = 0; i < gridBrushes.Length; ++i)
    78.                 gridBrushes[i].FloodFill(gridLayout, brushTarget, position);
    79.         }
    80.  
    81.         public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
    82.         {
    83.             ValidateBrushes();
    84.             for (int i = 0; i < gridBrushes.Length; ++i)
    85.                 gridBrushes[i].BoxFill(gridLayout, brushTarget, position);
    86.         }
    87.  
    88.         public override void Flip(FlipAxis flip, GridLayout.CellLayout layout)
    89.         {
    90.             ValidateBrushes();
    91.             foreach (var gridBrush in gridBrushes)
    92.             {
    93.                 gridBrush.Flip(flip, layout);
    94.             }
    95.         }
    96.  
    97.         public override void Rotate(RotationDirection direction, GridLayout.CellLayout layout)
    98.         {
    99.             ValidateBrushes();
    100.             foreach (var gridBrush in gridBrushes)
    101.             {
    102.                 gridBrush.Rotate(direction, layout);
    103.             }
    104.         }
    105.  
    106.         public override void ChangeZPosition(int change)
    107.         {
    108.             ValidateBrushes();
    109.             foreach (var gridBrush in gridBrushes)
    110.             {
    111.                 gridBrush.ChangeZPosition(change);
    112.             }
    113.         }
    114.  
    115.         public override void ResetZPosition()
    116.         {
    117.             ValidateBrushes();
    118.             foreach (var gridBrush in gridBrushes)
    119.             {
    120.                 gridBrush.ResetZPosition();
    121.             }
    122.         }
    123.     }
    124.  
    125.     /// <summary>
    126.     /// The Brush Editor for a Layer Brush.
    127.     /// </summary>
    128.     [CustomEditor(typeof(DefaultGameObjectBrush))]
    129.     public class DefaultGameObjectBrushEditor : GridBrushEditor
    130.     {
    131.         public DefaultGameObjectBrush targetBrush
    132.         {
    133.             get
    134.             {
    135.                 return target as DefaultGameObjectBrush;
    136.             }
    137.         }
    138.  
    139.         private GridBrushEditorBase[] editors;
    140.  
    141.         private void CreateEditor()
    142.         {
    143.             targetBrush.ValidateBrushes();
    144.             if (targetBrush.gridBrushes != null
    145.                 && (editors == null
    146.                 || editors.Length != targetBrush.gridBrushes.Length
    147.                 || editors[0] == null))
    148.             {
    149.                 editors = new GridBrushEditorBase[targetBrush.gridBrushes.Length];
    150.                 for (int i = 0; i < editors.Length; ++i)
    151.                 {
    152.                     editors[i] = Editor.CreateEditor(targetBrush.gridBrushes[i]) as GridBrushEditorBase;
    153.                 }
    154.             }
    155.         }
    156.  
    157.         public override void RegisterUndo(GameObject brushTarget, GridBrushBase.Tool tool)
    158.         {
    159.             var undoObjects = new UnityEngine.Object[2];
    160.             undoObjects[0] = brushTarget;
    161.             undoObjects[1] = brushTarget.GetComponent<Tilemap>();
    162.             Undo.RegisterCompleteObjectUndo(undoObjects, tool.ToString());
    163.         }
    164.  
    165.         public override void OnPaintSceneGUI(GridLayout gridLayout, GameObject brushTarget, BoundsInt position,
    166.             GridBrushBase.Tool tool, bool executing)
    167.         {
    168.             CreateEditor();
    169.             for (int i = 0; i < editors.Length; ++i)
    170.             {
    171.                 editors[i].OnPaintSceneGUI(gridLayout, brushTarget, position, tool, executing);
    172.             }
    173.         }
    174.  
    175.         public override void PaintPreview(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
    176.         {
    177.             CreateEditor();
    178.             for (int i = 0; i < editors.Length; ++i)
    179.             {
    180.                 var editor = editors[i] as GridBrushEditor;
    181.                 if (editor != null)
    182.                     editor.PaintPreview(gridLayout, brushTarget, position);
    183.             }
    184.         }
    185.  
    186.         public override void BoxFillPreview(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
    187.         {
    188.             CreateEditor();
    189.             for (int i = 0; i < editors.Length; ++i)
    190.             {
    191.                 var editor = editors[i] as GridBrushEditor;
    192.                 if (editor != null)
    193.                     editor.BoxFillPreview(gridLayout, brushTarget, position);
    194.             }
    195.         }
    196.  
    197.         public override void FloodFillPreview(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
    198.         {
    199.             CreateEditor();
    200.             for (int i = 0; i < editors.Length; ++i)
    201.             {
    202.                 var editor = editors[i] as GridBrushEditor;
    203.                 if (editor != null)
    204.                     editor.FloodFillPreview(gridLayout, brushTarget, position);
    205.             }
    206.         }
    207.  
    208.         public override void ClearPreview()
    209.         {
    210.             CreateEditor();
    211.             if (editors != null)
    212.             {
    213.                 foreach (var editor in editors)
    214.                 {
    215.                     var gridBrushEditor = editor as GridBrushEditor;
    216.                     if (gridBrushEditor != null)
    217.                         gridBrushEditor.ClearPreview();
    218.                 }
    219.             }
    220.         }
    221.     }
    222. }
     
    Chubzdoomer and sakamoto-kun like this.
  4. sakamoto-kun

    sakamoto-kun

    Joined:
    Dec 11, 2019
    Posts:
    5
    I'm not sure I follow, I could not get this to work in 2022.3.x.

    Incredible, thank you for this script! Does exactly what I'd hoped.