- Home /
Changing terrain in real time
Hey guys, I'll try and be specific as possible. Currently I'm looking at this extension (http://www.youtube.com/watch?v=yLi-Lp23j7Q), which seems to do exactly what I need, but the problem I have relates to updating the terrain in real time.
My goal is to have a SQL database with a table that stores the X and Y (of the grid) and the value which will correspond to what tile it would be. For example
1 1 5
1 2 10
On runtime, when read from the table, the tile at 1,1 will display tile 5. And then tile at 1,2 will display tile 10. But then if I were to change the the 5 to 20, for example, it will change the terrain in real time on the screen for the user.
I don't necessarily need to implement a SQL table right now. I could just read from a txt file and modify to SQL later. My main issue is just updating the tile in real time with unity.
Amazing community ;)
Answer by nastasache · Aug 11, 2013 at 09:41 PM
Hi, tenix
I'am not sure you mean about update an existing tile by some rules or about navigate on a huge number of tiles, so that below example is about create a tile.
The example is from my similar database, for a 3x3 tile:
1,3,1325
1,2,1337
1,1,1335
2,3,1325
2,2,1333
2,1,1329
3,3,1326
3,2,1331
3,1,1327
With these values retrieved as string (see xyzDb variable), you can use a script like (JS):
#pragma strict
var unitsStep : float = 30.0;
var material : Material;
private var height : int = 3;
private var width : int = 3;
private var area : int = width * height;
private var vertices = new Vector3[height * width];
var xyzDb="1,3,1325\n1,2,1337\n1,1,1335\n2,3,1325\n2,2,1333\n2,1,1329\n3,3,1326\n3,2,1331\n3,1,1327"; // Records from DB
var xzyValues = new String[area];
function Start() {
xzyValues = xyzDb.Split(char.Parse("\n"));
gameObject.AddComponent(MeshCollider);
gameObject.AddComponent(MeshFilter);
gameObject.AddComponent(MeshRenderer);
MakeTerrain();
}
function MakeTerrain() {
if (material) {
renderer.material = material;
} else {
renderer.material.color = Color.white;
}
/// Clean up
var meshCollider : MeshCollider = gameObject.GetComponent(MeshCollider);
meshCollider.sharedMesh = null;
var terrain : Mesh = GetComponent(MeshFilter).mesh;
terrain.Clear();
// Build vertices
var vertices = new Vector3[height * width];
var uv = new Vector2[height * width];
var uvScale = Vector2 (1/unitsStep,1/unitsStep);
for (var j : int = 0; j < xzyValues.Length ; j++){
var lle=xzyValues[j];
var xyz=lle.Split(char.Parse(","));
var x : int = parseInt(xyz[0]);
var z : int = parseInt(xyz[1]);
var xx = x * unitsStep;
var zz = z * unitsStep;
var e : int = parseInt(xyz[2]);
var vertex = Vector3 (xx, e, zz);
vertices[j] = vertex;
uv[j] = Vector2.Scale(Vector2 (xx, zz),uvScale);
}
// Assign vertices to terrain
terrain.vertices = vertices;
terrain.uv = uv;
// Build triangle indices: 3 indices into vertex array for each triangle
var triangles = new int[(height - 1) * (width - 1) * 6];
var index = 0;
for (z=0;z<height-1;z++)
{
for (x=0;x<width-1;x++)
{
// For each grid cell output two triangles
triangles[index++] = (z * width) + x;
triangles[index++] = ((z+1) * width) + x;
triangles[index++] = (z * width) + x + 1;
triangles[index++] = (z * width) + x + 1;
triangles[index++] = ((z+1) * width) + x;
triangles[index++] = ((z+1) * width) + x + 1;
}
}
// And assign them to the terrain
terrain.triangles = triangles;
// Auto-calculate vertex normals from the terrain
terrain.RecalculateNormals();
terrain.RecalculateBounds();
terrain.Optimize();
// Assign terrain mesh as collider mesh
meshCollider.sharedMesh = terrain;
}
Note terrain in the script is not about unity Terrains; I use it for meshes. As suggestion regarding DB, for large areas it's better to you use a NoSQL database, recording for example 1_1 as key and 5 as value, 1_2 as key and 10 and so (exploding by x/z coordinates by "_"). Then, retrieve records in needed range.
I'm sorry and just realized my entire question is stupid and not worded correctly.
I have developed a script that will take in X size, Y size, tile size and texture resolution. So I can define a 100x100 map with scale 1 and texture resolution of 32x32 for example. $$anonymous$$y script is actually very similar to yours.
What I am trying to do now is change a tile after it has been rendered.
So say my database looks like this:
1,1,5
1,2,5
1,3,5
1,4,5
Which would represent x = 1, y = 1, tileId = 5 and this is loaded on my screen right now, no problem. Now what I want to do is go in and change the 5 to a 6 and it will update the tile on the screen for the user, basically while they are playing. I'm newish to unity and 3d in general. This is something I did years ago in 2d with no issues. I just don't exactly know how to handle it here. Obviously I don't want to do $$anonymous$$akeTerrain() in Update() because that would probably destroy the computer lol.
I see. You mean not about creating a terrain but replacing some tiles. Still it's unclear for me how your maps it's working and what is replacing for. If you looking for a solution to walk in very large area splitting that area in small current tiles/terrains, than I am in the same research stage (also I am not expert in Unity3D) and my approach it's a bit different. $$anonymous$$aybe the links below are useful for you, I am not sure. Of course functions like $$anonymous$$akeTerrain() have not to be called directly in Update() (for example I called it only when set of tiles are changed; meanwhile, I decided anyway not to create terrains during of play but activating/deactivating/loading already existing terrains on the scene or in Resources folder)
Your answer
Follow this Question
Related Questions
Unity Batch Terrain Creation Script? 1 Answer
Tile generation problem 1 Answer
best tile size for terrain? 2 Answers