游戏开发小结——如何在Unity中创建有边界的2D地图

文章介绍了如何在Unity中创建2D游戏地图并限制玩家在边界内移动。通过使用PositionClamper类,可以实现将玩家位置限制在N乘以M的网格地图内。此外,通过坐标环绕技术,当玩家达到地图边缘时,会无缝地传送到地图的另一侧,增加了游戏的趣味性。为了模拟无缝过渡,文章还建议绘制多个精灵以覆盖边界区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

游戏开发小结——如何在Unity中创建有边界的2D地图

在Unity中创建一个2D游戏的有边界地图,并使其连接边缘。这是一种轻量级且简单的解决方案,适用于皇室战争和其他类型的游戏。

在创建地图时,我们希望将玩家限制在边界内。但是,让世界实际上在自身上包裹也很好:这可以为游戏机制提供有趣的元素,同时也给玩家一种增加自由度的印象。
在本文中,我们将向您展示如何为2D游戏实现这种行为的简单方法。
在N乘以M网格地图中限制玩家位置
在大多数情况下,2D游戏的地图被定义为完全填充的N乘以M网格。在这种情况下,将玩家的位置限制在边界内的明显解决方案是检查其相对于定义边界的位置,并相应地进行调整。
这可以通过一个简单的Monobehaviour组件实现:

class PositionClamper: MonoBehaviour {
  public int mapWidth;
  public int mapHeight;

  void LateUpdate() {
    Vector3 pos = transform.position;

    //假设地图从(0,0)开始
    pos.x = Mathf.Max(Mathf.Min(pos.x, mapWidth), 0);
    pos.y = Mathf.Max(Mathf.Min(pos.y, mapHeight), 0);

    // 设置transform position.。尽可能使用本地位置local position 
  }
}

这将确保玩家的位置被夹在地图尺寸内。
需要注意的一点是,多个游戏对象将检查这些边界,因此您应该考虑重写它们以使用外部数据源,例如Scriptable object或单例。这将更方便,而且比在每个游戏对象中直接指定字段要容错性更强。

实现环绕坐标

这也是相当简单的,我们只需要检查转换位置是否超出边界,并相应地调整它。
我们还将使用一个布尔值来检查是否想要环绕的位置。

class PositionClamper: MonoBehaviour {
  public int mapWidth;
  public int mapHeight;

  public bool isWrapping;

  void LateUpdate() {
    Vector3 pos = transform.position;


    if (bIsWrapping) {
      如果我们到达地图的x边界,请将位置回绕到0,使用地图尺寸
      if (pos.x > mapWidth) {
        pos.x -= mapWidth;
      } else if (pos.x < 0f) {
        pos.x += mapWidth;
      }
      
      //  我们对y也做同样的事情
      if (pos.y > mapHeight) {
        pos.y -= mapHeight;
      } else if (pos.y < 0f) {
        pos.y += mapHeight;
      }

    } else {
      pos.x = Mathf.Max(Mathf.Min(pos.x, mapWidth), 0);
      pos.y = Mathf.Max(Mathf.Min(pos.y, mapHeight), 0);
    }


    // 设置transform position。尽可能使用本地位置local position
    transform.position = pos;
  }
}

这样,当玩家到达地图边界时,他将实际上被传送到地图的另一端。
需要注意的是,实际上有一种更简洁的方法来编写上面的代码并避免编写if:使用模运算符!

pos.x = pos.x % mapWidth;
pos.y = pos.y % mapHeight;

绘制更多精灵以模拟无缝过渡

上述方法的主要问题是,当其他人查看时,玩家将似乎“瞬移”。
再次使用一个简单的技巧:我们只需绘制更多的spirte!
使用我们当前的玩家Gameobject作为中心,我们需要添加其他Gameobject,其中包含相同的spirte但位于不同的位置:(-mapWidth,0),(mapWidth,0),(0,-mapHeight),(0,mapHeight)。
尽管简单,但这种方法需要您在子级之间共享spirte的当前状态,并且您需要将其应用于所有具有spirte renderer的Gameobject。
尽管如此,由于您多次绘制相同的spirte,它们将被批处理,因此对性能的影响不应该太大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小云同志你好

谁能书阁下,白首太玄经

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值