Скрипт генерации мира не соединяет объекты

401
18 августа 2021, 01:20

Я написал скрипт генерации воксельного мира, в котором после генерации площяди, скрипт соединяет 1 чанк в 1 меш. Но этого не происходит т.к. скрипт не назначил сгенерированные воксели к родителю Chunk. Почему, и как это решить? Скрипт:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chunk : MonoBehaviour
{
    public GameObject currentBlockType;
    public int Seed;
    public bool randomizeSeed;
    public float smooth = 0;
    public float multiplier = 0;
    public int cols = 50;
    public int rows = 50;
    public bool CombineChunk;
    private Vector3 myPos;
    private Transform thisObject;
    static private GameObject thisobjscr;
    private void Start()
    {
        thisobjscr = gameObject;
        thisObject = gameObject.transform;
        if(randomizeSeed == true)
        {
            Seed = Random.Range(1, 200);
        }
    }
    public void OnTriggerEnter(Collider other)
    {
        if(other.tag == "gen")
        {
            print("entered");
            generate();
        }
    }

    public void generate()
    {
        myPos = this.transform.position;
        for (int x = 0; x < cols; x++)
        {
            for (int z = 0; z < rows; z++)
            {
                float y = Mathf.PerlinNoise((myPos.x + x) / smooth + Seed, (myPos.z + z) / smooth + Seed) * multiplier;
                y = Mathf.Floor(y);
                GameObject newBlock = GameObject.Instantiate(currentBlockType);
                newBlock.transform.position = new Vector3(myPos.x + x, y, myPos.z + z );

                if (CombineChunk == true)
                {
                    newBlock.transform.SetParent(thisObject);
                    StartCoroutine(TimerForCombineWait());
                }
            }
        }
    }
    IEnumerator TimerForCombineWait()
    {
        CombineChunk = false;
        print("waiting for world stabilization: " + Time.time);
        yield return new WaitForSeconds(1);
        print("world stabilized in " + Time.time);
        Combine();
    }
    public void Combine()
    {
        MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
        CombineInstance[] combine = new CombineInstance[meshFilters.Length];
        int a = 0;
        while (a < meshFilters.Length)
        {
            combine[a].mesh = meshFilters[a].sharedMesh;
            combine[a].transform = meshFilters[a].transform.localToWorldMatrix;
            meshFilters[a].gameObject.SetActive(false);
            a++;
        }
        transform.GetComponent<MeshFilter>().mesh = new Mesh();
        transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
        transform.gameObject.SetActive(true);
        gameObject.transform.position = new Vector3(0, 0, 0);
    }
}

Спасибо.

Answer 1

Я нашел решение, я просто переместил пониже функцию combine и SetParent. А так же добавил состояние сгенерированного, что бы скрип не залагивал при генерации бесконечного количества терраинов. Всё стало выглядить как то так:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chunk : MonoBehaviour
{
    public GameObject currentBlockType;
    public int Seed;
    public bool randomizeSeed;
    public float smooth = 0;
    public float multiplier = 0;
    public int cols = 50;
    public int rows = 50;
    public bool CombineChunk;
    public bool Lock;
    private Vector3 myPos;
    private Transform thisObject;
    static private GameObject thisobjscr;
    private void Start()
    {
        if(randomizeSeed == true)
        {
            Seed = Random.Range(1, 200);
        }
    }
    public void OnTriggerEnter(Collider other)
    {
        if(other.tag == "gen")
        {
            print("entered");
            Generate();
        }
    }

    public void Generate()
    {
        if (Lock == false)
        {
            thisobjscr = gameObject;
            thisObject = gameObject.transform;
            myPos = this.transform.position;
            for (int x = 0; x < cols; x++)
            {
                for (int z = 0; z < rows; z++)
                {
                    float y = Mathf.PerlinNoise((myPos.x + x) / smooth + Seed, (myPos.z + z) / smooth + Seed) * multiplier;
                    y = Mathf.Floor(y);
                    GameObject newBlock = GameObject.Instantiate(currentBlockType);
                    newBlock.transform.position = new Vector3(myPos.x + x, y, myPos.z + z);
                    newBlock.transform.SetParent(gameObject.transform);
                    if (CombineChunk == true)
                    {
                        StartCoroutine(TimerForCombineWait());
                    }
                }
            }
        }
    }
    IEnumerator TimerForCombineWait()
    {
        print(Time.time);
        yield return new WaitForSeconds(1);
        Combine();
        print(Time.time);
    }
    public void Combine()
    {
        MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
        CombineInstance[] combine = new CombineInstance[meshFilters.Length];
        int a = 0;
        while (a < meshFilters.Length)
        {
            combine[a].mesh = meshFilters[a].sharedMesh;
            combine[a].transform = meshFilters[a].transform.localToWorldMatrix;
            meshFilters[a].gameObject.SetActive(false);
            a++;
        }
        transform.GetComponent<MeshFilter>().mesh = new Mesh();
        transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
        transform.gameObject.SetActive(true);
        gameObject.transform.position = new Vector3(0, 0, 0);
        Lock = true;
    }
}