User:Mfcas

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(2D tile editor, uses undocumented API (tested for 3.4.1f))
 
(Blanked the page)
 
Line 1: Line 1:
A simple tile editor script.
 
  
Here's how you use it, first import those two scripts, the first one can be anywhere, you probably want to place it with your game scripts.
 
 
<csharp>
 
using UnityEngine;
 
using System.Collections;
 
using System.Collections.Generic;
 
 
public class Tiles : MonoBehaviour
 
{
 
//the size of the grid, sometimes non-square grid may be useful
 
public float width = 32.0f;
 
public float height = 32.0f;
 
 
//offset, just in case someone wants to adjust the position of the grid
 
public float offsetX = 0.0f;
 
public float offsetY = 0.0f;
 
 
//the color of the lines, someone it has to be adjusted for better visibility
 
public Color color = Color.white;
 
 
//shortcuts
 
public string drawKey = "";
 
public string deleteKey = "";
 
public string disableKey = "";
 
public string alignKey = "";
 
public string setParentKey = "";
 
 
//depth += 1.0f shortcut
 
public string incDepthKey = "";
 
//depth -= 1.0f shortcut
 
public string decDepthKey = "";
 
 
//depth at which the tiles are placed
 
public float depth = 0.0f;
 
 
//objects' offset from grid
 
public float objOffsetX = 0.0f;
 
public float objOffsetY = 0.0f;
 
 
//is tile placing enabled
 
public bool enabled = false;
 
 
//the tiles' parent object
 
public Transform parent;
 
 
void OnDrawGizmos()
 
{
 
                if (!enabled)
 
return false;
 
 
//Camera.current gets us the sceneview's camera
 
Camera c = Camera.current;
 
Vector3 cPos = c.transform.position;
 
 
Gizmos.color = color;
 
 
//draw horizontal lines... I cheat length and how many lines are drawn a bit here, ugly but works
 
//float.MinValue, float.MaxValue and float.NegativeInfinity, float.PositiveInfinity didn't work
 
for (float y = cPos.y - c.orthographicSize*4.0f; y < cPos.y + c.orthographicSize*4.0f; y+= height)
 
{
 
 
Gizmos.DrawLine(new Vector3(-1000000.0f, Mathf.Floor(y/height) * height + offsetY, 0.0f),
 
new Vector3(1000000.0f, Mathf.Floor(y/height) * height + offsetY, 0.0f));
 
}
 
 
//pretty much the same thing for the vertical lines
 
for (float x = cPos.x - c.orthographicSize*4.0f; x < cPos.x + c.orthographicSize*4.0f; x+= height)
 
{
 
 
Gizmos.DrawLine(new Vector3(Mathf.Floor(x/width) * width + offsetX, -1000000.0f, 0.0f),
 
new Vector3(Mathf.Floor(x/width) * width + offsetX, 1000000.0f, 0.0f));
 
}
 
}
 
}
 
</csharp>
 
 
The second script you need to place in the Editor folder, it extends the Tiles class.
 
 
<csharp>
 
using UnityEngine;
 
using UnityEditor;
 
using System.Collections;
 
 
[CustomEditor (typeof(Tiles))]
 
public class TilesEditor : Editor
 
{
 
Tiles tileMgr;
 
 
//last aligned pos, we'll use it to _NOT_ create multiple tiles in the same place
 
bool lastPosSet = false;
 
Vector3 lastPos;
 
 
//have any tiles been moved? We'll use that for Undo
 
bool moved = false;
 
 
//have tiles been painted? We'll use that for Undo
 
bool painted = false;
 
 
//have tiles been deleted? We'll use that for Undo
 
bool deleted = false;
 
 
void OnEnable()
 
{
 
tileMgr = (Tiles)target;
 
SceneView.onSceneGUIDelegate += UpdateTiles;
 
}
 
 
void UpdateTiles(SceneView sceneview)
 
{
 
//get the current event
 
Event e = Event.current;
 
 
//if the toggle key is set and was pressed, change then toggle activation
 
if ((tileMgr.disableKey != "") && (e.isKey && e.character == tileMgr.disableKey[0]))
 
tileMgr.enabled = false;
 
 
//if disabled, return
 
if (tileMgr.enabled == false)
 
return;
 
 
//calculating the world space mouse position in the scene view
 
Vector3 tmp = new Vector3(e.mousePosition.x, -e.mousePosition.y + Camera.current.pixelHeight);
 
Ray r = Camera.current.ScreenPointToRay(tmp);
 
Vector3 mousePos = new Vector3(r.origin.x, r.origin.y, tileMgr.depth);
 
 
//aligning to grid
 
Vector3 aligned = new Vector3(
 
Mathf.Floor((mousePos.x - tileMgr.offsetX)/tileMgr.width)*tileMgr.width + tileMgr.width/2.0f + (tileMgr.offsetX) + tileMgr.objOffsetX,
 
Mathf.Floor((mousePos.y - tileMgr.offsetY)/tileMgr.height)*tileMgr.height + tileMgr.height/2.0f + (tileMgr.offsetY) + tileMgr.objOffsetY,
 
tileMgr.depth);
 
 
//if drawKey is set then draw the aligned tile
 
if ((tileMgr.setParentKey != "") && (e.isKey && e.character == tileMgr.setParentKey[0]))
 
{
 
if (Selection.activeObject != null)
 
tileMgr.parent = (Transform)Selection.activeObject;
 
}
 
else if ((tileMgr.drawKey != "") && (e.isKey && e.character == tileMgr.drawKey[0]))
 
{
 
if ((lastPos == aligned) && lastPosSet)
 
return;
 
 
if (Selection.activeObject == null)
 
return;
 
 
if (!painted)
 
{
 
Undo.IncrementCurrentEventIndex(); //Create undo state for the tile painting
 
painted = true;
 
}
 
 
//if there's already a tile, delete it
 
if (tileMgr.parent != null)
 
{
 
foreach (Transform child in tileMgr.parent)
 
{
 
//we don't care about depth while deleting
 
if (child.position.x == aligned.x && child.position.y == aligned.y)
 
{
 
DestroyImmediate(child.gameObject);
 
break;
 
}
 
}
 
}
 
 
//our new tile
 
GameObject obj;
 
 
//get the tile's prefab
 
Object prefab = EditorUtility.GetPrefabParent(Selection.activeObject);
 
 
//if prefab exists, create from prefab, if not the simply clone
 
if (prefab)
 
obj = (GameObject)EditorUtility.InstantiatePrefab(prefab);
 
else
 
obj = (GameObject)Instantiate(Selection.activeObject);
 
 
Undo.RegisterCreatedObjectUndo(obj, "Create " + obj.name);
 
//set the tile's position and parent
 
obj.transform.position = aligned;
 
obj.transform.parent = tileMgr.parent;
 
 
//Debug.Log("Created Tile at " + aligned); //logging where the tile was placed in world space
 
lastPos = aligned;
 
lastPosSet = true;
 
}
 
else if ((tileMgr.deleteKey != "") && (e.isKey && e.character == tileMgr.deleteKey[0]))
 
{
 
//we delete only inside the parent object, it could be a mess to use hierarchy for that
 
if (tileMgr.parent != null)
 
{
 
if (!deleted)
 
{
 
Undo.IncrementCurrentEventIndex();
 
Undo.RegisterSceneUndo("Delete Tiles");
 
deleted = true;
 
}
 
 
foreach (Transform child in tileMgr.parent)
 
{
 
//we don't care about depth while deleting
 
if (child.position.x == aligned.x && child.position.y == aligned.y)
 
{
 
DestroyImmediate(child.gameObject);
 
break;
 
}
 
}
 
 
}
 
}
 
else if ((tileMgr.alignKey != "") && (e.isKey && e.character == tileMgr.alignKey[0]))
 
{
 
//we align only if there are selected objects
 
if (Selection.transforms.Length > 0)
 
{
 
if (!moved)
 
{
 
Undo.IncrementCurrentEventIndex();
 
Undo.RegisterSceneUndo("Move Tiles");
 
moved = true;
 
}
 
 
Vector3 posOffset = aligned - Selection.transforms[0].position;
 
Selection.transforms[0].position = aligned;
 
 
for (int i = 1; i < Selection.transforms.Length; ++i)
 
Selection.transforms[i].position += posOffset;
 
}
 
}
 
else if ((tileMgr.incDepthKey != "") && (e.isKey && e.character == tileMgr.incDepthKey[0]))
 
{
 
tileMgr.depth += 1.0f;
 
Debug.Log("Now placing tiles at Z equal to " + tileMgr.depth);
 
}
 
else if ((tileMgr.decDepthKey != "") && (e.isKey && e.character == tileMgr.decDepthKey[0]))
 
{
 
tileMgr.depth -= 1.0f;
 
Debug.Log("Now placing tiles at Z equal to " + tileMgr.depth);
 
}
 
else if (e.type == EventType.KeyUp)
 
{
 
//if the key is up and we were either moving, painting or deleting, the we se the appropiate variables
 
//to their appropiate values
 
if (moved && tileMgr.parent)
 
{
 
moved = false;
 
 
//we need to delete the tiles that has been replaced
 
for (int i = 0; i < Selection.transforms.Length; ++i)
 
{
 
foreach (Transform child in tileMgr.parent)
 
{
 
if (Selection.transforms[i] == child)
 
continue;
 
 
if (Selection.transforms[i].position == child.position)
 
{
 
DestroyImmediate(child.gameObject);
 
break;
 
}
 
}
 
}
 
}
 
else if (painted)
 
{
 
painted = false;
 
}
 
else if (deleted)
 
deleted = false;
 
}
 
 
}
 
 
//just a couple of simple fields
 
public override void OnInspectorGUI()
 
{
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Tile Width ");
 
tileMgr.width = EditorGUILayout.FloatField(tileMgr.width, GUILayout.Width(50));
 
GUILayout.Label(" Tile Height ");
 
tileMgr.height = EditorGUILayout.FloatField(tileMgr.height, GUILayout.Width(50));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Grid Offset X ");
 
tileMgr.offsetX = EditorGUILayout.FloatField(tileMgr.offsetX, GUILayout.Width(40));
 
GUILayout.Label(" Grid Offset Y ");
 
tileMgr.offsetY = EditorGUILayout.FloatField(tileMgr.offsetY, GUILayout.Width(40));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Object Offset X ");
 
tileMgr.objOffsetX = EditorGUILayout.FloatField(tileMgr.objOffsetX, GUILayout.Width(30));
 
GUILayout.Label(" Object Offset Y ");
 
tileMgr.objOffsetY = EditorGUILayout.FloatField(tileMgr.objOffsetY, GUILayout.Width(30));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Grid Color ");
 
tileMgr.color = EditorGUILayout.ColorField(tileMgr.color, GUILayout.Width(150));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Z Position ");
 
tileMgr.depth = EditorGUILayout.FloatField(tileMgr.depth, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Draw Key ");
 
tileMgr.drawKey = EditorGUILayout.TextField(tileMgr.drawKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Delete Key ");
 
tileMgr.deleteKey = EditorGUILayout.TextField(tileMgr.deleteKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Disable Key ");
 
tileMgr.disableKey = EditorGUILayout.TextField(tileMgr.disableKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Align Key ");
 
tileMgr.alignKey = EditorGUILayout.TextField(tileMgr.alignKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Increase Depth Key ");
 
tileMgr.incDepthKey = EditorGUILayout.TextField(tileMgr.incDepthKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Decrease Depth Key ");
 
tileMgr.decDepthKey = EditorGUILayout.TextField(tileMgr.decDepthKey, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Is Enabled? ");
 
tileMgr.enabled = EditorGUILayout.Toggle(tileMgr.enabled, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
GUILayout.BeginHorizontal();
 
GUILayout.Label(" Tiles' Parent ");
 
tileMgr.parent = (Transform)EditorGUILayout.ObjectField(tileMgr.parent, typeof(Transform), true, GUILayout.Width(100));
 
GUILayout.EndHorizontal();
 
 
 
//button to align the grid to the tiles' parent
 
if (GUILayout.Button("Align Grid Offset With Parent", GUILayout.Width(255)))
 
{
 
tileMgr.offsetX = tileMgr.parent.position.x;
 
tileMgr.offsetY = tileMgr.parent.position.y;
 
}
 
 
//button to align the grid to the tiles' parent and offset it by 0.5 to deter renderer's .f point errors
 
if (GUILayout.Button("Align Grid Offset With Parent + 0.5", GUILayout.Width(255)))
 
{
 
tileMgr.offsetX = Mathf.Floor(tileMgr.parent.position.x) + 0.5f;
 
tileMgr.offsetY = Mathf.Floor(tileMgr.parent.position.y) + 0.5f;
 
}
 
 
//repaint the scene to see the changes immediately
 
SceneView.RepaintAll();
 
}
 
}
 
</csharp>
 
 
Here's how you use it:
 
 
Attach a "Tiles" script to any object, then the grid will be drawn.
 
In the inspector you can find those types of fields:
 
 
    -Tile width, height -> those impact the size of your grid (in units).
 
    -Grid Offset X,Y -> this offsets the grid position (in units).
 
    -Object Offset X,Y -> this offsets the tiles from the center of the grid square
 
    -Grid Color            -> The color of the grid
 
    -Z position            -> the Z position at which the tiles will be placed
 
    -Draw Key              -> painta the selected tile on the grid
 
    -Delete Key            -> deletes a tile from the grid
 
    -Disable Key          -> disables the tile manager
 
    -Align Key            -> aligns anything selected to the grid
 
    -Set Parent Key        -> sets the parent of the created
 
    -Increase Depth Key    -> increases the Z position by one
 
    -Decrease Depth Key    -> decreases the Z position by one
 
    -Is Enabled?          -> enables or disables the manager
 
    -Tiles' Parent        -> a reference to a parent of the created tiles, if reference is not set the tiles will be created in the top of Hierarchy
 
 
Remember that you have to use keys when the scene view is active. Also, if you reimport the assets you need to select the tile manager for the script to work.
 
 
There are also two buttons, the first one is for aligning the grid with exact parent position, which helps to align the grid when the parent of the tiles is moved together with them. The second one does the same thing but it also offsets the grid by 0.5, you may want to use that to solve the floating point errors with rendering 2D sprites if your parent isn't placed properly.
 

Latest revision as of 20:23, 23 September 2011

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox