0
\$\begingroup\$
using UnityEngine;

public class TileTest : MonoBehaviour
{
    public int Rows;
    public int Columns;
    public float TileWidth = 1;
    public float TileHeight = 1;

    [HideInInspector]
    public Vector3 MarkerPosition;

    private void OnDrawGizmosSelected()
    {
        var mapWidth = this.Columns * this.TileWidth;
        var mapHeight = this.Rows * this.TileHeight;
        var position = this.transform.position;

        Gizmos.color = Color.white;
        Gizmos.DrawLine(position, position + new Vector3(mapWidth, 0, 0));
        Gizmos.DrawLine(position, position + new Vector3(0, mapHeight, 0));
        Gizmos.DrawLine(position + new Vector3(mapWidth, 0, 0), position + new Vector3(mapWidth, mapHeight, 0));
        Gizmos.DrawLine(position + new Vector3(0, mapHeight, 0), position + new Vector3(mapWidth, mapHeight, 0));

        Gizmos.color = Color.grey;
        for (float i = 1; i < this.Columns; i++)
        {
            Gizmos.DrawLine(position + new Vector3(i * this.TileWidth, 0, 0), position + new Vector3(i * this.TileWidth, mapHeight, 0));
        }

        for (float i = 1; i < this.Rows; i++)
        {
            Gizmos.DrawLine(position + new Vector3(0, i * this.TileHeight, 0), position + new Vector3(mapWidth, i * this.TileHeight, 0));
        }

        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(this.MarkerPosition, new Vector3(this.TileWidth, this.TileHeight, 1) * 1.1f);
    }

    public void GenerateNewMap()
    {
        
    }

    public void DestroyMap()
    {
        var Tiles = GameObject.FindGameObjectsWithTag("Tile");
        foreach (GameObject tile in Tiles)
        {
            DestroyImmediate(tile);
        }
    }
}

Then the editor :

using System;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(TileTest))]
public class TileMapEditor : Editor
{
    private Vector3 mouseHitPos;

    public override void OnInspectorGUI()
    {
        TileTest Generate = (TileTest)target;

        if (GUILayout.Button("Generate Map", GUILayout.Width(100), GUILayout.Height(30)))
        {
            Generate.GenerateNewMap();
        }

        DrawDefaultInspector();

        if (GUILayout.Button("Destroy Map", GUILayout.Width(100), GUILayout.Height(30)))
        {
            Generate.DestroyMap();
        }
    }

    private void OnSceneGUI()
    {
        if (this.UpdateHitPosition())
        {
            SceneView.RepaintAll();
        }

        this.RecalculateMarkerPosition();

        Event current = Event.current;

        if (this.IsMouseOnLayer())
        {
            if (current.type == EventType.MouseDown || current.type == EventType.MouseDrag)
            {
                if (current.button == 1)
                {
                    this.Erase();
                    current.Use();
                }
                else if (current.button == 0)
                {
                    this.Draw();
                    current.Use();
                }
            }
        }

        Handles.BeginGUI();
        GUI.Label(new Rect(10, Screen.height - 90, 100, 100), "LMB: Draw");
        GUI.Label(new Rect(10, Screen.height - 105, 100, 100), "RMB: Erase");
        Handles.EndGUI();
    }

    private void OnEnable()
    {
        Tools.current = Tool.View;
        Tools.viewTool = ViewTool.FPS;
    }

    private void Draw()
    {
        var map = (TileTest)this.target;
        var tilePos = this.GetTilePositionFromMouseLocation();
        var cube = GameObject.Find(string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y));

        if (cube != null && cube.transform.parent != map.transform)
        {
            return;
        }

        if (cube == null)
        {
            cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }

        var tilePositionInLocalSpace = new Vector3((tilePos.x * map.TileWidth) + (map.TileWidth / 2), (tilePos.y * map.TileHeight) + (map.TileHeight / 2));
        cube.transform.position = map.transform.position + tilePositionInLocalSpace;
        cube.transform.localScale = new Vector3(map.TileWidth, map.TileHeight, 1);
        cube.transform.parent = map.transform;
        cube.name = string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y);
        cube.tag = "Tile";
    }

    private void Erase()
    {
        var map = (TileTest)this.target;
        var tilePos = this.GetTilePositionFromMouseLocation();
        var cube = GameObject.Find(string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y));

        if (cube != null && cube.transform.parent == map.transform)
        {
            UnityEngine.Object.DestroyImmediate(cube);
        }
    }

    private Vector2 GetTilePositionFromMouseLocation()
    {
        var map = (TileTest)this.target;
        var pos = new Vector3(this.mouseHitPos.x / map.TileWidth, this.mouseHitPos.y / map.TileHeight, map.transform.position.z);

        pos = new Vector3((int)Math.Round(pos.x, 5, MidpointRounding.ToEven), (int)Math.Round(pos.y, 5, MidpointRounding.ToEven), 0);

        var col = (int)pos.x;
        var row = (int)pos.y;
        if (row < 0)
        {
            row = 0;
        }

        if (row > map.Rows - 1)
        {
            row = map.Rows - 1;
        }

        if (col < 0)
        {
            col = 0;
        }

        if (col > map.Columns - 1)
        {
            col = map.Columns - 1;
        }

        return new Vector2(col, row);
    }

    private bool IsMouseOnLayer()
    {
        var map = (TileTest)this.target;

        return this.mouseHitPos.x > 0 && this.mouseHitPos.x < (map.Columns * map.TileWidth) &&
               this.mouseHitPos.y > 0 && this.mouseHitPos.y < (map.Rows * map.TileHeight);
    }

    private void RecalculateMarkerPosition()
    {
        var map = (TileTest)this.target;
        var tilepos = this.GetTilePositionFromMouseLocation();
        var pos = new Vector3(tilepos.x * map.TileWidth, tilepos.y * map.TileHeight, 0);

        map.MarkerPosition = map.transform.position + new Vector3(pos.x + (map.TileWidth / 2), pos.y + (map.TileHeight / 2), 0);
    }

    private bool UpdateHitPosition()
    {
        var map = (TileTest)this.target;
        var p = new Plane(map.transform.TransformDirection(Vector3.forward), map.transform.position);
        var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
        var hit = new Vector3();
        float dist;

        if (p.Raycast(ray, out dist))
        {
            hit = ray.origin + (ray.direction.normalized * dist);
        }

        var value = map.transform.InverseTransformPoint(hit);

        if (value != this.mouseHitPos)
        {
            this.mouseHitPos = value;
            return true;
        }

        return false;
    }
}

Then in the editor script I added at the bottom the method :

public void TerrainObjects(GameObject gameobject)
    {
        Terrain terrain = Terrain.activeTerrain;
        var cube = GameObject.Find(string.Format("Terrain_{0}_{1}", gameobject.transform.position.x, gameobject.transform.position.y));
        if (cube != null)
            return;

        if (cube == null)
        {
            cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }

        cube.transform.position = new Vector3(terrain.transform.position.x + gameobject.transform.position.x, 0, terrain.transform.position.z + gameobject.transform.position.y);
        cube.transform.localScale = new Vector3(gameobject.transform.localScale.x, gameobject.transform.localScale.y, 1);
        cube.transform.parent = GameObject.Find("Terrain Map").transform;

        cube.name = string.Format("Terrain_{0}_{1}", gameobject.transform.position.x, gameobject.transform.position.y);
    }

This method create cubes on the terrain according to the positions on the grid tile map.

For example let's say the terrain is at position 0,0,0 and the tile map and terrain map objects are child of the terrain and positioned at 0,0,0

Screenshot of the terrain at 0,0,0

Terrain at position 0,0,0

Screenshot of the tile map child position 0,0,0

Tile map child at 0,0,0

And screenshot of the terrain map child also at 0,0,0

Terrain map child at 0,0,0

Now I'm clicking with the mouse left button on the grid and create some cubes and it's creating also cubes on the terrain :

Created cubes

Now I moved the terrain to position 10,0,0 Both childs tile map and terrain map moved with the terrain and they are still at 0,0,0

Now I'm clicking with the mouse on the grid again to create cubes and this time it's creating the terrain cubes on the left side of the terrain and not on the terrain.

It's only creating the cubes on the terrain when the terrain is at position 0,0,0

The cubes should be created on the terrain but they are on the left side of the terrain

How can I make that no matter where the terrain is at what position the cubes that should be create on the terrain will be on the terrain like when the terrain position is at 0,0,0 and not on the side of the terrain ?

\$\endgroup\$
2
  • \$\begingroup\$ The solution is to change to localPosition in the TerrainObjects method changing the variables terrian, gameobject, cube to localPosition solved the issue. \$\endgroup\$ – Benzi Avrumi Aug 2 '20 at 1:19
  • 1
    \$\begingroup\$ If you've solved your problem, please post your solution as an Answer below. \$\endgroup\$ – DMGregory Aug 2 '20 at 2:43
1
\$\begingroup\$

Solution is to change to localPositions :

public void TerrainObjects(GameObject gameobject)
    {
        Terrain terrain = Terrain.activeTerrain;
        var cube = GameObject.Find(string.Format("Terrain_{0}_{1}", gameobject.transform.localPosition.x, gameobject.transform.localPosition.y));
        if (cube != null)
            return;

        if (cube == null)
        {
            cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }

        //cube.transform.position = new Vector3(terrain.transform.position.x + gameobject.transform.position.x, 0, terrain.transform.position.z + gameobject.transform.position.y);
        cube.transform.localPosition = new Vector3(terrain.transform.localPosition.x + gameobject.transform.localPosition.x, 0, terrain.transform.localPosition.z + gameobject.transform.localPosition.y);
        cube.transform.localScale = new Vector3(gameobject.transform.localScale.x, gameobject.transform.localScale.y, 1);
        cube.transform.parent = GameObject.Find("Terrain Map").transform;

        cube.name = string.Format("Terrain_{0}_{1}", gameobject.transform.localPosition.x, gameobject.transform.localPosition.y);
        cube.tag = "Terrain Map";
    }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.