Unity 实现2D地面挖洞!涂抹地形(碰撞部分,方法二)

文章目录

  • 前言
  • 一、初始化虚拟点
      • 1.1点结构:
      • 1.2每个点有的状态:
      • 1.3生成点结构:
  • 二、实例化边缘碰撞盒
      • 2.1计算生成边缘碰撞盒
  • 三、涂抹部分
      • 3.1.虚拟点
      • 3.2.鼠标点
      • 3.3.内圈
      • 3.4.外圈
  • 四、关于优化
  • 结语:


前言

老规矩先上效果图
在这里插入图片描述

继上一篇涂抹地形文章讲解发出后,有不少网友私信找我要原码,也有部分网友觉得太复杂了难以实现。关于原码因为这个Demo最初始的原码弄不见了,还有就是代码本身用在了公司的游戏项目中加了很多项目相关的逻辑,我不知道能不能分享所以没有直接公布原码。关于太难实现的问题,如果只是要达到涂抹地形的话这里我再分享一个更简单的方式,非常简单!

上一篇的地址:
涂抹地形碰撞部分方法一

为什么说简单呢,因为只需要用到距离计算公式,与圆形碰撞盒:
在这里插入图片描述

好了下面开始进入正文…


一、初始化虚拟点

初始化的时候创建检查点,用数组存起来。
需要注意的是这里的检查点只是Vector2,不需要实例化否则会非常消耗性能。切记切记…

1.1点结构:

每个点用一个结构存起来,我们需要存下
下面是点数据结构,分别是记录:1.点的位置,2.当前点的状态,3.对应的碰撞盒

private class PointData
{
    public Vector2 pos;               //点位置
    public pointStatic sta;          //点状态
    public GameObject col;          //点实例
}

1.2每个点有的状态:

1.已经废弃,这个位置已经被完全挖开
2.等待检测,这个位置还没被挖到
3.正在使用:即这个位置是挖掘的边缘,有碰撞盒

private enum pointStatic
{
    die,                        //已经废弃
    wait,                       //等待检测
    collid                      //正在使用
}

1.3生成点结构:

int line = (int)(scale.x * 100);
int row = (int)(scale.y * 100);
float distancesX = 1f / line;
float distancesY = 1f / row;
for (int j = 0; j < row; j++)
{
    for (int k = 0; k < line; k++)
    {
        Vector2 v2 = new Vector2(distancesX * k - 0.5f, distancesY * j - 0.5f);
        PointData data = new PointData();
        data.pos = v2;
        data.sta = pointStatic.wait;
        listPoint.Add(data);
    }
}

不难看出这些结构点,除了Vector2以外并没有实例化什么内容,主要是这里创建了10000个点,这样可以极大的节省性能.
其实就像如图,创建了100X100个虚拟点:
在这里插入图片描述


二、实例化边缘碰撞盒

为了一开始还未操作时,物体不会从方块边缘直接穿过去过,我们需要将边缘的点先实例化出碰撞盒,效果如图:
在这里插入图片描述

2.1计算生成边缘碰撞盒

下面方法计算出边缘位置,并生成一边缘一圈碰撞盒,并将点记录到上面的数组中,这样后面涂抹的时候才可以将碰撞盒去掉.
计算边缘位置并生成的代码:

distancesX *= 3;
distancesY *= 3;
for (float x = -0.5f; x <= 0.5; x += distancesX)
{
    CreateBianKuan(new Vector3(x, -0.5f, 0));
    CreateBianKuan(new Vector3(x, 0.5f, 0));
    CreateBianKuan(new Vector3(-0.5f, x, 0));
    CreateBianKuan(new Vector3(0.5f, x, 0));
}
下面是具体生成的代码:
public void CreateBianKuan(Vector3 v3)
{
    Object obj = Resources.Load("MousePoint3");
    GameObject go = Instantiate(obj, Vector2.zero, Quaternion.Euler(Vector3.zero), target.transform) as GameObject;
    go.transform.localPosition = v3;
    go.transform.localScale = new Vector3(ColliderSize / scale.x, ColliderSize / scale.y, ColliderSize);
    PointData data = new PointData();
    data.pos = new Vector2(v3.x, v3.y);
    data.sta = pointStatic.collid;
    data.col = go;
    listPoint.Add(data);
}

"MousePoint3"其实就是带碰撞盒的圈
在这里插入图片描述


三、涂抹部分

前面铺垫了那么多,终于到核心的涂抹部分了
如图:
在这里插入图片描述

3.1.虚拟点

图中密密麻麻的是我们未创建碰撞盒的虚拟点,

3.2.鼠标点

黑色圈是鼠标点击的位置

3.3.内圈

红色为内圈,是我们需要挖掘的位置,此圈内的点则:
1):如状态为dit废弃则不做处理,
2):如状态为collid(有碰撞盒),即有碰撞盒则,销毁碰撞盒并改为die(废弃)
3):如为wait(等待处理),则状态改为die(废弃)

3.4.外圈

蓝圈略大于红圈,此范围是我们挖掘边缘的位置,则红圈以外蓝圈以内的点则:
1):状态为dit废弃则不做处理,
2):状态为wait(等待处理)则创建碰撞盒,并改为collid(有碰撞盒)
3):状态为collid则不做处理

具体代码如下,大家参考一下:

public void WaDong()
{
    //创建一条射线一摄像机为原点
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    //射线碰撞到游戏地形时
    if (Physics.Raycast(ray, out hit))
    {
        //从世界坐标转为局部坐标
        Vector2 localCenter = target.transform.InverseTransformPoint(hit.point);
        for (int i = 0; i < listPoint.Count; i++)
        {
            Vector2 centerPos = listPoint[i].pos - localCenter;
            centerPos.x *= scale.x;
            centerPos.y *= scale.y;
            float dis = Vector2.Distance(centerPos, Vector2.zero);
            if (dis < Circle1Range1 && listPoint[i].sta != pointStatic.die)
            {
                listPoint[i].sta = pointStatic.die;
                if (listPoint[i].col != null)
                {
                    GameObject.Destroy(listPoint[i].col);
                }
             
            }
            else if (dis >= Circle1Range1 && dis < Circle1Range2 && listPoint[i].sta == pointStatic.wait)
            {
                listPoint[i].sta = pointStatic.collid;
                Object obj = Resources.Load("MousePoint3");
                GameObject go = Instantiate(obj, Vector2.zero, Quaternion.Euler(Vector3.zero), target.transform) as GameObject;
                go.transform.localPosition = listPoint[i].pos;
                go.transform.localScale = new Vector3(ColliderSize / scale.x, ColliderSize / scale.y, ColliderSize);
                listPoint[i].col = go;
            }
        }
    }
}


四、关于优化

关于优化可以从几个方面着手,因为碰撞盒的数量比较多,而且创建销毁比较频繁.这一部分可以考虑对象池.
另一方面是销毁的点其实不太需要再次进行计算,因为可以考虑将废弃点的点移出表外.
进一步的优化留给大家自己思考咯…


结语:

这篇文章主要和大家分享一下实现的思路,说起来也简单.一开始创建一堆虚拟点等着检查.以点击位置为圆心进行距离计算.
小圈内为涂抹掉的位置,大圈内为边缘位置判断是否增删碰撞点.
希望对大家有帮助.如果可以帮忙点个赞,谢谢.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/76028.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker中MySQL应用部署操作步骤

在linux系统下安装mysql、安装redis是非常麻烦的&#xff0c;但是docker出现后&#xff0c;应用安装会非常简洁。 1.MySQL部署 2.docker中部署mysql的步骤 创建mysql容器 这样mysql就部署好了。 外部机器连接docker中部署的mysql

Intel 12代酷睿集体大降价!三折太离谱了

之前有德国媒体报道称&#xff0c;Intel 12/13代酷睿以及即将发布的14代酷睿&#xff0c;将会全面涨价。 没想到&#xff0c;12代酷睿大降价了&#xff0c;幅度相当不可思议&#xff0c;不过至少目前仅限美国市场&#xff0c;新蛋、亚马逊、MicroCenter等大型零售商集体行动。 …

Qt扫盲-QTableView理论总结

QTableView理论总结 一、概述二、导航三、视觉外观四、坐标系统五、示例代码1. 性别代理2. 学生信息模型3. 对应视图 一、概述 QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表&#xff0c;但这个是使用Qt的model/view架构提供…

四张图片道清AI大模型的发展史(1943-2023)

四张图片道清AI大模型的发展史(1943-2023) 现在最火的莫过于GPT了&#xff0c;也就是大规模语言模型(LLM)。“LLM” 是 “Large Language Model”&#xff08;大语言模型&#xff09;的简称&#xff0c;通常用来指代具有巨大规模参数和复杂架构的自然语言处理模型&#xff0c;…

代码随想录算法训练营第58天|动态规划part15|392.判断子序列、115.不同的子序列

代码随想录算法训练营第58天&#xff5c;动态规划part15&#xff5c;392.判断子序列、115.不同的子序列 392.判断子序列 392.判断子序列 思路&#xff1a; &#xff08;这道题也可以用双指针的思路来实现&#xff0c;时间复杂度也是O(n)&#xff09; 这道题应该算是编辑距…

java.lang.NoClassDefFoundError: org/apache/tez/dag/api/TezConfiguration

错误&#xff1a; java.lang.NoClassDefFoundError: org/apache/tez/dag/api/TezConfigurationat org.apache.hadoop.hive.ql.exec.tez.TezSessionPoolSession$AbstractTriggerValidator.startTriggerValidator(TezSessionPoolSession.java:74)at org.apache.hadoop.hive.ql.e…

MySQL 约束

查看约束 select * from information_schema.table_constraints where table_name要查看的表名按约束的作用范围 列级约束&#xff1a; 将此约束声明在对应字段的后面 表级约束&#xff1a;在表中所有字段都声明完&#xff0c;在所有字段的后面声明的约束&#xff0c;可以声明…

无涯教程-Perl - s函数

描述 这不是功能。这是正则表达式替换运算符。根据PATTERN中指定的正则表达式,将数据替换为REPLACE。与m //一样,分隔符由s后的第一个字符定义。 语法 以下是此函数的简单语法- s/PATTERN/REPLACE/返回值 如果失败,此函数返回0,如果成功,则返回替换次数。 例 以下是显示…

【C++深入浅出】初识C++上篇(关键字,命名空间,输入输出,缺省参数,函数重载)

目录 一. 前言 二. 什么是C 三. C关键字初探 四. 命名空间 4.1 为什么要引入命名空间 4.2 命名空间的定义 4.3 命名空间使用 五. C的输入输出 六. 缺省参数 6.1 缺省参数的概念 6.2 缺省参数的分类 七. 函数重载 7.1 函数重载的概念 7.2 函数重载的条件 7.3 C支…

PDM/PLM系统建设

仅供学习使用&#xff0c;会随时更新 工程机械跨生命周期数据管理系统 来源&#xff1a;清华大学 浅论企业PDM/PLM系统建设成功经验 来源&#xff1a;e-works 作者&#xff1a;陈凡 https://articles.e-works.net.cn/pdm/article149572.htm 随着“中国制造2025”强基工程战略的…

读高性能MySQL(第4版)笔记02_MySQL架构(下)

1. 事务日志 1.1. 事务日志有助于提高事务的效率 1.1.1. 存储引擎只需要更改内存中的数据副本&#xff0c;而不用每次修改磁盘中的表&#xff0c;这会非常快 1.1.2. 更改的记录写入事务日志中&#xff0c;事务日志会被持久化保存在硬盘上 1.2. 事务日志采用的是追加写操作&…

AUTOSAR规范与ECU软件开发(实践篇)3.3 AUTOSAR系统解决方案介绍(下)

示例将遵循AUTOSAR方法论来进行开发&#xff0c; 所用的AUTOSAR解决方案如图3.6所示。 图3.6 AUTOSAR系统解决方案 首先&#xff0c; 使用Matlab/Simulink来实现部分软件组件级的开发&#xff0c; 主要包括LightRequestSWC和LightControlSWC&#xff0c; 并自动生成应用层软件组…

Qt扫盲- Graphics View框架理论综述

Graphics View框架理论综述 一、概述二、Graphics View 体系结构1. The Scene2. The View3. 图元 Item 三、图形视图坐标系统1. 图元Item的坐标2. Scene Scene坐标3. View 视图坐标4. 坐标映射 四、关键特性1. 缩放和旋转2. 打印3. 拖放4. 鼠标指针和 提示5. 动画6. OpenGL渲染…

Coremail AI实验室:利用高级语境和视觉智能进行钓鱼邮件检测

在这个日益数字化的时代&#xff0c;对电子邮件安全需求是至关重要的。新兴的高级威胁邮件&#xff1a;应用社工技术的钓鱼邮件&#xff0c;仿冒公检法的钓鱼邮件等等&#xff0c;都需要更高级的防御策略。 Coremail邮件安全人工智能实验室&#xff0c;整合了高级文本语境理解和…

【实际开发19】- 压测 / 调优准备

目录 1. Jmeter 2. Jmeter 环境部署 1. 配置 : 临时修改语言 ~ Options → Choose Language → Chinese 3. Jmeter 并发测试 0. 提示 : Postman 测试是“串行”的 , 无法测试并发请求 1. daiding 1. Jmeter 下载 : Apache JMeter - Download Apache JMeter 详参&#xf…

蓝帽杯2022

计算机取证 1 内存取证获取开机密码 现对一个windows计算机进行取证&#xff0c;请您对以下问题进行分析解答。 从内存镜像中获得taqi7的开机密码是多少&#xff1f;&#xff08;答案参考格式&#xff1a;abcABC123&#xff09; 首先我们直接对 1.dmp 使用 vol查看 py -2 v…

如何给a-table增加列宽拖动功能

对于table的列宽设置 相信用过的人都知道&#xff0c;想要设置得很完美&#xff0c;几乎是不现实的&#xff0c;因为总有数据或长或短&#xff0c;那我们应该如何优化它呢&#xff1f;那便是让用户自行拖动列宽&#xff0c;从而能看全table的数据&#xff0c;但是对于antd-vue …

公司电脑三维图纸加密、机械图挡加密软件

机械图纸加密软件的问世&#xff0c;让很多的网络公司都大受其带来的工作中的便利。在安装了机械图纸加密软件后&#xff0c;不仅可以很好的管理员工在工作时的上网娱乐&#xff0c;在对整个公司员工的工作效率上也有着明显的提高&#xff0c;那么对于机械图纸加密软件的具体特…

利用Lifecycle,管理一个计时器生命周期

Lifecycle是Android Jetpack中的一个组件&#xff0c;用于管理Android应用程序组件&#xff08;如Activity或Fragment&#xff09;的生命周期。它可以帮助开发者在不同的生命周期阶段执行特定的操作&#xff0c;以便更好地管理资源、处理数据和提供用户体验。 Lifecycle作用 …

Python基础知识:列表推导式详解

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 我们经常需要这样处理一个列表&#xff1a; 把一个列表里面的每个元素&#xff0c; 经过相同的处理 &#xff0c;生成另一个列表。 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方…