Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
线程化依赖于C#(Unity)中另一个类的函数_C#_Multithreading_Unity3d_Game Engine_Procedural Generation - Fatal编程技术网

线程化依赖于C#(Unity)中另一个类的函数

线程化依赖于C#(Unity)中另一个类的函数,c#,multithreading,unity3d,game-engine,procedural-generation,C#,Multithreading,Unity3d,Game Engine,Procedural Generation,我正在尝试构建一个无止境的地形生成器(Sebastian Lague在本教程之后:),在这里他实现了生成地形和网格的线程。我更进一步,创建了一个工具,可以在地形(树木、岩石等)上放置游戏对象。现在我不知道如何在那里使用线程。。。几天以来我一直在尝试,但到了我想寻求帮助的地步。希望一些专业人士能帮我解决这个问题 以下是注释代码和我解决问题的尝试: public GameObject grasGeneratorPrefab; public GameObject physicsSimulatorPre

我正在尝试构建一个无止境的地形生成器(Sebastian Lague在本教程之后:),在这里他实现了生成地形和网格的线程。我更进一步,创建了一个工具,可以在地形(树木、岩石等)上放置游戏对象。现在我不知道如何在那里使用线程。。。几天以来我一直在尝试,但到了我想寻求帮助的地步。希望一些专业人士能帮我解决这个问题

以下是注释代码和我解决问题的尝试:

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;
    }
}
公共游戏对象grasGeneratorPrefab;
公共游戏对象物理模拟器;
public bool updateGras=false;
私有布尔allowGrasUpdate=false;
//检查此时的实例是否已存在-->如果是,请不要实例化其他实例。
HashSet AlreadyGeneratedObjectAtthistChunkTransform=新HashSet();
Queue assetDataInfoQueue=新队列();
//用于初始化
无效开始()
{
allowGrasUpdate=false;
start例程(WaitForFirstObjectPlacement());
}
//第一次在地形上实例化游戏对象
IEnumerator WaitForFirstObjectPlacement()
{
产生返回新WaitForSeconds(3);
foreach(在此.Transform中转换t)
{
PlaceObjectsOnChunks();
}
allowGrasUpdate=true;
}
//我希望将此函数线程化-->以防止执行期间冻结
public void PlaceObjectsOnChunks()
{
foreach(在此.Transform中转换t)
{
//如果变换对象具有碰撞器,且变换尚未在列表中。。。
if(t.GetComponent().sharedMesh!=null&&!AlreadyGeneratedObjectAtthistChunkTransform.Contains(t))
{
//…执行此功能
AssetPlacement.SpawnGrassGeneratorChunkPosition(t.transform.position,grasGeneratorPrefab);
//从AssetPlacement类中选择的函数是:
//公共静态无效生成GrassGeneratorChunkPosition(矢量3中心,游戏对象grasGeneratorPrefab)
//                {
//GameObject grasG=Object.Instantiate(grasGeneratorPrefab,新向量3(center.x,0,center.z),四元数.identity);
//                }
AssetPlacement.SpawnPhysicsSimulator匹配位置(t.transform.position,PhysicsSimulator重构B);
//与其他预制件的SpawnGrassGeneratorChunkPosition功能相同
AlreadyGeneratedObjectAtthistChunkTransform.Add(t);//将转换添加到列表中(在下一次迭代中检查)
}
}
}
无效更新()
{
if(allowGrasUpdate&&AssetPlacement.updateGras)
{
PlaceObjectsOnChunks();
//触发函数的停止
AssetPlacement.StopGrasUpdate();
}
// /// // // // // // // //  // // // 
////尝试使用线程////\u>此处需要帮助
// /// // // // // // // //  // // //
如果(assetDataInfoQueue.Count>0)
{
对于(int i=0;i
当我学习Sebastian Lague的教程时,我发现开始陆上生成非常棒,但我发现扩展其功能时受到限制。这是我对你所做的事情的经验。我希望它能为您的项目提供一些见解、帮助、想法或避免

我的解决方案 我发现在主网格生成上添加新的
生成层
的唯一方法是为下一块生成地形。然后,我将启动一个新线程,并根据地形的
高度
角度
获取对象的
合适位置的
列表

一旦我在列表中有了合适的位置,我就有了一个函数,可以随机分配对象来定位这些对象,如下所示:

  • 树木
  • 岩石
  • 箱子
线程完成后,我将放置对象,因为玩家
查看距离
即将进入对象的
视距

这段视频强化了我所说的内容。不幸的是,我没有代码了

下面是生成相机所在地图块时的菜单示例

负片:

  • 缺少对象的完美放置
  • 生成大量对象时可能会出现可伸缩性问题
  • 对象放置缺乏一致性
我将要做的改进:

  • 多线程每个对象层
  • 当以一次性生成性能成本生成块时,实施
    合适的位置
  • 在块级别实现
    对象层
    ,以便