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

游戏开发小结——如何在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,它们将被批处理,因此对性能的影响不应该太大。

猜你喜欢

转载自blog.csdn.net/qq_37270421/article/details/129806368