简体   繁体   English

Unity 3D:如何进行地形流?

[英]Unity 3D: How to do terrain streaming?

I want to make a terrain mechanism that will work according to my character's position.我想制作一个可以根据我角色的位置工作的地形机制。 I am only working on the y-axis.我只在 y 轴上工作。 And the fundamental composition of my game is, that my character(a sphere) goes up in the y-axis on tapping, and as I am on the y-axis as soon as I stop tapping no force is applied in an upward direction and gravity kicks in so the sphere starts falling.我的游戏的基本组成是,我的角色(一个球体)在敲击时在 y 轴上上升,当我停止敲击时,我在 y 轴上,没有向上施加力,并且重力开始,球体开始下落。

What I basically want to do is, I have made Crossy road type roads and the sphere will go up and there are cars incoming from the left and right direction on these roads(terrains) and I want that as soon as my player goes up and gets to a specific position, say (0,10) I want the terrain mechanism to kick in and lock the gap from the first and last terrain, like at (0,10) position of sphere, there are 10 terrains below it and 10 above it.我基本上想要做的是,我已经制作了 Crossy 道路类型的道路,球体会向上移动,并且这些道路(地形)上有来自左右方向的汽车,我希望只要我的玩家上升并且到达特定位置,例如 (0,10) 我希望地形机制启动并锁定与第一个和最后一个地形的间隙,例如在球体的 (0,10) 位置,其下方有 10 个地形,而其下方有 10 个地形它上面。 And from now on I want it to go up in chunks, like say if the player moved to (0,12) then the terrain at (0,1) gets destroyed and new one spawn at (0,2), and the same happen at the top.从现在开始,我希望它分块上升,比如如果玩家移动到 (0,12),那么 (0,1) 处的地形被破坏,新的地形在 (0,2) 处产生,同样发生在顶部。 Kind of like min and max, like if position is (0,15) min = (0,5) and max = (0,25).有点像 min 和 max,比如 position 是 (0,15) min = (0,5) 和 max = (0,25)。 All my terrains are prefabs.我所有的地形都是预制件。

I am kinda bad at explaining so I explained in the word file below.我有点不擅长解释,所以我在下面的单词文件中进行了解释。 Please check Please answer, I would really appreciate it.请检查请回答,我将不胜感激。

[Detailed] https://drive.google.com/file/d/1iDmaq-8hGVPNldbpM81axYaJ1PXVcDoo/view?usp=drivesdk [详细] https://drive.google.com/file/d/1iDmaq-8hGVPNldbpM81axYaJ1PXVcDoo/view?usp=drivesdk

If I understand your question correctly you are trying to find out which terrains to spawn (aka. choose from your terrain list).如果我正确理解您的问题,您将尝试找出要生成的地形(也就是从地形列表中选择)。 The math behind this is actually fairly simple:这背后的数学实际上相当简单:

public class TerrainLoader : MonoBehaviour
{
    private const float STEP_HEIGHT = 1;
    private const int NR_OF_STEPS_BELOW = 10;
    private const int NR_OF_STEPS_ABOVE = 10;

    private int currentMin;
    private int currentMax;
    
    [SerializeField] private Transform player;

    private void Awake()
    {
        if(player == null)
        {
            Debug.LogError("no player set");
            enabled = false;
            return;
        }
        Check();
    }

    private void Update()
    {
        // Can be moved to a coroutine. Checking in Update is inefficient.
        Check();
    }

    /// <summary>
    /// Checks if player reached a new step
    /// </summary>
    private void Check()
    {
        int currentStep = player.position.y / STEP_HEIGHT;
        int minStep = Mathf.Max(0, currentStep - NR_OF_STEPS_BELOW);
        int usedStepsBelow = currentStep - minStep;
        int maxStep = currentStep + NR_OF_STEPS_ABOVE + (NR_OF_STEPS_BELOW - usedStepsBelow);

        if(minStep == currentMin && maxStep == currentMax)
            return;

        LoadTerrain(minStep, maxStep);
    }

    /// <summary>
    /// Loads terrain between min and max steps.
    /// </summary>
    private void LoadTerrain(int min, int max)
    {
        for (int i = currentMin; i < min; i++)
        {
            UnloadTerrain(i);
        }

        for (int i = min; i < max; i++)
        {
            LoadTerrain(i);
        }

        for (int i = max; i < currentMax; i++)
        {
            UnloadTerrain(i);
        }

        currentMin = min;
        currentMax = max;
    }

    /// <summary>
    /// Loads a certain terrain step if it is not loaded already
    /// </summary>
    private void LoadTerrain(int index)
    {
        if(IsTerrainLoaded(index))
            return;

        // TODO: implement
    }

    /// <summary>
    /// Checks if a certain terrain step is already loaded
    /// </summary>
    private bool IsTerrainLoaded(int index)
    {
        // TODO: implement
    }

    /// <summary>
    /// Unloads a certain terrain step
    /// </summary>
    private void UnloadTerrain(int index)
    {
        // TODO: implement
    }
}

You could store your terrains in as array inside this class or make them addressable as loadable assets, depending on the complexity of your future/finished software.您可以将您的地形作为数组存储在此类中,或者将它们作为可加载资产进行寻址,具体取决于您未来/完成的软件的复杂性。

Calculating the destined y position of each terrain is simply计算每个地形的目标 y 位置很简单

terrainIndex * STEP_HEIGHT

NOTE: If you have lots of steps you will need a spawning mechanism sooner or later moving your player (and the whole world with him) back to the origin if he moves far away.注意:如果你有很多步骤,你迟早会需要一个生成机制,如果他移动很远,你的玩家(和他的整个世界)回到原点。 (You may read about float imprecision for this issue.) (您可以阅读有关此问题的浮动不精确性。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM