Wojtek Wencel
Wojtek Wencel

Reputation: 2127

Controlling the dynamic terrain creation in Unity

I'm creating game in which the player always moves forward along the path. Terrain is made of segments (there are always 9), and I have script which creates segment relative to another segment.

Now I want to create script which will control creating and destroying these segments. My idea is to create array with 3 rows and 3 columns and since there are always 9 segments each element of the array will contain another segment. So the script will work like this:

  1. At the start it will create nine segments and player will be at the center.

  2. Each frame it checks if player is on the other segment than the center one.

  3. If he is on the other segment it will first destroy all bottom segments, then change location of the remaining objects in the array and finally it will create new segments at the top. Now it goes to step 2.

Here is visualization of step 3: Algorithm

My problem is that I start making games in unity and I don't know how to code it properly. Do you know how to check if the player is currently on another segment? I also don't know how this entire script should look like (I have some idea, but i think somebody more experienced would do this better). I would be very grateful if someone explained to me how to code it.

Upvotes: 1

Views: 746

Answers (2)

Ogi Ivanov
Ogi Ivanov

Reputation: 31

I see it is an old thread, but I hope this technique will be useful for other people with similar problems. I found that one of the easiest and fastest ways to do this is just to move the tiles with the player, not to generate them on the fly, or to move the ones from behind to the front. Let's say we have 9 seamless terrain tiles, the center tile will be the parent for the other 8 adjacent tiles. All we need to do is to check if the player is moving inside a child terrain, if so then assign the position of the center to the position of that child terrain, all other tiles will occupy their proper new places automatically because they are child of the Center. Here is a code that illustrates this approach:

public UnityEngine.Terrain Center;
public UnityEngine.Terrain N;
public UnityEngine.Terrain S;
public UnityEngine.Terrain E;
public UnityEngine.Terrain W;
public UnityEngine.Terrain NE;
public UnityEngine.Terrain NW;
public UnityEngine.Terrain SE;
public UnityEngine.Terrain SW;

public GameObject _player;

 /// <summary>
/// 0=Center, 1=N, 2=S, 3=E, 4=W, 5=NE, 6=NW, 7=SE, 8=SW
/// </summary>
private int _ret; //the tile occupied by the player
private int tw; //terrain width

void Start()
{
    tw = (int)Center.terrainData.size.x;
}

 void Update()
{
    UpdateTileset(); //make the terrain endless
}

private void UpdateTileset()
{
    _ret = -1;
    //this first check is not really necessary:
    if (_ret == -1 && _player.transform.position.x >= Center.transform.position.x &&
        _player.transform.position.x <= Center.transform.position.x + tw &&
        _player.transform.position.z >= Center.transform.position.z &&
        _player.transform.position.z <= Center.transform.position.z + tw)
    {
        //we're inside the center
        _ret = 0;
    }
    else if (_ret == -1 && _player.transform.position.x >= N.transform.position.x &&
         _player.transform.position.x <= N.transform.position.x + tw &&
         _player.transform.position.z >= N.transform.position.z &&
         _player.transform.position.z <= N.transform.position.z + tw)
    {
        //we're inside the N
        _ret = 1;
    }
    else if (_ret == -1 && _player.transform.position.x >= S.transform.position.x &&
         _player.transform.position.x <= S.transform.position.x + tw &&
         _player.transform.position.z >= S.transform.position.z &&
         _player.transform.position.z <= S.transform.position.z + tw)
    {
        //we're inside the S
        _ret = 2;
    }
    else if (_ret == -1 && _player.transform.position.x >= E.transform.position.x &&
        _player.transform.position.x <= E.transform.position.x + tw &&
        _player.transform.position.z >= E.transform.position.z &&
        _player.transform.position.z <= E.transform.position.z + tw)
    {
        //we're inside the E
        _ret = 3;
    }
    else if (_ret == -1 && _player.transform.position.x >= W.transform.position.x &&
        _player.transform.position.x <= W.transform.position.x + tw &&
        _player.transform.position.z >= W.transform.position.z &&
        _player.transform.position.z <= W.transform.position.z + tw)
    {
        //we're inside the W
        _ret = 4;
    }
    else if (_ret == -1 && _player.transform.position.x >= NE.transform.position.x &&
        _player.transform.position.x <= NE.transform.position.x + tw &&
        _player.transform.position.z >= NE.transform.position.z &&
        _player.transform.position.z <= NE.transform.position.z + tw)
    {
        //we're inside the NE
        _ret = 5;
    }
    else if (_ret == -1 && _player.transform.position.x >= NW.transform.position.x &&
        _player.transform.position.x <= NW.transform.position.x + tw &&
        _player.transform.position.z >= NW.transform.position.z &&
        _player.transform.position.z <= NW.transform.position.z + tw)
    {
        //we're inside the NW
        _ret = 6;
    }
    else if (_ret == -1 && _player.transform.position.x >= SE.transform.position.x &&
        _player.transform.position.x <= SE.transform.position.x + tw &&
        _player.transform.position.z >= SE.transform.position.z &&
        _player.transform.position.z <= SE.transform.position.z + tw)
    {
        //we're inside the SE
        _ret = 7;
    }
    else if (_ret == -1 && _player.transform.position.x >= SW.transform.position.x &&
        _player.transform.position.x <= SW.transform.position.x + tw &&
        _player.transform.position.z >= SW.transform.position.z &&
        _player.transform.position.z <= SW.transform.position.z + tw)
    {
        //we're inside the SW
        _ret = 8;
    }

    //move the tiles:
    if (_ret != 0)
    {
        switch (_ret)
        {
            case 1: //N
                Center.transform.position = N.transform.position;
                break;
            case 2: //S
                Center.transform.position = S.transform.position;
                break;
            case 3: //E
                Center.transform.position = E.transform.position;
                break;
            case 4: //W
                Center.transform.position = W.transform.position;
                break;
            case 5: //NE
                Center.transform.position = NE.transform.position;
                break;
            case 6: //NW
                Center.transform.position = NW.transform.position;
                break;
            case 7: //SE
                Center.transform.position = SE.transform.position;
                break;
            case 8: //SW
                Center.transform.position = SW.transform.position;
                break;
        }
    }
}

This one works pretty fast and smooth, the transition between the old positions and the new positions is completely invisible, If you have some ideas on how to improve this approach, I'll be glad if you share them. I hope you'll find this useful :)

Upvotes: 1

Ulf Kristiansen
Ulf Kristiansen

Reputation: 1631

My problem is that I start making games in unity and I don't know how to code it properly

That's not a problem, that's a challenge, and a fun one indeed.

Do you know how to check if the player is currently on another segment?

I don't know Unity, but I guess a very simplified frame-update could look something like this:

private Segment lastSegment;

public void UpdateFrame()
{
    Segment currentSegment = MovePlayer();
    if (currentSegment != lastSegment)
    {
        // Handle player entering the new segment here
        lastSegment = currentSegment;
    }
}

private Segment MovePlayer()
{
    // if up-button is pressed, then move up and so on
    // Then find and return the current segment
}

but i think somebody more experienced would do this better

Yes, but if someone else does it for you, you miss out on the fun.

Game-related questions are more often answered on gamedev, so head on over there and see. Also, the words segment and chunk often means the same thing, so try using chunk in your search as well.

Happy coding!

Upvotes: 2

Related Questions