How do I make biomes with perlin noise

I wanna know how I can change my perlin noise values or something at certain points to make changes in the environment to make biomes, like minecraft with the planes and hills, I wanna be able to do something like that.
Here’s the code.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateInfiniteWorld : MonoBehaviour
{
public GameObject player;
public GameObject blockGameObject;

public int worldSizeX;
public int worldSizeZ;

public float offsetX;
public float offsetZ;

public float noiseHeight;

public float gridOffset;
private Vector3 startPosition;

private Hashtable blockContainer = new Hashtable();

void Start()
{

    offsetX = UnityEngine.Random.Range(1f, 2086040f);
    offsetZ = UnityEngine.Random.Range(1f, 2086040f);

    float upTime = Time.realtimeSinceStartup;

    for (int x = -worldSizeX - 15; x < worldSizeX + 15; x++)
    {
        for (int z = -worldSizeZ - 15; z < worldSizeZ + 15; z++)
        {
            Vector3 pos = new Vector3(x * 1 + startPosition.x, generateNoise(x + xPlayerLocation, z + zPlayerLocation, 8f) * noiseHeight, z * 1 + startPosition.z);

            string bName = $"Block-{((int)pos.x).ToString()},0,{((int)pos.z).ToString()}";

            GameObject block = Instantiate(blockGameObject, pos, Quaternion.identity) as GameObject;
            block.transform.SetParent(this.transform);
            block.name = bName;
            BlockData bData = new BlockData(block, upTime);
            blockContainer.Add(block, bData);
        }
    }
}

private void Update()
{
    if (Mathf.Abs(xPlayerMove) >= 1 || Mathf.Abs(zPlayerMove) >= 1)
    {
        float upTime = Time.realtimeSinceStartup;
        for (int x = -worldSizeX; x < worldSizeX * 1.733; x++)
        {
            for (int z = -worldSizeZ; z < worldSizeZ * 1.733; z++)
            {
                Vector3 pos = new Vector3(x * 1 + (xPlayerLocation - 10), generateNoise(x + xPlayerLocation, z + zPlayerLocation, 8f) * noiseHeight, z * 1 + (zPlayerLocation - 10));

                string bName = $"Block-{((int)pos.x).ToString()},0,{((int)pos.z).ToString()}";

                if (!blockContainer.ContainsKey(bName))
                {
                    GameObject block = Instantiate(blockGameObject, pos, Quaternion.identity) as GameObject;
                    block.transform.SetParent(this.transform);
                    block.name = bName;
                    BlockData bData = new BlockData(block, upTime);
                    blockContainer.Add(block, bData);
                }
                else
                    ((BlockData)blockContainer[bName]).upTime = upTime;
            }
        }
        Hashtable newBlockContainer = new Hashtable();
        foreach (BlockData bData in blockContainer.Values)
        {
            if (Math.Abs(bData.upTime - upTime) > 0.0)
                Destroy(bData.blockObj);
            else
                newBlockContainer.Add(bData.blockObj.name, bData);
        }
        blockContainer = newBlockContainer;
        startPosition = player.transform.position;
    }

}

public int xPlayerMove
{
    get
    {
        return (int)(player.transform.position.x - startPosition.x);
    }
}

public int zPlayerMove
{
    get
    {
        return (int)(player.transform.position.z - startPosition.z);
    }
}
public int xPlayerLocation
{
    get
    {
        return (int)Mathf.Floor(player.transform.position.x);
    }
}

public int zPlayerLocation
{
    get
    {
        return (int)Mathf.Floor(player.transform.position.z);
    }
}

private float generateNoise(int x, int z, float detailScale)
{
    float xNoise = (x + this.transform.position.x) / detailScale;
    float zNoise = (z + this.transform.position.y) / detailScale;

    return Mathf.PerlinNoise(xNoise + offsetX, zNoise + offsetZ);
}
}

class BlockData
{
    public GameObject blockObj;
    public float upTime;

public BlockData(GameObject blockObj, float upTime)
{
    this.blockObj = blockObj;
    this.upTime = upTime;
 }
}

You could use a large noise map to generate the location of the biomes. This could be a large scaled perlin noise, or even Voronoi noise, which is used by minecraft for regions and rivers I believe.


If you were using simple perlin noise, generate a large noise map first, and if the values are between a certain range, use a smaller perlin noise of your choise for that region. For example, where noise is of high values, you can have mountainous/snowy biomes, with much more hilly biomes, whereas areas of low noise could be desert/grass biomes, with mostly smooth and low-lying land.