代码之家  ›  专栏  ›  技术社区  ›  Rachel Dockter

无限移动隧道未正确对齐

  •  0
  • Rachel Dockter  · 技术社区  · 6 年前

    如果你能想象一个游戏,玩家将永远穿越隧道。为了做到这一点,我的相机是静止的,隧道向后移动,给人一种移动的错觉。

    屏幕上总是有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);
            }
        }
    }
    

    为什么要这么做?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Timothy Groote    6 年前

    在单帧中删除和实例化游戏对象可能比较昂贵,但是我不能说太多,因为我对它们的几何结构、材质等一无所知。

    但是,我可以告诉您,您删除和添加隧道的方式可能会导致一个隧道无法为每个帧更新,而另一个隧道则会更新 两次 相反。

    您正在执行以下操作:

    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<T> 为了你的 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);
    
        2
  •  2
  •   TheSkimek    6 年前

    在一个数组中同时循环删除和添加数组从来不是一个好主意。

    我建议另一种方法:

    1. 创建一个空的隧道管理器,并在其上附加一个脚本,该脚本只生成一个随机的隧道预制数组片段。

    2. 给每个隧道预设一个脚本,a)向下移动它,b)在到达端点(116.25f)时自动删除它。在执行此操作之前,应调用隧道管理器empty的“生成新隧道段”方法。

    像这样,不需要循环遍历数组中的每一帧,也不需要从中添加或删除。