1. 从零搭建推箱子游戏场景第一次用Unity做2D游戏时我盯着空荡荡的场景视图发呆了半小时——直到发现Tilemap这个神器。就像拼乐高一样用Tilemap搭建推箱子游戏的地图效率直接翻倍。具体操作在Hierarchy面板右键选择2D Object → Tilemap这时候会出现一个网格画布。建议先创建两个Tilemap图层一个专门放地面Ground另一个放墙壁Wall方便后期碰撞体管理。重点来了一定要给墙壁图层添加Tilemap Collider 2D组件。我刚开始偷懒没加结果角色直接穿墙而过活脱脱成了幽灵模拟器。更专业的做法是给所有墙壁添加Composite Collider 2D这样所有相邻墙壁会自动合并成整体碰撞体性能优化立竿见影。实测在手机端运行时使用复合碰撞体的场景帧率能提升20%左右。2. 角色移动的底层逻辑处理键盘输入时新手最容易犯两个错误一是把移动代码写在Update里导致抽搐式移动二是忘记做移动预判。正确的做法是在Update里检测输入在FixedUpdate里执行移动——这是Unity物理系统的黄金法则。代码结构应该是这样的void Update() { if (Input.GetKeyDown(KeyCode.RightArrow)) pendingDirection Vector2.right; // 其他方向同理... } void FixedUpdate() { if(pendingDirection ! Vector2.zero) { TryMove(pendingDirection); pendingDirection Vector2.zero; } }移动前必须做射线检测这是我踩过最痛的坑。推荐用Physics2D.Raycast搭配LayerMask只检测墙壁和箱子所在的层级。检测距离建议设为1.1倍格子大小可以避免卡墙角的尴尬情况。进阶技巧在角色四周预先埋设四个Raycast发射点上下左右各一个这样无论哪个方向移动都能获得更精确的碰撞检测。3. 推箱子机制的精髓推箱子的本质是连锁反应检测。当角色试图推动箱子时系统需要检查三件事1角色与箱子之间是否有障碍2箱子另一侧是否有空间3多个箱子是否形成连锁推动。最优雅的实现方式是递归检测bool CanPushBox(Vector2 direction, GameObject box) { RaycastHit2D hit Physics2D.Raycast( box.transform.position, direction, 1.1f, obstacleLayerMask); return !hit; // 没有障碍物才能推动 }特别注意箱子碰撞体大小要设置为精灵尺寸的80%-90%我最初用全尺寸碰撞体导致箱子经常黏在墙上。另一个实用技巧给箱子添加轻微的材质摩擦力Physics Material 2D参数设为0.1-0.3之间这样推动时会有更真实的惯性效果。4. 游戏状态管理艺术胜利条件检测看似简单实则暗藏玄机。推荐使用事件驱动的方式管理游戏状态而不是每帧检查。具体实现分三步走创建GameManager单例管理全局状态每个终点触发器被激活时触发事件当激活终点数量等于箱子总数时触发胜利// 在箱子脚本中 void OnTriggerEnter2D(Collider2D other) { if(other.CompareTag(Target)) { GameManager.Instance.OnBoxReachedTarget(); } } // 在GameManager中 public void OnBoxReachedTarget() { currentFinished; if(currentFinished totalBoxes) { StartCoroutine(VictoryRoutine()); } }关卡切换时建议添加淡入淡出效果用Unity的UI Image配合协程就能实现。关键代码IEnumerator FadeAndLoadScene() { float duration 1f; Image fadeImage GetComponentImage(); // 淡出 for(float t0; tduration; tTime.deltaTime) { fadeImage.color new Color(0,0,0, t/duration); yield return null; } SceneManager.LoadScene(nextSceneIndex); }记得在场景之间用DontDestroyOnLoad保存玩家进度数据。我曾因为忘记这点导致玩家每次进入新关卡都要从头开始被测试玩家疯狂吐槽。
从零到一:用Unity 2D实现经典推箱子游戏的核心机制
1. 从零搭建推箱子游戏场景第一次用Unity做2D游戏时我盯着空荡荡的场景视图发呆了半小时——直到发现Tilemap这个神器。就像拼乐高一样用Tilemap搭建推箱子游戏的地图效率直接翻倍。具体操作在Hierarchy面板右键选择2D Object → Tilemap这时候会出现一个网格画布。建议先创建两个Tilemap图层一个专门放地面Ground另一个放墙壁Wall方便后期碰撞体管理。重点来了一定要给墙壁图层添加Tilemap Collider 2D组件。我刚开始偷懒没加结果角色直接穿墙而过活脱脱成了幽灵模拟器。更专业的做法是给所有墙壁添加Composite Collider 2D这样所有相邻墙壁会自动合并成整体碰撞体性能优化立竿见影。实测在手机端运行时使用复合碰撞体的场景帧率能提升20%左右。2. 角色移动的底层逻辑处理键盘输入时新手最容易犯两个错误一是把移动代码写在Update里导致抽搐式移动二是忘记做移动预判。正确的做法是在Update里检测输入在FixedUpdate里执行移动——这是Unity物理系统的黄金法则。代码结构应该是这样的void Update() { if (Input.GetKeyDown(KeyCode.RightArrow)) pendingDirection Vector2.right; // 其他方向同理... } void FixedUpdate() { if(pendingDirection ! Vector2.zero) { TryMove(pendingDirection); pendingDirection Vector2.zero; } }移动前必须做射线检测这是我踩过最痛的坑。推荐用Physics2D.Raycast搭配LayerMask只检测墙壁和箱子所在的层级。检测距离建议设为1.1倍格子大小可以避免卡墙角的尴尬情况。进阶技巧在角色四周预先埋设四个Raycast发射点上下左右各一个这样无论哪个方向移动都能获得更精确的碰撞检测。3. 推箱子机制的精髓推箱子的本质是连锁反应检测。当角色试图推动箱子时系统需要检查三件事1角色与箱子之间是否有障碍2箱子另一侧是否有空间3多个箱子是否形成连锁推动。最优雅的实现方式是递归检测bool CanPushBox(Vector2 direction, GameObject box) { RaycastHit2D hit Physics2D.Raycast( box.transform.position, direction, 1.1f, obstacleLayerMask); return !hit; // 没有障碍物才能推动 }特别注意箱子碰撞体大小要设置为精灵尺寸的80%-90%我最初用全尺寸碰撞体导致箱子经常黏在墙上。另一个实用技巧给箱子添加轻微的材质摩擦力Physics Material 2D参数设为0.1-0.3之间这样推动时会有更真实的惯性效果。4. 游戏状态管理艺术胜利条件检测看似简单实则暗藏玄机。推荐使用事件驱动的方式管理游戏状态而不是每帧检查。具体实现分三步走创建GameManager单例管理全局状态每个终点触发器被激活时触发事件当激活终点数量等于箱子总数时触发胜利// 在箱子脚本中 void OnTriggerEnter2D(Collider2D other) { if(other.CompareTag(Target)) { GameManager.Instance.OnBoxReachedTarget(); } } // 在GameManager中 public void OnBoxReachedTarget() { currentFinished; if(currentFinished totalBoxes) { StartCoroutine(VictoryRoutine()); } }关卡切换时建议添加淡入淡出效果用Unity的UI Image配合协程就能实现。关键代码IEnumerator FadeAndLoadScene() { float duration 1f; Image fadeImage GetComponentImage(); // 淡出 for(float t0; tduration; tTime.deltaTime) { fadeImage.color new Color(0,0,0, t/duration); yield return null; } SceneManager.LoadScene(nextSceneIndex); }记得在场景之间用DontDestroyOnLoad保存玩家进度数据。我曾因为忘记这点导致玩家每次进入新关卡都要从头开始被测试玩家疯狂吐槽。