Skip to content

Instantly share code, notes, and snippets.

@N-Carter
Created March 13, 2013 09:17
Show Gist options
  • Save N-Carter/5150477 to your computer and use it in GitHub Desktop.
Save N-Carter/5150477 to your computer and use it in GitHub Desktop.
Tilemap made up of batched TextMesh prefabs (could also work with other meshes)
using UnityEngine;
using System.Collections;
public class EndlessTiles : MonoBehaviour
{
[SerializeField] protected Tile m_TilePrefab;
[SerializeField] protected Material[] m_Materials;
[SerializeField] protected Material m_TouchedMaterial;
protected Tile[,] m_Tiles;
protected int m_Width;
protected int m_Height;
protected Tile[] m_SpareRow;
protected Tile[] m_SpareColumn;
protected Vector3 m_Movement;
Camera m_MainCamera;
protected void Start()
{
m_MainCamera = Camera.main;
Rect extents = GetViewExtents();
m_MainCamera.transform.position += new Vector3((extents.width + 1.0f) * 0.5f, 0.0f, (extents.height + 1.0f) * 0.5f);
m_Width = (int)extents.width + 2;
m_Height = (int)extents.height + 2;
m_Tiles = new Tile[m_Width, m_Height];
m_SpareRow = new Tile[m_Width];
m_SpareColumn = new Tile[m_Height];
Quaternion rotation = m_TilePrefab.transform.rotation;
float scale = m_TilePrefab.textMesh.characterSize * 0.1f; // Why are characters 1/10th of a unit high by default?
for(int y = 0; y < m_Height; ++y)
{
for(int x = 0; x < m_Width; ++x)
{
var tile = (Tile)Instantiate(m_TilePrefab, new Vector3(x, 0, y) * scale, rotation);
tile.endlessTiles = this;
tile.transform.parent = transform;
m_Tiles[x, y] = tile;
}
}
FillTiles(0, m_Width, 0, m_Height);
}
public Rect GetViewExtents()
{
Vector3 minCorner = GetPositionOnPlane(Vector3.zero);
Vector3 maxCorner = GetPositionOnPlane(new Vector3(m_MainCamera.pixelWidth, m_MainCamera.pixelHeight, 0.0f));
return new Rect(minCorner.x, minCorner.z, maxCorner.x - minCorner.x, maxCorner.z - minCorner.z);
}
public Vector3 GetPositionOnPlane(Vector3 screenPosition)
{
Ray ray = m_MainCamera.ScreenPointToRay(screenPosition);
Plane plane = new Plane(Vector3.up, Vector3.zero);
float distance;
if(plane.Raycast(ray, out distance))
{
// Debug.DrawRay(ray.origin, ray.direction * distance, Color.green, 1.0f);
return ray.origin + ray.direction * distance;
}
Debug.Log("Plane.Raycast missed the plane! Your camera is pointing in a stupid direction!");
return new Vector3(0, 0, 100);
}
public Tile GetTileAtPosition(Vector3 position)
{
Vector3 transformPosition = transform.position;
int x = Mathf.RoundToInt(position.x - transformPosition.x % 1.0f);
int y = Mathf.RoundToInt(position.z - transformPosition.z % 1.0f);
return m_Tiles[x, y];
}
public void Move(Vector3 offset)
{
m_Movement = offset;
Vector3 position = transform.position;
position += offset;
if(position.x < 0.0f)
{
position.x += 1.0f;
MoveTilesRight();
}
else if(position.x > 1.0f)
{
position.x -= 1.0f;
MoveTilesLeft();
}
if(position.z < 0.0f)
{
position.z += 1.0f;
MoveTilesUp();
}
else if(position.z > 1.0f)
{
position.z -= 1.0f;
MoveTilesDown();
}
transform.position = position;
}
protected void MoveTilesLeft()
{
StoreColumn(m_Width - 1);
for(int x = m_Width - 1; x > 0; --x)
{
for(int y = 0; y < m_Height; ++y)
MoveTile(x - 1, y, x, y);
}
RestoreColumn(0);
FillTiles(0, 1, 0, m_Height);
}
protected void MoveTilesRight()
{
StoreColumn(0);
for(int x = 0; x < m_Width - 1; ++x)
{
for(int y = 0; y < m_Height; ++y)
MoveTile(x + 1, y, x, y);
}
RestoreColumn(m_Width - 1);
FillTiles(m_Width - 1, m_Width, 0, m_Height);
}
protected void MoveTilesDown()
{
StoreRow(m_Height - 1);
for(int y = m_Height - 1; y > 0; --y)
{
for(int x = 0; x < m_Width; ++x)
MoveTile(x, y - 1, x, y);
}
RestoreRow(0);
FillTiles(0, m_Width, 0, 1);
}
protected void MoveTilesUp()
{
StoreRow(0);
for(int y = 0; y < m_Height - 1; ++y)
{
for(int x = 0; x < m_Width; ++x)
MoveTile(x, y + 1, x, y);
}
RestoreRow(m_Height - 1);
FillTiles(0, m_Width, m_Height - 1, m_Height);
}
protected void MoveTile(int fromX, int fromY, int toX, int toY)
{
// System.Console.WriteLine("{0}, {1} => {2}, {3}", fromX, fromY, toX, toY);
var fromTile = m_Tiles[fromX, fromY];
RepositionTile(fromTile, toX - fromX, toY - fromY);
m_Tiles[toX, toY] = fromTile;
}
protected void RepositionTile(Tile tile, int offsetX, int offsetY)
{
Vector3 position = tile.transform.localPosition;
tile.transform.localPosition = new Vector3((int)(position.x + offsetX), position.y, (int)(position.z + offsetY));
}
protected void StoreColumn(int x)
{
for(int y = 0; y < m_Height; ++y)
m_SpareColumn[y] = m_Tiles[x, y];
}
protected void RestoreColumn(int x)
{
// Only meant to work on the outermost columns:
int offset = (m_Width - 1) * (x == 0 ? -1 : 1);
for(int y = 0; y < m_Height; ++y)
{
var tile = m_SpareColumn[y];
RepositionTile(tile, offset, 0);
m_Tiles[x, y] = tile;
}
}
protected void StoreRow(int y)
{
for(int x = 0; x < m_Width; ++x)
m_SpareRow[x] = m_Tiles[x, y];
}
protected void RestoreRow(int y)
{
// Only meant to work on the outermost columns:
int offset = (m_Height - 1) * (y == 0 ? -1 : 1);
for(int x = 0; x < m_Width; ++x)
{
var tile = m_SpareRow[x];
RepositionTile(tile, 0, offset);
m_Tiles[x, y] = tile;
}
}
protected void FillTiles(int startX, int endX, int startY, int endY)
{
for(int y = startY; y < endY; ++y)
{
for(int x = startX; x < endX; ++x)
{
var tile = m_Tiles[x, y];
tile.Reset();
}
}
}
public Vector3 Movement {get {return m_Movement;}}
public Material[] Materials {get {return m_Materials;}}
public Material TouchedMaterial {get {return m_TouchedMaterial;}}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment