【问题标题】:Infinitely moving tunnels are not aligning correctly无限移动的隧道未正确对齐
【发布时间】:2018-06-29 08:30:57
【问题描述】:

如果你能想象一个玩家永远穿越隧道的游戏。为此,我的相机是静止的,隧道向后移动以产生运动的错觉。

屏幕上总是有 3 个迷你隧道同时粘在一起,当一个移动到玩家视野之外时,会在前面生成一个新的隧道,给人一种无限的错觉。

这一切正常,除非一条隧道被删除。之后的隧道似乎停止移动一帧,导致前面的隧道在其中移动并重叠,我不知道为什么。

每条隧道的长度正好是 116.25,默认情况下第一条隧道在屏幕上。

//An array to store the pre made tunnels for easy difficulty
public GameObject[] easyTunnels;

//List of tunnels that are currently on screen
public List<GameObject> tunnels = new List<GameObject>();

float speed = 0.5f;
int level = 0;

//A list of all of the tunnels for every difficulty(only easy atm)
List<GameObject[]> levelsArray = new List<GameObject[]>();

void Start () 
{
    levelsArray.Add(easyTunnels);

    //Spawn 2 tunnels for a total of 3 in a row. Starting tunnel already exists
    for (int i = 1; i < 3; i++)
    {
        int randomTunnel = Random.Range(0, easyTunnels.Length);
        Vector3 startingPos = new Vector3(0, 0, 116.25f * i);
        GameObject tunnel = Instantiate(easyTunnels[randomTunnel]);
        tunnel.transform.position = startingPos;
        tunnels.Add(tunnel);
    }
}

void Update () 
{
    //For each tunnel on the map
    for (int i = 0; i < tunnels.Count; i++)
    {
        //As its moving on the z axis, get that value
        Transform tunnelPos = tunnels[i].transform;
        float zPos = tunnelPos.position.z;

        //Each tunnel is exactly 116.25 in length
        //If it reaches this, it means its off screen as the tunnel starts at 0
        if (zPos < -116.25f)
        {
            //Get the spawn point of the new tunnel. The existing position + the length of 3 tunnels
            float newZPos = zPos + 348.75f;

            //Destroy this one as we dont need it anymore
            Destroy(tunnels[i]);
            tunnels.RemoveAt(i);

            //And spawn the new one
            int randomTunnel = Random.Range(0, easyTunnels.Length);
            Vector3 startingPos = new Vector3(0, 0, newZPos);
            GameObject tunnel = Instantiate(levelsArray[level][randomTunnel]);
            tunnel.transform.position = startingPos;
            tunnels.Add(tunnel);

        }

        //If the tunnel exists, then move it
        if (tunnels[i] != null)
        {
            tunnelPos.position = new Vector3(tunnelPos.position.x, tunnelPos.position.y, zPos -= speed);
        }
    }
}

为什么要这样做?

【问题讨论】:

  • 当您从列表中删除隧道 ('tunnels.RemoveAt(i);') 时,您可能需要将 i 的计数器减一,因为想象如下: tunnel[0] get删除 (i =0) 您生成一个新隧道并将其添加到屏幕(将是隧道 [3])现在在下一个循环中,它将是 i=1;但它会指向隧道[2],因为你删除了一个,所以你跳过了一个。尝试一下,看看会发生什么。如需快速检查,请尝试评论 `tunnels.Add(tunnel);这是在循环内,看看你是否得到和 IndexOutOfRangeException。
  • 啊这有道理,我没有意识到列表会自动调整它的索引

标签: c# unity3d


【解决方案1】:

在遍历数组的同时从数组中删除和添加绝不是一个好主意。

我会建议另一种方法:

  1. 创建一个 TunnelManager Empty 并附加一个脚本,该脚本只是随机生成隧道预制数组的一部分。

  2. 给每个隧道预制一个脚本,该脚本 a) 将其向下移动 b) 在到达端点(即 116.25f)时删除自身。在此之前,它应该调用 TunnelManager Empty 的“Spawn new tunnel piece”方法。

这样就不需要每帧循环遍历数组并从中添加或删除。

【讨论】:

  • 谢谢,我解决了原来的问题,但这听起来更好,我会试试这个
【解决方案2】:

在单个帧中删除和实例化游戏对象可能相对昂贵,但我不能说太多关于不知道它们的几何、材料等的事情。

我可以告诉你的是,您删除和添加隧道的方式可能会导致一个隧道不会为每一帧都更新,而另一个会更新两次

您正在执行以下操作:

for index i =0, do while i < the number of tunnels
  if the tunnel is too far away
    destroy it and create a new one, add it to the end of the list of tunnels
    reposition the tunnel at index i

如果您正在处理第二条隧道,但它离得太远,它会被移除,并在列表末尾添加一条新隧道。 它已重新定位,然后我们转到列表中的下一项(即您刚刚添加并重新定位的隧道)

也许尝试用新隧道替换当前索引处的项目,这样您就不会在迭代隧道时弄乱隧道的更新顺序。确保您使用 List&lt;T&gt; 作为您的 tunnels 变量,然后试试这个:

        //do not call tunnels.RemoveAt(i); instead : 

        //And spawn the new one
        int randomTunnel = Random.Range(0, easyTunnels.Length);
        Vector3 startingPos = new Vector3(0, 0, newZPos);
        GameObject tunnel = Instantiate(levelsArray[level][randomTunnel]);
        tunnel.transform.position = startingPos;
        tunnels[i] = tunnel;

额外提示:此外,它只是为渲染的每一帧将它们移动特定的量。

由于每秒渲染的帧数是可变的,隧道部分的速度可能会随着帧率下降或跳跃。

尝试以下方法:

tunnelPos.position = new Vector3(tunnelPos.position.x, tunnelPos.position.y, zPos -= speed * Time.DeltaTime);

【讨论】:

  • 感谢您提供的所有信息,我已经采用了 TheSkimek 的方法,但我可以看到您在回答方面付出了很多努力。我将使用您的增量时间方式移动
  • @RachelDockter TheSkimek 的回答使事情更具可读性并易于理解(我赞成它,因为这是一个好主意),这很好!我为这个冗长的答案付出了努力,因为编程中的一半战斗在于理解正在发生的事情和原因;)并且洞察力是一件有价值的事情。编码愉快!
猜你喜欢
  • 2021-10-20
  • 2013-02-01
  • 2012-11-07
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多