我正在尝试构建一个无尽的地形生成器(遵循Sebastian Lague的本教程:Tutorial Source),在那里他实现了生成地形和网格的线程。我更进一步,创建了一个工具,将Gameobjects放置在地形(树木,岩石等)上,现在我无法弄清楚我将如何在那里使用线程......我正在尝试从几天开始,但达到了一个点我想请求帮助。希望某种专业人士可以帮助我解决这个问题。
以下是注释代码以及我尝试解决问题的方法:
public GameObject grasGeneratorPrefab;
public GameObject physicsSimulatorPrefab;
public bool updateGras = false;
private bool allowGrasUpdate = false;
// Check if instance at this point already exists --> if YES, don't instantiate another.
HashSet<Transform> alreadyGeneratedObjectAtThisChunkTransform = new HashSet<Transform>();
Queue<AssetDataInfoThread<AssetData>> assetDataInfoQueue = new Queue<AssetDataInfoThread<AssetData>>();
// Use this for initialization
void Start ()
{
allowGrasUpdate = false;
StartCoroutine (WaitForFirstObjectPlacement ());
}
// First time instantiating Gameobjects on terrain
IEnumerator WaitForFirstObjectPlacement()
{
yield return new WaitForSeconds (3);
foreach (Transform t in this.transform)
{
PlaceObjectsOnChunks ();
}
allowGrasUpdate = true;
}
// I WANT THIS FUNCTION TO BE THREADED --> To prevent freezes during execution
public void PlaceObjectsOnChunks()
{
foreach (Transform t in this.transform)
{
// If the Transform-object has a collider and the TRansform is yet not in the List...
if (t.GetComponent<MeshCollider> ().sharedMesh != null && !alreadyGeneratedObjectAtThisChunkTransform.Contains(t))
{
// ...execute this function
AssetPlacement.SpawnGrassGeneratorAtChunkPosition (t.transform.position, grasGeneratorPrefab);
// THE FUNCTION THAT IS PICKED FROM AssetPlacement class is:
// public static void SpawnGrassGeneratorAtChunkPosition(Vector3 centre, GameObject grasGeneratorPrefab)
// {
// GameObject grasG = Object.Instantiate (grasGeneratorPrefab, new Vector3 (centre.x, 0, centre.z), Quaternion.identity);
// }
AssetPlacement.SpawnPhysicsSimulatorsAtChunkPosition (t.transform.position, physicsSimulatorPrefab);
// same function as SpawnGrassGeneratorAtChunkPosition with other prefab
alreadyGeneratedObjectAtThisChunkTransform.Add (t); // Add Transform to the List (to be checked in next iteration)
}
}
}
void Update()
{
if (allowGrasUpdate && AssetPlacement.updateGras)
{
PlaceObjectsOnChunks();
// Triggers the Stop for the Function
AssetPlacement.StopGrasUpdate ();
}
// /// // // // // // // // // // //
// // TRYING OUT WITH THREADING // // __> Need help here
// /// // // // // // // // // // //
if(assetDataInfoQueue.Count > 0)
{
for (int i = 0; i < assetDataInfoQueue.Count; i++)
{
AssetDataInfoThread<AssetData> threadInfo = assetDataInfoQueue.Dequeue();
threadInfo.callback (threadInfo.parameter);
Debug.Log ("Reached crucial threading point");
}
}
}
public void RequestAssetToPlaceData(Action<AssetData> callback)
{
ThreadStart threadStart = delegate {
AssetDataThread(callback);
};
new Thread (threadStart).Start ();
}
void AssetDataThread(Action<AssetData> callback)
{
AssetData assetData = PlaceObjectsOnChunks();
lock (assetDataInfoQueue) {
assetDataInfoQueue.Enqueue (new AssetDataInfoThread<AssetData> (callback, assetData));
}
}
// DO I NEED THIS STRUCT (?)
public struct AssetData
{
public Vector3 centre; // These values are used in AssetPlacement-Script
public readonly GameObject prefab; // These values are used in AssetPlacement-Script
public AssetData (Vector3 centre, GameObject prefab)
{
this.centre = centre;
this.prefab = prefab;
}
}
struct AssetDataInfoThread<T>
{
public readonly Action<T> callback;
public readonly T parameter;
public AssetDataInfoThread (Action<T> callback, T parameter)
{
this.callback = callback;
this.parameter = parameter;
}
}
答案 0 :(得分:3)
当我跟随Sebastian Lague的教程时,我发现开始研究陆地生成非常棒,但我发现它在扩展它的功能时受到限制。这是我对你要做的事情的体验。我希望它可能为您的项目提供一些见解,帮助,想法或避免。
我发现在主网格生成之上添加新generation layer
的唯一方法是我为下一个块生成了地形。然后,我会根据地形的list
和suitable locations
触发一个新线程并获取height
angle
个对象。
一旦我在列表中有合适的位置,我就有了一个函数,可以将对象随机分配到这些对象的位置,如下所示:
线程完成后,我将对象放置为view distance
玩家即将进入对象的LOS
。
Video of the suitable locations script in chunk
这个片段强化了我所谈论的内容。不幸的是,我不再拥有代码了。
这是生成相机所在地图块的菜单示例。
否定:
我要做的改进:
suitable locations
时,一次性生成块的性能成本Object Layers
,以便每次加载时每个块看起来都相同