Среда, 18 Декабря 2024, 18:58

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Защита от пересечения генерируемых объектов
mrFrankensteinДата: Воскресенье, 10 Мая 2020, 22:49 | Сообщение # 1
частый гость
Сейчас нет на сайте
На сцене перед началом игры случайно генерируются части уровня, всячески поворачивая и закручиваясь. Иногда они закручиваются сами в себя, а иногда большой кусок ставится в маленькой пространство. вот как-то так получается http://s1.uploadpics.ru/images/-yyDLbFjpB.png
Надо как-то придумать проверку для того, чтобы знать когда можно ставить кусочки а когда нельзя, а я не могу придумать(
Помогите :)

Добавлено (12 Мая 2020, 18:24)
---------------------------------------------
Короче. Рас уж никто мне не может помочь, то буду делать сам и пусть вам, дорогие друзья, будет стыдно crazy
На данный момент придумал я такую штуку: перед установкой нужного объекта на своё место на это место ставится примитив (куб) который ещё и триггер. Триггер меняет размеры примерно имитируя размеры возможных комнат, а результаты пишутся в массив. Если такой-то размер задевает другие объекты, то комнату такого-то размера суда ставить нельзя. Осталось только придумать, как в нулевой промежуток времени (между строчками кода) проверить касается ли триггера что-нибудь или нет, т.к. OnTriggerStay-Enter работают не так, да и вдобавок енто в дугом скрипте делается, а я так не хочу.
Короче, пойду искать инфу. Вернусь завтра ^_^ ну, или когда там получится)


Сообщение отредактировал mrFrankenstein - Вторник, 12 Мая 2020, 18:27
Storm54Дата: Вторник, 12 Мая 2020, 19:16 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
Можно проверять без костылей с триггерами, например через Physics.OverlapBox или подобный метод. А можно проверять без использования средств Unity, задав каждой комнате прямоугольник или параллелепипед (если требуется 3D) и проверять пересечение этих фигур. Проблема же не только в пересечении, а в целом в алгоритме генерации лабиринтов? Парой строк кода здесь не обойдешься.
mrFrankensteinДата: Среда, 13 Мая 2020, 18:32 | Сообщение # 3
частый гость
Сейчас нет на сайте
Да вот нет, мне кажется, что как раз обойдешься. И Physics.OverlapBox, возможно, как раз то, что я ищу. Заранее спасибо)

Сейчас код выглядит так

Код

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CaveCreator : MonoBehaviour
{
public GameObject[] caveSpavnPoint;    //хранилище найденых точек установки частей пещеры
public GameObject[] spawnObjects;    //устанавливаемые обьекты
public GameObject[] spawnedObj;    //установленные обьекты
public int caveLong;    // задаём длинну пещеры

private int I=0;    //счётчик длинны пещеры
private GameObject Instantiat;    //надо подумать как без этого
public Bounds b;    //попробуем с бондами избавится от пересечения

void Start()
{
spawnedObj= new GameObject[caveLong];    //устанавливаем длинну массива
}

void Update()
{
if(caveLong>I)    //если ещё надо ставить куски то...
{
caveSpavnPoint = GameObject.FindGameObjectsWithTag("CaveSpawnPoint");    //ищем все точки для спавна
if(caveSpavnPoint.Length>=2)    //если нашлось больше 2-х точек то...
{
GameObject spawn = new GameObject();    //создаём обьект для выбора рондомного кусочка
spawn=caveSpavnPoint[Random.Range(0,(caveSpavnPoint.Length-1))];    //выбераем кусочек
Instantiat=GameObject.Instantiate(spawnObjects[Random.Range(0,(spawnObjects.Length-1))],spawn.transform.position,spawn.transform.rotation) as GameObject;    //ставим кусочек
spawnedObj[I]=Instantiat;    //записываем установленный кусочек в массив
Destroy(spawn);    //удаляем точку спавна
b = new Bounds(spawnedObj[I].transform.Find("main").position, new Vector3(112, 112, 12));    //пытаюсь разобраться с бондами
}
else    //если точек спавна мень 2-х то...
{
Instantiat=GameObject.Instantiate(spawnObjects[0],caveSpavnPoint[0].transform.position,caveSpavnPoint[0].transform.rotation) as GameObject;    //не мудрствуя лукаво ставим кусочек
spawnedObj[I]=Instantiat;    //записываем установленный кусочек в массив
Destroy(caveSpavnPoint[0]);    //удаляем точку спавна
}
I++;    //рибавляем 1 к счётчику
}
}
}

Посмотрим, что из него получится)

Добавлено (14 Мая 2020, 23:44)
---------------------------------------------
И вот я снова тут. Это было сложно, но я что-то сделал crazy
По крайней мере оно работает и даже так, как я хотел)
А вот собственно и код. Если есть замечания и предложения- бичуйте меня по чём зря! Нечего тут рассусоливать! Если говно- то и говорите что говно, но с оговорками что и как можно исправить)

Код
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CaveCreator : MonoBehaviour
{
    public Vector3 startPointPos;  //запомнить стартовую позицию
    public Quaternion startPointRot;  //и направление
    public int misTry;  //счётчик неудачных установок

    public GameObject[] caveSpavnPoint;    //хранилище найденых точек установки частей пещеры
    public GameObject[] spawnObjects;    //устанавливаемые обьекты
    public GameObject[] spawnRums;    //обьект для выбора онончаний тонелей
    public GameObject[] spawnedObj;    //установленные обьекты
    public GameObject spawn;    //обьект для выбора рондомного кусочка
    public int caveLong;    // задаём длинну пещеры

    private int I=0;    //счётчик длинны пещеры
    private GameObject Instantiat;    //надо подумать как без этого
    
    bool Started;  //для гизмо для инспектора. Удалить по окончании!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    //чтобы не создавать новые переменные во время работы кода
    //создаём переменные, в кторые будут сохранятся переменные колайдёра
    //для проверки столкновений с другими коллайдёрами
    Vector3 positionOfCave;  //сохраняем позицию
    Vector3 sizeOfCave;   //и размер
    Quaternion rotOfCave;  //и направление

    void Start()
    {
        spawnedObj= new GameObject[(caveLong+10)];    //устанавливаем длинну массива
        Started = true;  //это штука для работы гизмо в инспекторе. Удалить!!!!!!!!!!!!!!!!!!!!!!!!!
        startPointPos=GameObject.FindWithTag("CaveSpawnPoint").transform.position;  //запоминаем стартовую позицию
        startPointRot=GameObject.FindWithTag("CaveSpawnPoint").transform.rotation;  //и направление обьекта, из которого будет начинаться пещера
    }

    void Update()
    {
     if(misTry>25)  //если ошибок больше 25
     {
      misTry=0;  //обнуляем счётчик ошибок
      GameObject star = new GameObject();  //создаём новый обьект в сцене. Да, от этого все эти непонятные "New Game Objeсt". Больше не использую такую нострукцию
      star.transform.position=startPointPos;  //задаём обьекту нужную позицию
      star.transform.rotation=startPointRot;  //и напавление
      star.tag = "CaveSpawnPoint";  //и нужный таг тоже

      for(int i=0; i<spawnedObj.Length-1; i++)  //циклом удаляем все уже созданные обьекты
      {
       Destroy(spawnedObj[i]);  
      }

      spawnedObj= new GameObject[caveLong+10];  //обуляем массив созданных обьектов чтоб наверняка
      I=0;  //ну и обнуляем счётчик длинны пещеры
     }
     else  //если ошибок не больше 25, то
     {
      caveSpavnPoint = GameObject.FindGameObjectsWithTag("CaveSpawnPoint");    //ищем все точки для спавна
      if(caveSpavnPoint.Length >0)    //если ещё надо ставить куски то...
      {
       spawn=caveSpavnPoint[Random.Range(0,(caveSpavnPoint.Length-1))];    //берём случайный кусочек

       if(caveSpavnPoint.Length +I <= caveLong)  //если не достаточно проходов и не нужно ставить комнаты
       {
        Instantiat=GameObject.Instantiate(spawnObjects[Random.Range(0,spawnObjects.Length)],spawn.transform.position,spawn.transform.rotation) as GameObject;    //ставим кусочек
       }
       else  //если достаточно проходов и нужно ставить комнаты
       {
        Instantiat=GameObject.Instantiate(spawnRums[Random.Range(0,spawnRums.Length)],spawn.transform.position,spawn.transform.rotation) as GameObject;    //ставим комнаты
       }
       spawnedObj[I]=Instantiat;  //записываем установленный кусочек в массив
       string nam=I.ToString();  //переводим цифры в буквы
       spawnedObj[I].name=nam ;  //переименовываем установленный кусочек в номер
      
          positionOfCave=spawnedObj[I].transform.Find("box").transform.position;  //из только что установленного кусочка выдераем обьект, который размерами как комната, только это простой квадрат
          sizeOfCave=spawnedObj[I].transform.Find("box").GetComponent<Collider>().bounds.size;  //выдераем из квадрата его размер в мировых кординатах
          rotOfCave=spawnedObj[I].transform.rotation;  //и направление

          spawnedObj[I].SetActive(false);  //основной же обьект скрываем на время проверки
          Collider[] colliders = Physics.OverlapBox(positionOfCave, sizeOfCave, rotOfCave);  //собственно, делаем проверку

          if(colliders.Length>=1)  //если проверка показала, что мы чего-то касаемся, то...
          {
           misTry++;  //+1 в ошибки
           Destroy(spawnedObj[I]);  //удаляем установленный обьект
          }
          else  //если проверка показала, что мы ничего не касаемся, то...
          {
           misTry=0;  //обнуляем счётчик ошибок
           spawnedObj[I].SetActive(true);  //включаем наш главный обьект
           Destroy(spawnedObj[I].transform.Find("box").gameObject);  //удаляем уже ненужный квадрат
           Destroy(spawn);    //удаляем точку спавна
           I++;    //прибавляем 1 к счётчику
          }
      }
  }
    }

    void OnDrawGizmos()  //эта штака нужна только для гизмо в инспекторе. Удалить!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    {
        Gizmos.color = Color.red;
        if (Started)
            Gizmos.DrawWireCube(positionOfCave, sizeOfCave);
    }
}


Сообщение отредактировал mrFrankenstein - Среда, 13 Мая 2020, 18:33
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг