Unity3D 房间去重叠化算法详解

news/2024/10/3 23:19:04/

前言
Unity3D>Unity3D游戏开发中,经常需要生成和处理多个房间的场景,特别是在地牢生成、房屋布局或迷宫设计等应用中。为了确保生成的房间不会重叠,我们需要一种有效的去重叠化算法。以下将详细介绍该算法的原理和代码实现。
对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!
算法原理
房间表示:
每个房间可以表示为一个矩形,其位置和大小由其在世界坐标系中的位置(x, y, z)以及宽度和高度决定。在Unity3D>Unity3D中,通常使用Rect组件或自定义的DungeonCell类来表示房间。
重叠检测:
重叠检测是判断两个房间是否相交的过程。这可以通过比较两个矩形的边界来实现。如果两个矩形的任意一边相交,则它们重叠。
移动房间:
一旦检测到重叠,就需要移动其中一个房间以避免重叠。移动的方向和距离可以根据重叠的严重程度来计算。一种简单的方法是计算两个房间中心点的差值,然后移动重叠的房间,使其中心点沿这个差值方向移动一定距离。
迭代处理:
由于移动一个房间可能会导致它与另一个房间重叠,因此需要迭代处理,直到所有房间都不重叠为止。
代码实现
以下是一个Unity3D>Unity3D中实现房间去重叠化算法的示例代码。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Linq;

public class DungeonCell : MonoBehaviour

{

public Rect CellRect { get; private set; }

public Vector3 Position { get; private set; }

public int Width { get; private set; }

public int Height { get; private set; }

public CellType cellType { get; set; }

public enum CellType

{

Normal,

Hall

}

public void CreateCell(int width, int height)

{

Width = width;

Height = height;

Position = transform.position;

CellRect = new Rect(Position.x - Width / 2, Position.z - Height / 2, Width, Height);

}

public void MoveTo(Vector3 position)

{

transform.position = position;

Position = position;

CellRect = new Rect(Position.x - Width / 2, Position.z - Height / 2, Width, Height);

}

public bool Overlap(DungeonCell comparedCell)

{

return CellRect.Overlaps(comparedCell.CellRect);

}

}

public class DungeonMaker : MonoBehaviour

{

public float CellCreationRadius = 150;

public int NumberOfCells = 40;

public int NumberOfHalls = 12;

public List<DungeonCell> cellsList = new List<DungeonCell>();

public int MinWidth = 3;

public int MaxWidth = 8;

public int MinLength = 3;

public int MaxLength = 8;

public float movementForce = 4.0f;

public List<DungeonCell> importantCells = new List<DungeonCell>();

void Start()

{

CreateCells();

SeparateCells();

MarkImportantCell();

}

private void CreateCells()

{

for (int i = 0; i < NumberOfCells; i++)

{

Vector2 Position2D = Random.insideUnitCircle * CellCreationRadius;

GameObject gameObjectPointer = new GameObject("Cell" + i);

DungeonCell cellPointer = gameObjectPointer.AddComponent<DungeonCell>();

cellPointer.CreateCell(Random.Range(MinWidth, MaxWidth + 1), Random.Range(MinLength, MaxLength + 1));

cellPointer.MoveTo(new Vector3(Position2D.x, 0, Position2D.y));

cellsList.Add(cellPointer);

}

}

private void SeparateCells()

{

bool allCellsNotOverlap = false;

while (!allCellsNotOverlap)

{

allCellsNotOverlap = true;

foreach (DungeonCell currentCell in cellsList)

{

Vector3 movementVector = Vector3.zero;

int numberOfOverlaps = 0;

foreach (DungeonCell comparedCell in cellsList)

{

if (currentCell == comparedCell) continue;

if (currentCell.Overlap(comparedCell))

{

movementVector += currentCell.transform.position - comparedCell.transform.position;

numberOfOverlaps++;

}

}

if (numberOfOverlaps != 0)

{

allCellsNotOverlap = false;

if (movementVector.magnitude > 0)

{

movementVector = movementVector.normalized * movementForce;

}

else

{

movementVector = Random.insideUnitCircle.normalized * movementForce;

}

currentCell.MoveTo(currentCell.transform.position + movementVector);

}

}

}

}

private void MarkImportantCell()

{

importantCells = cellsList.OrderByDescending(n => n.CellRect.width * n.CellRect.height).ToList();

for (int i = 0; i < NumberOfHalls; i++)

{

importantCells[i].cellType = DungeonCell.CellType.Hall;

}

}

}

技术详解
DungeonCell 类:
CreateCell 方法用于初始化房间的大小和位置,并计算其Rect边界。
MoveTo 方法用于更新房间的位置,并重新计算其Rect边界。
Overlap 方法用于检测两个房间是否重叠。

DungeonMaker 类:
CreateCells 方法用于随机生成指定数量的房间,并将它们添加到cellsList中。
SeparateCells 方法用于迭代处理房间重叠问题。通过计算重叠房间的移动向量,并将房间移动到新位置来避免重叠。
MarkImportantCell 方法用于根据房间大小将房间标记为重要房间(如大厅),以便后续处理。

通过该算法和代码实现,可以有效地解决Unity3D>Unity3D中房间重叠的问题,并为后续的房间布局和场景生成提供基础。
更多教学视频
Unity3D>Unity3D

www.bycwedu.com/promotion_channels/2146264125


http://www.ppmy.cn/news/1534146.html

相关文章

kubernetes笔记(一)

kubernetes安装&#xff1a; 主机清单 主机名IP地址最低配置master192.168.1.502CPU,4G内存node-0001192.168.1.512CPU,4G内存node-0002192.168.1.522CPU,4G内存node-0003192.168.1.532CPU,4G内存node-0004192.168.1.542CPU,4G内存node-0005192.168.1.552CPU,4G内存harbor192…

828华为云征文|华为云 Flexus X 实例初体验

一直想有自己的一款的服务器&#xff0c;为了更好的进行家庭娱乐&#xff0c;甚至偶尔可以满足个人搭建开发环境的需求&#xff0c;直到接触到了华为云 Flexus X 云服务器。Flexus 云服务器 X 实例是面向中小企业和开发者打造的轻量级云服务器。提供快速应用部署和简易的管理能…

以太网交换安全:MAC地址表安全

一、MAC地址表安全 MAC地址表安全是网络安全中的一个重要方面&#xff0c;它涉及到网络设备的MAC地址表的管理和保护。以下是对MAC地址表安全的详细介绍&#xff1a; &#xff08;1&#xff09;基本概念 定义&#xff1a;MAC地址表是网络设备&#xff08;如交换机&#xff0…

electron出现乱码和使用cmd出现乱码

第一种出现乱码。这种可以通过chcp 65001&#xff0c;设置为utf-8的编码。第二种&#xff0c;是执行exec的时候出现乱码&#xff0c;这个时候需要设置一些编码格式&#xff0c;可以通过iconv-lite进行解决&#xff0c;这个方法是node自带的&#xff0c;所以不需要导入。使用方法…

人工智能价格战——如何降低成本让人工智能更易于普及

十年前&#xff0c;开发人工智能 (AI) 是只有大公司和资金充足的研究机构才能负担得起的事情。必要的硬件、软件和数据存储成本非常高。但从那时起&#xff0c;情况发生了很大变化。一切始于 2012 年的 AlexNet&#xff0c;这是一种深度学习模型&#xff0c;展示了神经网络的真…

主流前端框架实际案例说明

为了更深入地理解不同前端框架的特点和适用场景&#xff0c;以下将通过几个具体案例分析&#xff0c;探讨在实际项目中选择框架的决策过程。 案例一&#xff1a;电商平台开发 项目背景 一个新兴电商平台希望快速上线&#xff0c;提供良好的用户体验和性能&#xff0c;同时需…

Electron应用创建和打包

一、创建项目目录 创建NodeJs项目目录&#xff0c;项目有关的文件、依赖包都将在本目录创建和安装。 mkdir hello_electron & cd hello_electronCMD执行以上命令将在用户目录下创建hello_electron并进入该目录。当然也可以手动在任何地方创建目录&#xff0c;cmd中cd 路径…

【YashanDB知识库】如何dump数据文件,转换rowid, 查询对应内容

本文来自YashanDB官网&#xff0c;具体内容可见https://www.yashandb.com/newsinfo/7459464.html?templateId1718516 问题现象 客户环境有时候会遇到文件损坏的情况&#xff0c;需要dump文件&#xff0c;根据rowid查询数据情况。 问题的风险及影响 熟练掌握崖山数据文件du…