我的自定义地形生成插件实例化了很多预制件

Posted

技术标签:

【中文标题】我的自定义地形生成插件实例化了很多预制件【英文标题】:My custom terrain generation plugin instantiates to much prefabs 【发布时间】:2014-07-21 19:02:07 【问题描述】:

问题如下:通常脚本应该在播放器周围的立方体中生成 16 个预制件,当我启动它时它工作正常,因为它调用了 generate on start 函数,但是当我用第一个人踩到另一个块时控制器它每秒生成这 16 个块,它会产生很多滞后并且确实存在故障,并且不应该生成那么多预制件,非常感谢任何帮助。非常感谢。

我不认为问这么大的问题是允许的,但是在连续几天尝试解决这个问题之后,它似乎仍然没有工作。所以这就是我得到的:

第一人称控制器 2 个脚本 一个名为 infiniteTerrain 的脚本附加到第一人称控制器脚本的简短描述:此脚本生成围绕玩家的预制件,形状为 立方体。它还将这些块保存到.txt 文件中,以便它们可以 在需要时加载以最大程度地减少延迟。 一个名为 chunkRename 的脚本附加到生成的每个块脚本的简短描述:重命名这些块,以便可以在另一个脚本中轻松访问它们。

以下是脚本:

infiniteTerrain.js

#pragma strict

var terrains : GameObject[];
var newworld = true;
var trees : GameObject[];
var vegetation : GameObject[];
var rivers : GameObject[];
var mountains : GameObject[];
var playerTerrainUnavailable = false;
var x = 50;
var z = 50;
var y = 100;
var cameraDirection : float;
var chunkWidth = 50;

var chunk1 = " ";
var chunk2 = " ";
var chunk3 = " ";   
var chunk4 = " ";
var chunk5 = " ";
var chunk6 = " ";
var chunk7 = " ";
var chunk8 = " ";
var chunk9 = " ";
var chunk10= " ";
var chunk11= " ";
var chunk12= " ";
var chunk13= " ";
var chunk14= " ";
var chunk15= " ";
var chunk16= " ";
var chunk17= " ";
var chunk18= " ";
var chunk19= " ";
var chunk20= " ";
var chunk21= " ";
var chunk22= " ";
var chunk23= " ";
var chunk24= " ";
var chunk25= " ";
var load1 = true;
var load2 = true;
var load3 = true;
var load4 = true;
var load5 = true;
var load6 = true;
var load7 = true;
var load8 = true;
var load9 = true;
var load10 = true;
var load11 = true;
var load12 = true;
var load13 = true;
var load14 = true;
var load15 = true;
var load16 = true;
var load17 = true;
var load18 = true;
var load19 = true;
var load20 = true;
var load21 = true;
var load22 = true;
var load23 = true;
var load24 = true;
var load25 = true;

var canGenerate = true;


function Start() 
    if(newworld) 
        generateOnStart();
        saveLoadedChunk();
        newworld = false;
    else
        loadSavedWorld();
    


function Update() 



function callGenerate() 
    if(canGenerate) 
    var canGenerate = false;
    var gameObjects : GameObject[] = FindObjectsOfType(GameObject) as GameObject[];
        for (var i = 0; i < gameObjects.length ; i++) 
            if(gameObjects[i].name.Substring(0,6) == "ACTIVE")
                if(gameObjects[i].tag != "Player") 
                var xco = gameObjects[i].transform.position.x;
                var yco = gameObjects[i].transform.position.y;
                var zco = gameObjects[i].transform.position.z;
                generateFromMiddleOfChunk(xco, yco, zco);
                               
        
    


function saveLoadedChunk() 
    var loadedChunks : GameObject[] = FindObjectsOfType(GameObject) as GameObject[];
    var fileName = "C:/Reactor Games/chunks.txt";    

    var lines = System.IO.File.ReadAllLines(fileName);

    var write = true;

    var sw : System.IO.StreamWriter = new System.IO.StreamWriter(fileName, true);
    for (var i = 0; i < loadedChunks.length ; i++) 
        if(loadedChunks[i].name.Substring(0,5) == "Chunk" || loadedChunks[i].name.Substring(0,5) == "_TERR" || loadedChunks[i].name.Substring(0,5) == "ACTIV") 
            if(loadedChunks[i].tag != "Player") 
                var xco = loadedChunks[i].transform.position.x;
                var yco = loadedChunks[i].transform.position.y;
                var zco = loadedChunks[i].transform.position.z;
                var stringToWrite = "Chunk (" + xco + ", " + yco + ", " + zco + ")";

                write = true;
                for (var chunkName in lines) 
                    if(chunkName.Equals(stringToWrite)) 
                        write = false;
                        break;
                    
                

                if(write)sw.WriteLine(stringToWrite);     
            
        
    
    sw.Flush();
    sw.Close();


function generateFromMiddleOfChunk(xco : int, yco : int, zco : int) 
    //V1
    chunk1 = "Chunk (" + xco.ToString() + ", " + yco.ToString() + ", " + zco.ToString() + ")";
    chunk2 = "Chunk (" + (xco + chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco+chunkWidth).ToString() + ")";
    chunk3 = "Chunk (" + (xco + chunkWidth).ToString() + ", " + yco.ToString() + ", " + zco.ToString() + ")";
    chunk4 = "Chunk (" + (xco + chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco * -1).ToString() + ")";
    chunk5 = "Chunk (" + (xco + chunkWidth * -1).ToString() + ", " + yco.ToString() + ", " + (zco+chunkWidth).ToString() + ")";
    chunk6 = "Chunk (" + (xco + chunkWidth * -1).ToString() + ", " + yco.ToString() + ", " + zco.ToString() + ")";
    chunk7 = "Chunk (" + (xco + chunkWidth * -1).ToString() + ", " + yco.ToString() + ", " + (zco * -1).ToString() + ")";
    chunk8 = "Chunk (" + xco.ToString() + ", " + yco.ToString() + ", " + (zco + chunkWidth).ToString() + ")";
    chunk9 = "Chunk (" + xco.ToString() + ", " + yco.ToString() + ", " + (zco * -1).ToString() + ")";
    chunk10= "Chunk (" + (xco + chunkWidth * -2).ToString() + ", " + yco.ToString() + ", " + (zco + 2 * chunkWidth).ToString() + ")";
    chunk11= "Chunk (" + (xco + chunkWidth * -2).ToString() + ", " + yco.ToString() + ", " + (zco + chunkWidth).ToString() + ")";
    chunk12= "Chunk (" + (xco + chunkWidth * -2).ToString() + ", " + yco.ToString() + ", " + zco.ToString() + ")";
    chunk13= "Chunk (" + (xco + chunkWidth * -2).ToString() + ", " + yco.ToString() + ", " + (zco * -1).ToString() + ")";
    chunk14= "Chunk (" + (xco + chunkWidth * -2).ToString() + ", " + yco.ToString() + ", " + (zco + -2 * chunkWidth).ToString() + ")";
    chunk15= "Chunk (" + (xco + chunkWidth * -1).ToString() + ", " + yco.ToString() + ", " + (zco + 2 * chunkWidth).ToString() + ")";
    chunk16= "Chunk (" + (xco + chunkWidth * -1).ToString() + ", " + yco.ToString() + ", " + (zco + -2 * chunkWidth).ToString() + ")";
    chunk17= "Chunk (" + xco.ToString() + ", " + yco.ToString() + ", " + (zco + 2 * chunkWidth).ToString() + ")";
    chunk18= "Chunk (" + xco.ToString() + ", " + yco.ToString() + ", " + (zco + -2 * chunkWidth).ToString() + ")";
    chunk19= "Chunk (" + (xco + chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco + 2 * chunkWidth).ToString() + ")";
    chunk20= "Chunk (" + (xco + chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco + -2 * chunkWidth).ToString() + ")";
    chunk21= "Chunk (" + (xco + 2 * chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco + 2 * chunkWidth).ToString() + ")";
    chunk22= "Chunk (" + (xco + 2 * chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco + chunkWidth).ToString() + ")";
    chunk23= "Chunk (" + (xco + 2 * chunkWidth).ToString() + ", " + yco.ToString() + ", " + zco.ToString() + ")";
    chunk24= "Chunk (" + (xco + 2 * chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco * -1).ToString() + ")";
    chunk25= "Chunk (" + (xco + 2 * chunkWidth).ToString() + ", " + yco.ToString() + ", " + (zco + -2 * chunkWidth).ToString() + ")";

    var chunksInScene : GameObject[] = FindObjectsOfType(GameObject) as GameObject[];
    var myArray : boolean[] = new boolean[25];

    for (var i = 0; i < chunksInScene.length ; i++) 
        if(chunksInScene[i].name.Substring(0,5) == "Chunk" || chunksInScene[i].name.Substring(0,5) == "_TERR" || chunksInScene[i].name.Substring(0,5) == "ACTIV") 
                if(chunksInScene[i].tag != "Player") 

                if(myArray[0] && chunksInScene[i].Equals(chunk1))
                load1 = false; myArray[0] = false;continue;

                if(myArray[1] && chunksInScene[i].Equals(chunk2))
                load2 = false; myArray[1] = false; continue;

                if(myArray[2] && chunksInScene[i].Equals(chunk3))
                load3 = false; myArray[2] = false; continue;

                if(myArray[3] && chunksInScene[i].Equals(chunk4))
                load4 = false; myArray[3] = false; continue;

                if(myArray[4] && chunksInScene[i].Equals(chunk5))
                load5 = false; myArray[4] = false; continue;

                if(myArray[5] && chunksInScene[i].Equals(chunk6))
                load6 = false; myArray[5] = false; continue;

                if(myArray[6] && chunksInScene[i].Equals(chunk7))
                load7 = false; myArray[6] = false; continue;

                if(myArray[7] && chunksInScene[i].Equals(chunk8))
                load8 = false; myArray[7] = false; continue;

                if(myArray[8] && chunksInScene[i].Equals(chunk9))
                load9 = false; myArray[8] = false; continue;

                if(myArray[9] && chunksInScene[i].Equals(chunk10))
                load10 = false; myArray[9] = false; continue;

                if(myArray[10] && chunksInScene[i].Equals(chunk11))
                load11 = false; myArray[10] = false; continue;

                if(myArray[11] && chunksInScene[i].Equals(chunk12))
                load12 = false; myArray[11] = false; continue;

                if(myArray[12] && chunksInScene[i].Equals(chunk13))
                load13 = false; myArray[12] = false; continue;

                if(myArray[13] && chunksInScene[i].Equals(chunk14))
                load14 = false; myArray[13] = false; continue;

                if(myArray[14] && chunksInScene[i].Equals(chunk15))
                load15 = false; myArray[14] = false; continue;

                if(myArray[15] && chunksInScene[i].Equals(chunk16))
                load16 = false; myArray[15] = false; continue;

                if(myArray[16] && chunksInScene[i].Equals(chunk17))
                load17 = false; myArray[16] = false; continue;

                if(myArray[17] && chunksInScene[i].Equals(chunk18))
                load18 = false; myArray[17] = false; continue;

                if(myArray[18] && chunksInScene[i].Equals(chunk19))
                load19 = false; myArray[18] = false; continue;

                if(myArray[19] && chunksInScene[i].Equals(chunk20))
                load20 = false; myArray[19] = false; continue;

                if(myArray[20] && chunksInScene[i].Equals(chunk21))
                load21 = false; myArray[20] = false; continue;

                if(myArray[21] && chunksInScene[i].Equals(chunk22))
                load22 = false; myArray[21] = false; continue;

                if(myArray[22] && chunksInScene[i].Equals(chunk23))
                load23 = false; myArray[22] = false; continue;

                if(myArray[23] && chunksInScene[i].Equals(chunk24))
                load24 = false; myArray[23] = false; continue;

                if(myArray[24] && chunksInScene[i].Equals(chunk25))
                load25 = false; myArray[24] = false; continue;
            
        
    

    //V1
    if(load1)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco, yco, zco), Quaternion.identity);
    //V2
    if(load2)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth, yco, zco + chunkWidth), Quaternion.identity);
    if(load3)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth, yco, zco), Quaternion.identity);
    if(load4)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth, yco, zco * -1), Quaternion.identity);
    if(load5)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -1, yco, zco + chunkWidth), Quaternion.identity);
    if(load6)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -1, yco, zco), Quaternion.identity);
    if(load7)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -1, yco, zco * -1), Quaternion.identity);
    if(load8)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco, yco, zco + chunkWidth), Quaternion.identity);
    if(load9)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco, yco, zco * -1), Quaternion.identity);
    //V3 
    if(load10)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -2, yco, zco + 2 * chunkWidth), Quaternion.identity);
    if(load11)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -2, yco, zco + chunkWidth), Quaternion.identity);
    if(load12)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -2, yco, zco), Quaternion.identity);
    if(load13)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -2, yco, zco * -1), Quaternion.identity);
    if(load14)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -2, yco, zco + -2 * chunkWidth), Quaternion.identity);
    if(load15)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -1, yco, zco + 2 * chunkWidth), Quaternion.identity);
    if(load16)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth * -1, yco, zco + -2 * chunkWidth), Quaternion.identity);
    if(load17)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco, yco, zco + 2 * chunkWidth), Quaternion.identity);
    if(load18)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco, yco, zco + -2 * chunkWidth), Quaternion.identity);
    if(load19)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth, yco, zco + 2 * chunkWidth), Quaternion.identity);
    if(load20)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + chunkWidth, yco, zco + -2 * chunkWidth), Quaternion.identity);
    if(load21)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + 2 * chunkWidth, yco, zco + 2 * chunkWidth), Quaternion.identity);
    if(load22)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + 2 * chunkWidth, yco, zco + chunkWidth), Quaternion.identity);
    if(load23)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + 2 * chunkWidth, yco, zco), Quaternion.identity);
    if(load24)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + 2 * chunkWidth, yco, zco * -1), Quaternion.identity);
    if(load25)Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(xco + 2 * chunkWidth, yco, zco + -2 * chunkWidth), Quaternion.identity);     
    yield WaitForSeconds(5);
    var canGenerate = true;



function generateOnStart() 
    //MOET EEN FUNCTION WORDEN DIE ALS DE SPELER EEN NIEUWE WERELD START, DAT ER AL EEN KLEIN TERREIN KOMT
    //V1
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(0, 0, 0), Quaternion.identity);
    //V2
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(50, 0, 50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(50, 0, 0), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(50, 0, -50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-50, 0, 50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-50, 0, 0), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-50, 0, -50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(0, 0, 50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(0, 0, -50), Quaternion.identity);
    //V3 
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-100, 0, 100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-100, 0, 50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-100, 0, 0), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-100, 0, -50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-100, 0, -100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-50, 0, 100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(-50, 0, -100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(0, 0, 100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(0, 0, -100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(50, 0, 100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(50, 0, -100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(100, 0, 100), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(100, 0, 50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(100, 0, 0), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(100, 0, -50), Quaternion.identity);
    Instantiate(terrains[Random.Range(0,terrains.length)], Vector3(100, 0, -100), Quaternion.identity);

chunkRename.js

#pragma strict

function Start () 
    this.name = "Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";




function OnTriggerEnter (col : Collider) 
    if(col.gameObject.tag == "Player") 
        this.name = "ACTIVE_Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";
       


function OnTriggerExit (col : Collider) 
    if(col.gameObject.tag == "Player") 
        this.name = "Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";
        gameObject.Find("First Person Controller").SendMessage("callGenerate");
    

【问题讨论】:

是否违反规定?对不起,我会编辑它。 这段代码一团糟。我想问你是否听说过数组,但后来注意到你已经在某些地方使用它们了。说真的:使用 chunk[25] 而不是 25 个不同的变量。 【参考方案1】:

首先,将您的 25 行实例化更改为:

for (int i = -2; i< 3; i++)
    
        for (int j = -2; j < 3; j++)
        
            Instantiate(terrains[Random.Range(0,terrains.length)], 
                          Vector3(j*50, 0, i*50), Quaternion.identity);
        
    

其次,你在这个调用中已经有了游戏对象,所以不要使用 GameObject.Find() //它很昂贵 因此,假设标记为“播放器”的对象具有 FPS 控制器,请更改:

if(col.gameObject.tag == "Player") 
    this.name = "Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";
    gameObject.Find("First Person Controller").SendMessage("callGenerate");

收件人:

if(col.gameObject.tag == "Player") 
    this.name = "Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";
    col.gameObject.SendMessage("callGenerate");

最后,从您的代码看来,您希望根据玩家当前所在的位置生成您的一代。与其在 OnTriggerExit 中执行此操作,不如将其放在 OnTriggerEnter() 中,然后将触发器对象传递给您的函数,这样您就无需在 callGenerate 方法中查找活动对象:

function OnTriggerEnter (col : Collider) 
if(col.gameObject.tag == "Player") 
    this.name = "ACTIVE_Chunk (" + this.transform.position.x + ", " + this.transform.position.y + ", " + this.transform.position.z + ")";
    col.gameObject.SendMessage("callGenerate", this.gameObject);
       


function callGenerate(go: GameObject) 
    if(canGenerate) 
        canGenerate = false; //you were redeclaring this variable here, 
        //which is mostly likely why you had more generation going on than desired
        generateFromMiddleOfChunk(go.transform.position);
    

我找不到您保存块的位置,但您希望以只生成所需的新块的方式执行此操作。

【讨论】:

以上是关于我的自定义地形生成插件实例化了很多预制件的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D日常开发UI预制体的实例化实操演示

Unity2D:在订单中禁用实例化的预制件

当我第二次实例化预制件时,为啥会出现错误?

Unity快速入门教程-详解预制体(Prefab)及其实例化Instantiate

发生碰撞时如何实例化预制件c#

如何在运行时控制实例化的预制件作为孩子