当前位置: 首页 > news >正文

【日志】unity俄罗斯方块——边界限制检测

Bug修复记录

项目场景

尝试使用Unity独自制作俄罗斯方块(也许很没有必要,网上随便一搜就有教程)

问题描述

俄罗斯方块的边缘检测出错了,对方块进行旋转后,无法到达最左侧或者最下侧的位置,以及其他问题。演示图如下所示:

 边缘检测代码如下所示:

    // 检查方块是否可以移动private bool IsCanMove(){// 检查是否超出边界for (int i = 0; i < transform.childCount - 1; i++){Vector3 pos = transform.GetChild(i).position;if (pos.y < 0 || pos.x < 0 || pos.x >= 10){return false;}}return true;}

修复方案

怀疑在旋转该物体的时候位置发生了轻微偏移,导致检测结果为超出边界,但是在视觉上看不出来。修复代码如下:

    // 检查方块是否可以移动private bool IsCanMove(){// 检查是否超出边界for (int i = 0; i < transform.childCount - 1; i++){int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);if (roundY < 0 || roundX < 0 || roundX >= 10){return false;}}return true;}

今日收获

场景摆放

关于场景摆放这真的是一个很头疼的问题,想必跟我一样的新手都会考虑如何使方块每步的移动与方块的大小一致,然后考虑各种计算方块大小、这个场景要做多大以及这个场景该怎么限制。

其实这个问题不用想那么多,把每个素材都做成1unity单位的大小就好了,场景先设置成10x15的大小,同时把左下角的位置移到(0,0)的位置,调整相机位置。这样就把一个没方向没大小没标准的问题变成了一个二维数组的问题,之后的问题就是对这个二维数组进行操作。

方块创建

方块的创建有太多种方式了,但是考虑到配置并创建每一种方块以及旋转,我选择了使用预制体,这样方便旋转,还能更直观了解这些二维数组的变化。

状态列表

这个是目前项目中最令人满意的地方,因为我只是用了一个方法就把输入系统和方块的操作联系了起来(没错,这里使用了之前提到的事件系统:Unity笔记——事件中心-CSDN博客)

// 方块的状态
public enum MoveType
{Move,Rotate,MoveDown,MoveRight,MoveLeft,Stop
}// 具体的方块控制逻辑private void Start(){EventCenter.AddListener(EventName.CONTROL_MOVE, controlMove);}private void OnDestroy(){EventCenter.RemoveListener(EventName.CONTROL_MOVE, controlMove);}// 改变移动类型private void controlMove(object[] args = null){moveType = (MoveType)args[0];}// 方块移动private void TryMove(MoveType moveType = MoveType.Move){switch (moveType){case MoveType.Move:MoveFall();break;case MoveType.Rotate:Rotate();break;case MoveType.MoveDown:MoveDown();break;case MoveType.MoveLeft:MoveLeft();break;case MoveType.MoveRight:MoveRight();break;case MoveType.Stop:Stop();break;}}
   // 输入系统if (Input.GetKeyDown(KeyCode.W)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.Rotate);}if (Input.GetKeyDown(KeyCode.S)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveDown);}if (Input.GetKeyUp(KeyCode.S)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.Move);}if (Input.GetKeyDown(KeyCode.A)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveLeft);}if (Input.GetKeyDown(KeyCode.D)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveRight);}

动态加载组件

这一块就没有太多可说的地方了,直接new一个新对象,AddComponent相关脚本或者组件。不过,在动态将所有方块预制体加入GameObject[]的时候发现其实用List存储这些预制体其实也都是一样的,感觉没有太多差别,直接GameObject[]能直接导入该文件下所有的预制体。

    private GameObject[] blocks;private List<GameObject> blocklist;private void Awake(){blockList = new List<GameObject>();generatorPoint = new GameObject();generatorPoint.transform.position = new Vector3(0, 0, 0);generatorPoint.transform.parent = transform;}private void Start(){generatorPoint.transform.position = createPos;blocks = Resources.LoadAll<GameObject>("Prefabs/Block");foreach (GameObject block in blocks){blockList.Add(block);}SpawnBoard();}// 生成方块public void SpawnBoard(){randomIndex = Random.Range(0, blockList.Count);blockList[randomIndex].AddComponent<Block>();Instantiate(blockList[randomIndex], generatorPoint.transform.position, Quaternion.identity, transform);}
http://www.dtcms.com/a/297689.html

相关文章:

  • 如何在离线电脑win11上安装VS2022
  • PI 思维升级 PI设计的典范转移:从阻抗思维到谐振控制
  • 在 Ansys CFX Pre 中配置 RGP 表的分步指南
  • C++中的反向迭代器
  • java面试题(中级题汇总)
  • k8s 中的 deployment,statefulset,daemonset 控制器的区别
  • 特征值与特征向量
  • 腾讯云CodeBuddy+微信小程序:5分钟开发番茄小闹钟
  • 电科金仓新一代数据库一体机:国产化方案替换优质选择
  • 本地内网IP映射到公网访问如何实现?内网端口映射外网工具有哪些?
  • python学习DAY22打卡
  • 深入解析Hadoop高频面试题:HDFS读/写流程的RPC调用链
  • yolov8通道级剪枝讲解(超详细思考版)
  • 解密负载均衡:如何轻松提升业务性能
  • JS事件流
  • 疯狂星期四第19天运营日记
  • 网络资源模板--基于Android Studio 实现的天气预报App
  • LeetCode 127:单词接龙
  • 三维图像识别中OpenCV、PCL和Open3D结合的主要技术概念、部分示例
  • 水库大坝安全监测的主要内容
  • MySQL 全新安装步骤(Linux版yum源安装)
  • Lua(面向对象)
  • 深度学习水论文:特征提取
  • NBIOT模块 BC28通过MQTT协议连接到EMQX
  • 如何在 Ubuntu 24.04 或 22.04 上安装和使用 GDebi
  • 智能网关:物联网时代的核心枢纽
  • ABP VNext + Razor 邮件模板:动态、多租户隔离、可版本化的邮件与通知系统
  • 智能网关芯片:物联网连接的核心引擎
  • 酷暑来袭,科技如何让城市清凉又洁净?
  • 制造业低代码平台实战评测:简道云、钉钉宜搭、华为云Astro、金蝶云·苍穹、斑斑低代码,谁更值得选?