Оптимальная генерация 2D ландшафта

Speed Tree : Terrain & Trees.

Оптимальная генерация 2D ландшафта

Сообщение HarvestNide 04 июл 2017, 19:34

Здравствуйте. /* Возможно, задаю невероятно глупый вопрос, но разобраться методом тыка не вышло */
Пишу скрипт для генерации ландшафта для 2D игры с видом сбоку. Предполагается возможность разрушать блоки. Воспользовался алгоритмом "midpoint displacement". За один проход рекурсивно заполняется один слой блоков, далее - второй слой, потом заполняется полость между ними. Учитывая размер одного блока (8 пикселей х 8 пикселей) получается примерно 11 тысяч ГО на экране в каждый момент времени, что точно негативно отражается на производительности. Каким образом можно оптимизировать?

Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LandscapeGenerator : MonoBehaviour {

        public int counter = 0;
        [SerializeField] GameObject ground;
        [SerializeField] GameObject stone;
        private GameObject ActiveLayer;
        float xBegin = -5;
        float xEnd = 5;
        [SerializeField] float roughness; //во сколько блоков перепад высот
        private float distance;

        SortedDictionary<float, float> PreviousLayer;//для хранения координат блоков слоя, который заполняется в данный момент
        SortedDictionary<float, float> thisLayer;//для хранения координат блоков предыдущего слоя

        void Awake(){
                PreviousLayer = new SortedDictionary<float, float>();
                thisLayer = new SortedDictionary<float, float>();
                distance = ground.GetComponent<SpriteRenderer>().bounds.size.x;//размер блока(слава квадратности)
                roughness *= distance;//перевод рандомного числа в блоки
                float[] begin = {1, -5};//рандомные значения по y для левого края всех слоев
                float[] end = {3, -5};//аналогично, для правого
                GameObject[] layers = {ground, stone};//из каких ГО составлять слой
                StartGenerator(layers, begin, end);
        }

        public void StartGenerator(GameObject[] Layers, float[] Begin, float[] End){
                for(int i = 0; i < Layers.Length; i++){
                        ActiveLayer = Layers[i];
                        float yBegin = Begin[i];
                        float yEnd = End[i];
                        CheckValues(xBegin, yBegin);
                        CheckValues(xEnd, yEnd);
                        GenerateLayer(xBegin, yBegin, xEnd, yEnd);
                        foreach(KeyValuePair<float, float> entry in PreviousLayer){
                                float topValue = thisLayer[entry.Key];
                                Debug.Log((entry.Value + distance) + " " + topValue);
                                for(float y = entry.Value + distance; y > topValue; y -= distance){
                                        putBlock(entry.Key, y);
                                }
                        }
                        PreviousLayer = new SortedDictionary<float,float>();
                        foreach(KeyValuePair<float, float> entry in thisLayer)
                                PreviousLayer.Add(entry.Key, entry.Value);
                        thisLayer = new SortedDictionary<float, float>();
                }
                Debug.Log(counter);
        }

        private void GenerateLayer(float x1, float y1, float x2, float y2){
                float x = (x1 + x2) / 2;
                float y = (y1 + y2) / 2 + Random.Range(roughness * (x - x1) * (-1), roughness * (x - x1));
                CheckValues(x, y);
                if(x - x1 > distance)
                        GenerateLayer(x1, y1, x, y);
                if(x2 - x > distance)
                        GenerateLayer(x, y, x2, y2);
        }

        private void CheckValues(float x, float y){//чтобы блок не оказался не там, где нужно. По сути - создание квадратной сетки
                y = Mathf.Round(y / distance) * distance;
                x = Mathf.Round(x / distance) * distance;
                if(!thisLayer.ContainsKey(x)){
                        thisLayer.Add(x, y);
                        putBlock(x, y);
                }
        }

        private void putBlock(float x, float y){
                Instantiate(ActiveLayer, new Vector3(x, y, 0), Quaternion.identity);
                counter++;
        }
}
HarvestNide
UNец
 
Сообщения: 1
Зарегистрирован: 04 июл 2017, 19:22

Re: Оптимальная генерация 2D ландшафта

Сообщение istreloi 04 сен 2018, 10:55

отключать го которые не видно в камере(длать не активными) это если они все уже поставлены(загружены)
или всю карту в массив(типы го) а потом по мере продвижения игрока подгружать перед ним опираясь на массив а что по зади удолять либо делать не активным.
но помоиму постоянная выгрузка и удаление го сильно нагружает и проц (там какойто стандартный чистильщик памяти устройства толи он не успевает если много толи слишком много обращений к нему) как то так.
я создавал рандомно область карты вокруг персонажа на расстоянии которое в камеру попадает и записывал эту область в массив (в массиве тип го, его угол и координаты), и так постепенно создавалась рандомная карта(размер естественно ограничен размером массива).
тоесть модельки со скриптами только в области которую видит камера отстолное либо не активно либо удалено.
Аватара пользователя
istreloi
UNец
 
Сообщения: 16
Зарегистрирован: 15 апр 2014, 15:46


Вернуться в Земля и деревья.

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2