Задать вопрос
@dima89e

Почему после запекания и объединения мешей остается еще 1 грань?

я же вроде все удалил которые внутри

6826c7bd2811a074274477.png
6826c7d25719f283820664.png
6826c7d823829190084872.png

вот грань внутри с 1 стороны после запекания
6826c7ed48a1b247774572.png

вот грань внутри с 2 стороны после запекания
6826c7ff16a72231808151.png

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

public class WorldBaker : MonoBehaviour
{
  [SerializeField] private List<GameObject> blocksToBake = new List<GameObject>();
  [SerializeField] private GameObject combinedContainer;
  [SerializeField] private LayerMask groundLayer;

  const float BlockScale = 1;

  private Mesh cubeMesh;
  private Transform currentBlock;

  private List<Vector3> verticies = new List<Vector3>();
  private List<Vector2> uvs = new List<Vector2>();
  private List<int> triangles = new List<int>();

  private List<CombineInstance> combineInstances = new List<CombineInstance>();

  [ContextMenu("Bake World")]
  public void BakeWorld()
  {
    foreach (var item in blocksToBake)
    {
      currentBlock = item.transform;
      cubeMesh = new Mesh();
      // var combine = new CombineInstance[blocksToBake.Count];

      // Удаляем существующий Collider (если есть)
      Collider existingCollider = currentBlock.gameObject.GetComponent<Collider>();
      if (existingCollider != null)
      {
        UnityEngine.Object.DestroyImmediate(existingCollider);
      }
      currentBlock.gameObject.AddComponent<MeshCollider>();

      RemakeMesh();

      CombineInstance ci = new CombineInstance();
      ci.mesh = cubeMesh;
      ci.transform = currentBlock.localToWorldMatrix;
      combineInstances.Add(ci);

      // MeshFilter meshFilter = item.GetComponent<MeshFilter>();
      // meshFilter.sharedMesh = cubeMesh;
      // meshFilter.transform.position = currentBlock.position; // Устанавливаем позицию меша равной позиции блока

      // cubeMesh.CombineMeshes(combine);

      item.SetActive(false);
    }

    Mesh finalMesh = new Mesh();
    finalMesh.CombineMeshes(combineInstances.ToArray());

    // Присваиваем объединенный меш combinedContainer
    MeshFilter containerFilter = combinedContainer.GetComponent<MeshFilter>();
    if (containerFilter == null)
    {
      containerFilter = combinedContainer.AddComponent<MeshFilter>();
    }
    containerFilter.sharedMesh = finalMesh;

    // Добавляем коллайдер к объединенному контейнеру
    MeshCollider containerCollider = combinedContainer.GetComponent<MeshCollider>();
    if (containerCollider == null)
    {
      containerCollider = combinedContainer.AddComponent<MeshCollider>();
    }
    containerCollider.sharedMesh = finalMesh;

    print("baked and combined");
  }

  private void RemakeMesh()
  {
    verticies.Clear();
    uvs.Clear();
    triangles.Clear();

    RemakeBlock();

    cubeMesh.triangles = Array.Empty<int>();
    cubeMesh.vertices = verticies.ToArray();
    cubeMesh.uv = uvs.ToArray();
    cubeMesh.triangles = triangles.ToArray();

    cubeMesh.Optimize();

    cubeMesh.RecalculateNormals();
    cubeMesh.RecalculateBounds();

    currentBlock.GetComponent<MeshCollider>().sharedMesh = cubeMesh;
  }

  private void RemakeBlock()
  {
    if (!Physics.Raycast(currentBlock.position, Vector3.right, BlockScale, groundLayer)) GenerateRightSide();
    if (!Physics.Raycast(currentBlock.position, Vector3.left, BlockScale, groundLayer)) GenerateLeftSide();
    if (!Physics.Raycast(currentBlock.position, Vector3.forward, BlockScale, groundLayer)) GenerateFrontSide();
    if (!Physics.Raycast(currentBlock.position, Vector3.back, BlockScale, groundLayer)) GenerateBackSide();
    if (!Physics.Raycast(currentBlock.position, Vector3.up, BlockScale, groundLayer)) GenerateTopSide();
    if (!Physics.Raycast(currentBlock.position, Vector3.down, BlockScale, groundLayer)) GenerateBottomSide();
  }

  private void GenerateRightSide()
  {
    verticies.Add(new Vector3(1, 0, 0));
    verticies.Add(new Vector3(1, 1, 0));
    verticies.Add(new Vector3(1, 0, 1));
    verticies.Add(new Vector3(1, 1, 1));

    AddLastVerticiesSquare();
  }

  private void GenerateLeftSide()
  {
    verticies.Add(new Vector3(0, 0, 0));
    verticies.Add(new Vector3(0, 0, 1));
    verticies.Add(new Vector3(0, 1, 0));
    verticies.Add(new Vector3(0, 1, 1));

    AddLastVerticiesSquare();
  }

  private void GenerateFrontSide()
  {
    verticies.Add(new Vector3(0, 0, 1));
    verticies.Add(new Vector3(1, 0, 1));
    verticies.Add(new Vector3(0, 1, 1));
    verticies.Add(new Vector3(1, 1, 1));

    AddLastVerticiesSquare();
  }

  private void GenerateBackSide()
  {
    verticies.Add(new Vector3(0, 0, 0));
    verticies.Add(new Vector3(0, 1, 0));
    verticies.Add(new Vector3(1, 0, 0));
    verticies.Add(new Vector3(1, 1, 0));

    AddLastVerticiesSquare();
  }

  private void GenerateTopSide()
  {
    verticies.Add(new Vector3(0, 1, 0));
    verticies.Add(new Vector3(0, 1, 1));
    verticies.Add(new Vector3(1, 1, 0));
    verticies.Add(new Vector3(1, 1, 1));

    AddLastVerticiesSquare();
  }

  private void GenerateBottomSide()
  {
    verticies.Add(new Vector3(0, 0, 0));
    verticies.Add(new Vector3(1, 0, 0));
    verticies.Add(new Vector3(0, 0, 1));
    verticies.Add(new Vector3(1, 0, 1));

    AddLastVerticiesSquare();
  }

  private void AddLastVerticiesSquare()
  {
    uvs.Add(new Vector2(0, 0));
    uvs.Add(new Vector2(0, 1));
    uvs.Add(new Vector2(1, 0));
    uvs.Add(new Vector2(1, 1));

    triangles.Add(verticies.Count - 4);
    triangles.Add(verticies.Count - 3);
    triangles.Add(verticies.Count - 2);

    triangles.Add(verticies.Count - 3);
    triangles.Add(verticies.Count - 1);
    triangles.Add(verticies.Count - 2);
  }
}
  • Вопрос задан
  • 40 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 1
@DrRen7
а если в RemakeBlock() сработал Raycast не надо пересчитать мэш в который он попал ?
Но лучше отказаться от RemakeBlock(), сделать трехмерный массив(размером чанка с типами блоков) добавлять блоки в массив а в RemakeBlock() делать проверку на типо
if (_сhunks(this.x,this.y,this.z+1)==BlockType.empty) GenerateFrontSide();

плюс в том чанк легко сгенерировать, и можно можно хранить различные типы блоков

По сути надо отказать от создания конкретного блока и перейти в создание массива блоков, надо что бы где то массив чанков заполнился потом отправить его в этот скрипт и пробежаться for'ом по массиву и генерировать так если this.x,thiz.z,this.z == BlockType.empty &&this.x,thiz.z,this.z+1 != BlockType.empty => GenerateFrontSide() а в метод ещё и тип поверхности можно передать
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы