|
Post by nerdares on Feb 2, 2017 2:02:18 GMT
This is kind of an advanced topic, but I'm really hoping someone could help me out with this.
I am trying to make a Terrain Manager System. Basically, let's say you create a 9km^2 terrain. That is SUPER HUGE. Loading all of that during game play is going to kill performance right? In order to solve this, I thought of splitting the terrain into 9 for example. Once the terrain' are split, they are separated onto their own scene. Now, during runtime, based off the player's positon, the player should be able to additively load terrain as he progresses forwards. What that means is that whatever terrain tile you are on, and according to the direction you are facing, 3 tiles in front of you {front, front left, front right} and 3 tiles behind you {back, back left, back right} should load. Once you move one terrain tile forward, the previous back one's unload and there will be a new row in front. Let me know if I need to be more clear, I will post some code here that I have done to attempt at this
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Feb 2, 2017 2:06:51 GMT
I could help you out nerdares pm me the problem and we could solve it. If you would like help
|
|
|
Post by uberwiggett on Feb 2, 2017 2:10:25 GMT
There are a few terrain building assets that do this. Terrain composer 2 is one, but I think the particular part you are after is called world streamer. Not only does it load terrains but detail objects too. Actually i think the terrains are all there, but all the objects and details on them are hidden until you move near them (you can set the radius around you that things appear). Might be worth a look
|
|
|
Post by nerdares on Feb 5, 2017 2:49:39 GMT
Alright so I have just started the project. Basically it is a scene that contains 16 individual terrains, all in a 4x4 grid like fashion. They are all stored (in order) in an empty game object called terrain master and that is what is going to take the terrain manager script. This is just for testing right now, my goal is to actually make an editor window that looks for a game object called terrain master and processes my terrains. That's the first concern I have. As a matter of fact, this will all be editor based, with clicks of buttons to do the next task on the editor window.
|
|
|
Post by nerdares on Feb 5, 2017 4:47:39 GMT
So here's the terrain manager class, and each method is called by a button in the inspector made with an editor script.
TerrainManager:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using TerrainManager;
public class TerrainManagement : MonoBehaviour
{
public const string path = @"Assets/Terrain Manager/Data.xml";
public Dictionary<string, Transform> Terrains;
public void Init()
{
Terrains = new Dictionary<string, Transform>();
for (int i = 0; i < transform.childCount; i++)
{
Terrains.Add(transform.GetChild(i).name, transform.GetChild(i));
}
}
public void Serialize()
{
print("Creating \"Data.xml\" @ " + path);
List<IndividualTerrainData> myList = new List<IndividualTerrainData>();
foreach (KeyValuePair<string, Transform> entry in Terrains)
{
myList.Add(new IndividualTerrainData
{
Name = entry.Key,
xCoord = entry.Value.position.x,
yCoord = entry.Value.position.y,
zCoord = entry.Value.position.z,
});
}
File.Create(path).Dispose();
AssetDatabase.Refresh();
SerializerTool.SerializeObject(myList, path);
}
}
Terrain Editor
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(TerrainManagement))]
public class TerrainManagementEditor : Editor
{
public override void OnInspectorGUI()
{
TerrainManagement myTarget = (TerrainManagement)target;
if(GUILayout.Button("Initialize"))
{
myTarget.Init();
}
if(GUILayout.Button("Serialize"))
{
myTarget.Serialize();
}
}
}
SerializerTool
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
namespace TerrainManager
{
public static class SerializerTool
{
/// <summary>
/// Serializes a list
/// </summary>
/// <param name="list"> List to serialize </param>
/// <param name="fileName"> File path </param>
public static void SerializeObject(this List<IndividualTerrainData> list, string fileName)
{
var serializer = new XmlSerializer(typeof(List<IndividualTerrainData>));
using (var stream = File.OpenWrite(fileName))
{
serializer.Serialize(stream, list);
}
}
/// <summary>
/// Deserializes a list
/// </summary>
/// <param name="list"> List to deserialize </param>
/// <param name="fileName"> File path </param>
public static void Deserialize(this List<IndividualTerrainData> list, string fileName)
{
var serializer = new XmlSerializer(typeof(List<IndividualTerrainData>));
using (var stream = File.OpenRead(fileName))
{
var other = (List<IndividualTerrainData>)(serializer.Deserialize(stream));
list.Clear();
list.AddRange(other);
}
}
}
} IndividualTerrainData
using UnityEngine;
using System.Collections;
using System.Xml.Serialization;
using System.IO;
namespace TerrainManager
{
public struct IndividualTerrainData
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public double xCoord { get; set; }
[XmlAttribute]
public double yCoord { get; set; }
[XmlAttribute]
public double zCoord { get; set; }
}
} After pressing the buttons (the script TerrainManager is attached to a gameobject called terrain master which is the parent to 16 child terrain tile objects) in the terrain master's TerrainManager script, (they must be pressed in order - Initialize then Serialize - ), the Data.xml looks like this:
<?xml version="1.0" encoding="Windows-1252"?>
<ArrayOfIndividualTerrainData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IndividualTerrainData Name="Tile1" xCoord="0" yCoord="0" zCoord="-500.00003051757813" />
<IndividualTerrainData Name="Tile2" xCoord="-500" yCoord="0" zCoord="-500.00003051757813" />
<IndividualTerrainData Name="Tile3" xCoord="-1000" yCoord="0" zCoord="-500.00003051757813" />
<IndividualTerrainData Name="Tile4" xCoord="-1500" yCoord="0" zCoord="-500" />
<IndividualTerrainData Name="Tile5" xCoord="0" yCoord="0" zCoord="0" />
<IndividualTerrainData Name="Tile6" xCoord="-500" yCoord="0" zCoord="0" />
<IndividualTerrainData Name="Tile7" xCoord="-1000" yCoord="0" zCoord="0" />
<IndividualTerrainData Name="Tile8" xCoord="-1500" yCoord="0" zCoord="0" />
<IndividualTerrainData Name="Tile9" xCoord="0" yCoord="0" zCoord="500" />
<IndividualTerrainData Name="Tile10" xCoord="-500" yCoord="0" zCoord="500" />
<IndividualTerrainData Name="Tile11" xCoord="-1000" yCoord="0" zCoord="500" />
<IndividualTerrainData Name="Tile12" xCoord="-1500" yCoord="0" zCoord="500" />
<IndividualTerrainData Name="Tile13" xCoord="0" yCoord="0" zCoord="1000" />
<IndividualTerrainData Name="Tile14" xCoord="-500" yCoord="0" zCoord="1000" />
<IndividualTerrainData Name="Tile15" xCoord="-1000" yCoord="0" zCoord="1000" />
<IndividualTerrainData Name="Tile16" xCoord="-1500" yCoord="0" zCoord="1000" />
</ArrayOfIndividualTerrainData>
My first issue is that in the editor, I need to check if the last button was pressed before proceeding on with the user clicking the next button. So basically, Serialize should not be called unless Initialize is called. Maybe I should use events?
|
|