0

I want to use GetComponent. This script is not attached to any Gameobject:

namespace CBX.Unity.Editors.Editor
{
    using System;
    using CBX.TileMapping.Unity;
    using UnityEditor;
    using UnityEngine;

    /// <summary>
    /// Provides a editor for the <see cref="TileMap"/> component
    /// </summary>
    [CustomEditor(typeof(TileMap))]
    public class TileMapEditor : Editor
    {
        /// <summary>
        /// Holds the location of the mouse hit location
        /// </summary>
        private Vector3 mouseHitPos;

        /// <summary>
        /// Lets the Editor handle an event in the scene view.
        /// </summary>
        /// 

        private void OnSceneGUI()
        {
            // if UpdateHitPosition return true we should update the scene views so that the marker will update in real time
            if (this.UpdateHitPosition())
            {
                SceneView.RepaintAll();
            }

            // Calculate the location of the marker based on the location of the mouse
            this.RecalculateMarkerPosition();

            // get a reference to the current event
            Event current = Event.current;

            // if the mouse is positioned over the layer allow drawing actions to occur
            if (this.IsMouseOnLayer())
            {
                // if mouse down or mouse drag event occurred
                if (current.type == EventType.MouseDown || current.type == EventType.MouseDrag)
                {
                    if (current.button == 1)
                    {
                        // if right mouse button is pressed then we erase blocks
                        this.Erase();
                        current.Use();
                    }
                    else if (current.button == 0)
                    {
                        // if left mouse button is pressed then we draw blocks
                        this.Draw();
                        current.Use();
                    }
                }
            }

            // draw a UI tip in scene view informing user how to draw & erase tiles
            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();
        }

        /// <summary>
        /// When the <see cref="GameObject"/> is selected set the current tool to the view tool.
        /// </summary>
        private void OnEnable()
        {
            Tools.current = Tool.View;
            Tools.viewTool = ViewTool.FPS;
        }

        /// <summary>
        /// Draws a block at the pre-calculated mouse hit position
        /// </summary>
        private void Draw()
        {
            // get reference to the TileMap component
            var map = (TileMap)this.target;

            // Calculate the position of the mouse over the tile layer
            var tilePos = this.GetTilePositionFromMouseLocation();

            // Given the tile position check to see if a tile has already been created at that location
            var cube = GameObject.Find(string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y));

            // if there is already a tile present and it is not a child of the game object we can just exit.
            if (cube != null && cube.transform.parent != map.transform)
            {
                return;
            }

            // if no game object was found we will create a cube
            if (cube == null)
            {
                cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            }

            // set the cubes position on the tile map
            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;

            // we scale the cube to the tile size defined by the TileMap.TileWidth and TileMap.TileHeight fields 
            cube.transform.localScale = new Vector3(map.TileWidth, map.TileHeight, 1);

            // set the cubes parent to the game object for organizational purposes
            cube.transform.parent = map.transform;

            // give the cube a name that represents it's location within the tile map
            cube.name = string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y);

            // give the cube a tag
            cube.tag = "GridObject";

            TerrainObjects(cube);
        }

        public GameObject TerrainObjects(GameObject gameobject)
        {
            return gameobject;
        }

        /// <summary>
        /// Erases a block at the pre-calculated mouse hit position
        /// </summary>
        private void Erase()
        {
            // get reference to the TileMap component
            var map = (TileMap)this.target;

            // Calculate the position of the mouse over the tile layer
            var tilePos = this.GetTilePositionFromMouseLocation();

            // Given the tile position check to see if a tile has already been created at that location
            var cube = GameObject.Find(string.Format("Tile_{0}_{1}", tilePos.x, tilePos.y));
            var terrainObject = GameObject.Find(string.Format("Terrain_{0}_{1}", Terrain.activeTerrain.transform.position.x + tilePos.x, Terrain.activeTerrain.transform.position.z + tilePos.y));

            // if a game object was found with the same name and it is a child we just destroy it immediately
            if (cube != null && cube.transform.parent == map.transform)
            {
                UnityEngine.Object.DestroyImmediate(cube);
            }

            if (terrainObject != null && terrainObject.transform.parent == map.transform)
            {
                DestroyImmediate(terrainObject);
            }
        }

        /// <summary>
        /// Calculates the location in tile coordinates (Column/Row) of the mouse position
        /// </summary>
        /// <returns>Returns a <see cref="Vector2"/> type representing the Column and Row where the mouse of positioned over.</returns>
        private Vector2 GetTilePositionFromMouseLocation()
        {
            // get reference to the tile map component
            var map = (TileMap)this.target;

            // calculate column and row location from mouse hit location
            var pos = new Vector3(this.mouseHitPos.x / map.TileWidth, this.mouseHitPos.y / map.TileHeight, map.transform.position.z);

            // round the numbers to the nearest whole number using 5 decimal place precision
            pos = new Vector3((int)Math.Round(pos.x, 5, MidpointRounding.ToEven), (int)Math.Round(pos.y, 5, MidpointRounding.ToEven), 0);

            // do a check to ensure that the row and column are with the bounds of the tile map
            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 the column and row values
            return new Vector2(col, row);
        }

        /// <summary>
        /// Returns true or false depending if the mouse is positioned over the tile map.
        /// </summary>
        /// <returns>Will return true if the mouse is positioned over the tile map.</returns>
        private bool IsMouseOnLayer()
        {
            // get reference to the tile map component
            var map = (TileMap)this.target;

            // return true or false depending if the mouse is positioned over the map
            return this.mouseHitPos.x > 0 && this.mouseHitPos.x < (map.Columns * map.TileWidth) &&
                   this.mouseHitPos.y > 0 && this.mouseHitPos.y < (map.Rows * map.TileHeight);
        }

        /// <summary>
        /// Recalculates the position of the marker based on the location of the mouse pointer.
        /// </summary>
        private void RecalculateMarkerPosition()
        {
            // get reference to the tile map component
            var map = (TileMap)this.target;

            // store the tile location (Column/Row) based on the current location of the mouse pointer
            var tilepos = this.GetTilePositionFromMouseLocation();

            // store the tile position in world space
            var pos = new Vector3(tilepos.x * map.TileWidth, tilepos.y * map.TileHeight, 0);

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

        /// <summary>
        /// Calculates the position of the mouse over the tile map in local space coordinates.
        /// </summary>
        /// <returns>Returns true if the mouse is over the tile map.</returns>
        private bool UpdateHitPosition()
        {
            // get reference to the tile map component
            var map = (TileMap)this.target;

            // build a plane object that 
            var p = new Plane(map.transform.TransformDirection(Vector3.forward), map.transform.position);

            // build a ray type from the current mouse position
            var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);

            // stores the hit location
            var hit = new Vector3();

            // stores the distance to the hit location
            float dist;

            // cast a ray to determine what location it intersects with the plane
            if (p.Raycast(ray, out dist))
            {
                // the ray hits the plane so we calculate the hit location in world space
                hit = ray.origin + (ray.direction.normalized * dist);
            }

            // convert the hit location from world space to local space
            var value = map.transform.InverseTransformPoint(hit);

            // if the value is different then the current mouse hit location set the 
            // new mouse hit location and return true indicating a successful hit test
            if (value != this.mouseHitPos)
            {
                this.mouseHitPos = value;
                return true;
            }

            // return false if the hit test failed
            return false;
        }
    }
}

In this script i also added a public method

public GameObject TerrainObjects(GameObject gameobject)
{
    return gameobject;
}

And I want to get access to this method TerrainObjects from another script:

This script is attached to a GameObject:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TerrainObjects : MonoBehaviour {

    // Use this for initialization
    void Start ()
    {
      GetComponent<tile>
    }

    // Update is called once per frame
    void Update ()
    {

    }
}

I'm trying to type tile or TileMap or TileMapEditor but it's not exist. So i can't make Getcomponent of this script.

In the Start i tried to type:

GetComponent<tile>

But I can't access the TileMapEditor.

Is there any way to get access to it ? If it's editor type script should i attach to the same gameobject as the TerrainObjects script ?

I don't want that the TileMapEditor will work in game only in scene.

4
  • 1
    I would not expect TileMapEditor to be attached to a game object due to it being a editor component. Also, you need to show your code where you used GetComponent and it did not work Commented Jun 7, 2017 at 21:27
  • 1
    But that method doesn't do anything... Commented Jun 7, 2017 at 21:28
  • @RufusL you right i updated the question with the TileMapEditor full code. and i'm using the method TerrainObjects inside the Draw in the TileMapEditor. What i want to do is each time in real time when i create a cube in the TileMapEditor send the gameobject to the TerrainObjects script so i can use this gameobject. Commented Jun 7, 2017 at 21:45
  • I want in the TerrainObjects script to take from the returned gameobject in the TerrainObjects method some information like position,scale,rotation,tag,name....Then make manipulation with the gameobject info in the TerrainObjects script. Commented Jun 7, 2017 at 21:47

2 Answers 2

2

I assume this is an Editor plugin. GetComponent should not work for scripts that inherits from the Editor. You need to use Resources.FindObjectsOfTypeAll to find TileMapEditor then call its function (TerrainObjects).

If there is one instance of TileMap, use index 0 to call the function. If there are many of them then loop through them and call their functions.

TileMapEditor[] tpEditorInstance = (TileMapEditor[])Resources.FindObjectsOfTypeAll(typeof(TileMapEditor));

//Make sure it is not null
if (tpEditorInstance != null && tpEditorInstance.Length > 0)
{
    tpEditorInstance[0].TerrainObjects(gameObject);
}
else
{
    Debug.Log("TileMapEditor is Null");
}

EDIT:

TileMapEditor is not exist in the TerrainObjects script.

Don't really understand that but remember that your TileMapEditor script is in another namespace called "CBX.Unity.Editors.Editor". You have to import that namespace too in any script that will access TileMapEditor.

Just add using CBX.Unity.Editors.Editor; to the top of each script that will access the TileMapEditor script.

Sign up to request clarification or add additional context in comments.

4 Comments

TileMapEditor is not exist in the TerrainObjects script. I cant add there the line TileMapEditor[] tpEditorInstance = (TileMapEditor[])Resources.FindObjectsOfTypeAll(typeof(TileMapEditor));
TileMap is a script that attached to a gameobject but not accessing to the TileMapEditor.
Please carefully read the answer again. I never mentioned TerrainObjects script in my answer. I only mentioned the TerrainObjects function in your TileMapEditor script. This is why you should not name function and class the-same name as that is confusing you now. You want to call TerrainObjects function from the TileMapEditor script? That's what is in my answer.
Also check my Edit about namespace.
0

In my case, creating a folder under Assets named Editor solved it. I see that this has been a long inactive post, and making a dir for editor mode only scripts should be a standard convention, but I'm still leaving my solution here in case anyone needs it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.