A different generation of trees for Client

When 2 or more players connect to each other, the trees are generated slightly differently for each player.

I tried to add Network transform to the prefab tree, but it didn’t help and it’s still different

Host’s pov:

Client’s pov:

Thank you for all the replies

This is script that generace terrain(mesh) and trees (DataStorage is a class that stores data between scenes):

```csharp
**using UnityEngine;[/B][/SIZE][/B]
[B][SIZE=3][B]
using System.Linq;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using Unity.Netcode;

public class MeshGenerator : MonoBehaviour
{
Mesh mesh;

Vector3[] vertices;
int[] triangles;

[Header("Map settings")]
public int Size = 20;

[Space]

public float heightMultiplier = 20f;

public AnimationCurve curve; 

[Header("Noise map")]
public float scale = 0.3f;

public int octaves;
public float presistance;
public float lacunarity;

[Space]

public int seed;
public Vector2 offset;

float[,] heightMap;

[Header("Trees")]
public GameObject treePrefab;

[Space]

public int PosibleTrees;
public int trees;

float[,] treeHeightMap;



[Header("Texture")]
public Material mat;

[Space]

public Layer[] layers;

const int textureSize = 512;
const TextureFormat textureFormat = TextureFormat.RGB565;

Vector2[] uvs;

[Header("Player")]

public GameObject playerPrefab;

bool multiplayer;
bool client;

System.Random seedGen;

async void Awake()
{
    mesh = new Mesh();
    GetComponent<MeshFilter>().mesh = mesh;
    mesh.name = "Mesh";

    heightMap = GenerateNoiseMap(Size, scale, seed, octaves, presistance, lacunarity, offset);
    treeHeightMap = GenerateNoiseMap(Size, scale, seed + 3, octaves, presistance, lacunarity, offset);
    seed = DataStorage.seed;
    multiplayer = DataStorage.multiplayer;
    client = DataStorage.client;

    seedGen = new System.Random(seed);

    await Task.Delay(1000);

    CreateShape();
    UpdateMesh();

    LevelManager.instance._loaderConvas.SetActive(false);

}

void CreateShape()
{

    vertices = new Vector3[(Size + 1) * (Size + 1)];


    for (int i = 0, z = 0; z <= Size; z++)
    {
        for (int x = 0; x <= Size; x++)
        {

            float currentHeight = (float)curve.Evaluate((float)heightMap[x, z]) * (float)heightMultiplier;

            GenerateTree(currentHeight, x, z, seedGen);

            vertices[i] = new Vector3(x, currentHeight, z);
            i++;
        }
    }

    triangles = new int[Size * Size * 6];

    int vert = 0;
    int tris = 0;

    for (int z = 0; z < Size; z++)
    {
        for (int x = 0; x < Size; x++)
        {
            triangles[tris + 0] = vert + 0;
            triangles[tris + 1] = vert + Size + 1;
            triangles[tris + 2] = vert + 1;
            triangles[tris + 3] = vert + 1;
            triangles[tris + 4] = vert + Size + 1;
            triangles[tris + 5] = vert + Size + 2;

            vert++;
            tris += 6;
        }
        vert++;
    }

    GenerateUVs();

    SetShaderVariable();
}

void GenerateUVs()
{
    uvs = new Vector2[vertices.Length];
    for (int i = 0, z = 0; z <= Size; z++)
    {
        for (int x = 0; x <= Size; x++)
        {
            uvs[i] = new Vector2((float)x / Size, (float)z / Size);
            i++;
        }
    }
}

void SetShaderVariable()
{
    mat.SetFloat("minHeight", heightMultiplier * curve.Evaluate(0));
    mat.SetFloat("maxHeight", heightMultiplier * curve.Evaluate(1));

    mat.SetInt("layerCount", layers.Length);
    mat.SetColorArray("baseColours", layers.Select(x => x.tint).ToArray());
    mat.SetFloatArray("baseStartHeights", layers.Select(x => x.startHeigth).ToArray());
    mat.SetFloatArray("baseBlends", layers.Select(x => x.blendStrength).ToArray());
    mat.SetFloatArray("baseColourStrength", layers.Select(x => x.tintStrength).ToArray());
    mat.SetFloatArray("baseTextureScales", layers.Select(x => x.textureScale).ToArray());

    Texture2DArray textureArray = GenerateTextureArray(layers.Select(x => x.texture).ToArray());

    mat.SetTexture("baseTextures", textureArray);
}

void SpawnPlayer(float currentHeight, Vector3 pos)
{
    GameObject player = Instantiate(playerPrefab);

    player.transform.position = pos;
}

Texture2DArray GenerateTextureArray(Texture2D[] textures)
{
    Texture2DArray textureArray = new Texture2DArray(textureSize, textureSize, textures.Length, textureFormat, true);

    for(int i = 0; i < textures.Length; i++)
    {
        textureArray.SetPixels(textures[i].GetPixels(), i);
    }

    textureArray.Apply();

    return textureArray;
}
void UpdateMesh()
{
    mesh.Clear();

    mesh.vertices = vertices;
    mesh.triangles = triangles;
    mesh.uv = uvs;

    mesh.RecalculateNormals();

    GetComponent<MeshCollider>().sharedMesh = mesh;

    float currentHeight;
    Vector3 pos;

    while (true)
    {
        int x = seedGen.Next(0, Size);
        int z = seedGen.Next(0, Size);

        currentHeight = (float)curve.Evaluate((float)heightMap[x, z]) * (float)heightMultiplier;

        if (currentHeight > 1.8)
        {
            pos = new Vector3(x, (float)currentHeight + 2f, z);
            break;
        }
    }





    if (multiplayer && !client)
    {
        DataStorage.x = (float)pos.x;
        DataStorage.y = (float)pos.y;
        DataStorage.z = (float)pos.z;

        if (NetworkManager.Singleton.StartHost())
        {
            Debug.Log("host");
        }
        else
        {
            Debug.Log("host failed");
        }
    }
    else if (DataStorage.solo == true)
    {
        SpawnPlayer(currentHeight, pos);
        Debug.Log("player");
    }
}

float[,] GenerateNoiseMap(int size, float scale, int seed, int octaves, float presistance, float lacunarity, Vector2 offset)
{
    float[,] noiseMap = new float[size + 1, size + 1];

    System.Random prng = new System.Random(seed);
    Vector2[] octaveOffsets = new Vector2[octaves + 1];

    for (int i = 0; i <= octaves; i++)
    {
        float offsetX = prng.Next(-100000, 100000) + offset.x;
        float offsetZ = prng.Next(-100000, 100000) + offset.y;

        octaveOffsets[i] = new Vector2(offsetX, offsetZ);
    }

    if (scale <= 0)
    {
        scale = 0.0001f;
    }

    float minNoiseHeight = float.MaxValue;
    float maxNoiseHeight = float.MinValue;

    float halfSize = size / 2;

    for (int z = 0; z <= size; z++)
    {
        for (int x = 0; x <= size; x++)
        {

            float amplitude = 1;
            float frequency = 1;
            float noiseHeight = 0;

            for (int i = 0; i <= octaves; i++)
            {
                float sampleX = (x - halfSize) / scale * frequency + octaveOffsets[i].x;
                float sampleY = (z - halfSize) / scale * frequency + octaveOffsets[i].y;

                float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
                noiseHeight += perlinValue * amplitude;

                amplitude *= presistance;
                frequency *= lacunarity;
            }

            if (noiseHeight < minNoiseHeight)
            {
                minNoiseHeight = noiseHeight;
            }
            else if (noiseHeight > maxNoiseHeight)
            {
                maxNoiseHeight = noiseHeight;
            }

            noiseMap[x, z] = noiseHeight;
        }
    }

    for (int z = 0; z <= size; z++)
    {
        for (int x = 0; x <= size; x++)
        {
            noiseMap[x, z] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, z]);

            float fallOffX = z / (float)size * 2 - 1;
            float fallOffZ = x / (float)size * 2 - 1;

            float value = Mathf.Max(Mathf.Abs(fallOffX), Mathf.Abs(fallOffZ));

            noiseMap[x, z] = Mathf.Clamp01(noiseMap[x, z] - Evaluate(value));
        }
    }

    return noiseMap;
}

void GenerateTree(float currentHeight, int x, int z, System.Random prng)
{

    PosibleTrees++;

    int d = prng.Next(0, 10);
    int c = prng.Next(0, 10);

    double X = prng.NextDouble();
    double Z = prng.NextDouble();
    double Y = prng.NextDouble();

    if(Y < .5f)
    {
        Y = .5f;
    }

    if (treeHeightMap[x, z] >= Y && currentHeight > 1.5 && currentHeight < 10 && d >= 8)
    {
        GameObject tree = Instantiate(treePrefab);

        tree.transform.position = new Vector3((float)(x + X), currentHeight, (float)(z + Z));

        trees++;
    }
}

float Evaluate(float value)
{
    float a = 3;
    float b = 2.2f;

    return Mathf.Pow(value, a) / (Mathf.Pow(value, a) + Mathf.Pow(b - b * value, a));
}


[System.Serializable]
public class Layer
{
    public Texture2D texture;
    public Color tint;

    [Range(0,1)]
    public float tintStrength;

    [Range(0, 1)]
    public float startHeigth;

    [Range(0, 1)]
    public float blendStrength;

    public float textureScale;
}

/*private void OnDrawGizmos()
{
    Gizmos.color = Color.black;
    for (int i = 0; i < vertices.Length; i++)
    {
        Gizmos.DrawSphere(vertices[i], 0.1f);
    }
}*/

}
__
**__ __**This is a script that is attached to a tree to prevent trees from flying in the air (There may be a collision problem, so they will be destroyed, but but if that's the case, I don't know how to fix it.):**__ __**csharp**__
**using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting.Antlr3.Runtime.Tree;
using UnityEngine;

public class TreeMnager : MonoBehaviour
{

public GameObject groundCheck;
public GameObject iTree;


// Start is called before the first frame update
void Start()
{
    if(!Physics.CheckSphere(groundCheck.transform.position, .1f, LayerMask.GetMask("Mesh")))
    {
        Destroy(iTree);
    }

    Collider[] hitColliders = Physics.OverlapSphere(iTree.transform.position, 1);
    foreach (var hitCollider in hitColliders)
    {
        if (hitCollider.gameObject != iTree &&
            hitCollider.gameObject.CompareTag("Tree"))
        {
            Destroy(iTree);
        }
    }
}

// Update is called once per frame
void Update()
{
   
}

}
__
**__ **This script controls what type of game will be played(Multyplayer/singleplayer):** **csharp**
**using System.Threading.Tasks;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelManager : MonoBehaviour
{
public static LevelManager instance;

public GameObject _loaderConvas;
[SerializeField] private Slider _loaderSlider;
[SerializeField] private InputField input;

// Start is called before the first frame update
void Awake()
{
    if(instance == null)
    {
        instance = this;
        DontDestroyOnLoad(gameObject);
    }
    else
    {
        Destroy(gameObject);
    }
}

public async void LoadScene(string sceneName)
{
    int seed = 0;
    int.TryParse(input.text, out seed);

    if(seed == 0)
    {
        seed = Random.Range(-2147483647, 2147483647);
    }

    DataStorage.seed = seed;
    DataStorage.multiplayer = false;
    DataStorage.client = false;
    DataStorage.solo = true;

    var scene = SceneManager.LoadSceneAsync(sceneName);
    scene.allowSceneActivation = false;

   _loaderConvas.SetActive(true);

    do
    {
        await Task.Delay(500);
        _loaderSlider.value = scene.progress;
    } while (scene.progress < 0.9f);

    scene.allowSceneActivation = true;
}

public async void LoadSceneHost(string sceneName)
{
    int seed = 0;
    int.TryParse(input.text, out seed);

    if (seed == 0)
    {
        seed = Random.Range(-2147483647, 2147483647);
    }

    DataStorage.seed = seed;
    DataStorage.multiplayer = true;
    DataStorage.client = false;
    DataStorage.solo = false;

    var scene = SceneManager.LoadSceneAsync(sceneName);
    scene.allowSceneActivation = false;

    _loaderConvas.SetActive(true);

    do
    {
        await Task.Delay(500);
        _loaderSlider.value = scene.progress;
    } while (scene.progress < 0.9f);

    scene.allowSceneActivation = true;
}

public void JoinWorld()
{

    DataStorage.multiplayer = true;
    DataStorage.client = true;
    DataStorage.solo = false;

    if (NetworkManager.Singleton.StartClient())
    {
        Debug.Log("succes");
    }
    else
    {
        Debug.Log("World not found");
    }
}

}**
```

Is the seed sent to the client?

Confirm that both host and client are generating the trees using the same seed.
If they use the same seed, check for anything where they may deviate.

Theanks for reply, Yes, thats the problem but I don’t know how to share the seed

I tried this but that return 0 to client:

to LevelManager i Add this:

using System.Threading.Tasks;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelManager : [B]NetworkBehaviour[/B]
{
    public static LevelManager instance;

    public GameObject _loaderConvas;
    [SerializeField] private Slider _loaderSlider;
    [SerializeField] private InputField input;
    [SerializeField] private InputField IPinput;

    [B]public NetworkVariable<int> seedClient = new NetworkVariable<int>();[/B]

    // Start is called before the first frame update
    void Awake()
    {
        if(instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public async void LoadScene(string sceneName)
    {
        int seed = 0;
        int.TryParse(input.text, out seed);

        if(seed == 0)
        {
            seed = Random.Range(-2147483647, 2147483647);
        }

        DataStorage.seed = seed;
        DataStorage.multiplayer = false;
        DataStorage.client = false;
        DataStorage.solo = true;

        var scene = SceneManager.LoadSceneAsync(sceneName);
        scene.allowSceneActivation = false;

       _loaderConvas.SetActive(true);

        do
        {
            await Task.Delay(500);
            _loaderSlider.value = scene.progress;
        } while (scene.progress < 0.9f);

        scene.allowSceneActivation = true;
    }

    public async void LoadSceneHost(string sceneName)
    {
        int seed = 0;
        int.TryParse(input.text, out seed);

        if (seed == 0)
        {
            seed = Random.Range(-2147483647, 2147483647);
        }

        DataStorage.seed = seed;
        [B]seedClient.Value = seed;[/B]
        DataStorage.multiplayer = true;
        DataStorage.client = false;
        DataStorage.solo = false;

        var scene = SceneManager.LoadSceneAsync(sceneName);
        scene.allowSceneActivation = false;

        _loaderConvas.SetActive(true);

        do
        {
            await Task.Delay(500);
            _loaderSlider.value = scene.progress;
        } while (scene.progress < 0.9f);

        scene.allowSceneActivation = true;
    }

    public void JoinWorld()
    {

        DataStorage.multiplayer = true;
        DataStorage.client = true;
        DataStorage.solo = false;
        //DataStorage.seed = 2415;

        NetworkManager.Singleton.GetComponent<UnityTransport>().ConnectionData.Address = IPinput.text;

        if (NetworkManager.Singleton.StartClient())
        {
            Debug.Log("succes");
        }
        else
        {
            Debug.Log("World not found");
        }
    }
}

and to MeshGenerator I add this:

if (client) { seed = LevelManager.instance.seedClient.Value; Debug.Log(LevelManager.instance.seedClient.Value); }

This prints 0 to the console, but when I look in the GameObject LevelManager at the seedClient value it is the correct value and not 0

When I put Debug.Log(LevelManager.instance.seedClient.Value); on end of the script it’s prints correct value.

Do you now how to fix it?

I think this is a very bad solution but I solved it by putting a delay so my scripts now look like this:

MeshGenerator:

using UnityEngine;
using System.Linq;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using Unity.Netcode;

public class MeshGenerator : NetworkBehaviour
{
    Mesh mesh;

    Vector3[] vertices;
    int[] triangles;

    [Header("Map settings")]
    public int Size = 20;

    [Space]

    public float heightMultiplier = 20f;

    public AnimationCurve curve;   

    [Header("Noise map")]
    public float scale = 0.3f;

    public int octaves;
    public float presistance;
    public float lacunarity;

    [Space]

    public int seed;
    public Vector2 offset;

    float[,] heightMap;

    [Header("Trees")]
    public GameObject treePrefab;

    [Space]

    public int PosibleTrees;
    public int trees;

    float[,] treeHeightMap;



    [Header("Texture")]
    public Material mat;

    [Space]

    public Layer[] layers;

    const int textureSize = 512;
    const TextureFormat textureFormat = TextureFormat.RGB565;

    Vector2[] uvs;

    [Header("Player")]

    public GameObject playerPrefab;

    bool multiplayer;
    bool client;

    System.Random seedGen;

    [Space]

    public bool menu;

    private NetworkVariable<int> seedClient = new NetworkVariable<int>();

    async void Awake()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;
        mesh.name = "Mesh";

        multiplayer = DataStorage.multiplayer;
        client = DataStorage.client;

        await Task.Delay(1000);

        if (!menu && !multiplayer) { seed = DataStorage.seed; }
        if (!menu && multiplayer && !client) { seed = DataStorage.seed; seedClient.Value = seed; }
        if (client) { seed = seedClient.Value; }

        heightMap = GenerateNoiseMap(Size, scale, seed, octaves, presistance, lacunarity, offset);
        treeHeightMap = GenerateNoiseMap(Size, scale, seed + 3, octaves, presistance, lacunarity, offset);



        seedGen = new System.Random(seed + 3);

       

        CreateShape();
        UpdateMesh();
       
        LevelManager.instance._loaderConvas.SetActive(false);
    }

    void CreateShape()
    {
        vertices = new Vector3[(Size + 1) * (Size + 1)];


        for (int i = 0, z = 0; z <= Size; z++)
        {
            for (int x = 0; x <= Size; x++)
            {

                float currentHeight = (float)curve.Evaluate((float)heightMap[x, z]) * (float)heightMultiplier;

                GenerateTree(currentHeight, x, z, seedGen);

                vertices[i] = new Vector3(x, currentHeight, z);
                i++;
            }
        }

        triangles = new int[Size * Size * 6];

        int vert = 0;
        int tris = 0;

        for (int z = 0; z < Size; z++)
        {
            for (int x = 0; x < Size; x++)
            {
                triangles[tris + 0] = vert + 0;
                triangles[tris + 1] = vert + Size + 1;
                triangles[tris + 2] = vert + 1;
                triangles[tris + 3] = vert + 1;
                triangles[tris + 4] = vert + Size + 1;
                triangles[tris + 5] = vert + Size + 2;

                vert++;
                tris += 6;
            }
            vert++;
        }

        GenerateUVs();

        SetShaderVariable();
    }

    void GenerateUVs()
    {
        uvs = new Vector2[vertices.Length];
        for (int i = 0, z = 0; z <= Size; z++)
        {
            for (int x = 0; x <= Size; x++)
            {
                uvs[i] = new Vector2((float)x / Size, (float)z / Size);
                i++;
            }
        }
    }

    void SetShaderVariable()
    {
        mat.SetFloat("minHeight", heightMultiplier * curve.Evaluate(0));
        mat.SetFloat("maxHeight", heightMultiplier * curve.Evaluate(1));

        mat.SetInt("layerCount", layers.Length);
        mat.SetColorArray("baseColours", layers.Select(x => x.tint).ToArray());
        mat.SetFloatArray("baseStartHeights", layers.Select(x => x.startHeigth).ToArray());
        mat.SetFloatArray("baseBlends", layers.Select(x => x.blendStrength).ToArray());
        mat.SetFloatArray("baseColourStrength", layers.Select(x => x.tintStrength).ToArray());
        mat.SetFloatArray("baseTextureScales", layers.Select(x => x.textureScale).ToArray());

        Texture2DArray textureArray = GenerateTextureArray(layers.Select(x => x.texture).ToArray());

        mat.SetTexture("baseTextures", textureArray);
    }

    void SpawnPlayer(float currentHeight, Vector3 pos)
    {
        GameObject player = Instantiate(playerPrefab);

        player.transform.position = pos;
    }

    Texture2DArray GenerateTextureArray(Texture2D[] textures)
    {
        Texture2DArray textureArray = new Texture2DArray(textureSize, textureSize, textures.Length, textureFormat, true);

        for(int i = 0; i < textures.Length; i++)
        {
            textureArray.SetPixels(textures[i].GetPixels(), i);
        }

        textureArray.Apply();

        return textureArray;
    }
    void UpdateMesh()
    {
        mesh.Clear();

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uvs;

        mesh.RecalculateNormals();

        GetComponent<MeshCollider>().sharedMesh = mesh;

        float currentHeight;
        Vector3 pos;

        while (true)
        {
            int x = seedGen.Next(0, Size);
            int z = seedGen.Next(0, Size);

            currentHeight = (float)curve.Evaluate((float)heightMap[x, z]) * (float)heightMultiplier;

            if (currentHeight > 1.8)
            {
                pos = new Vector3(x, (float)currentHeight + 4f, z);

                break;
            }
        }



       

        if (multiplayer && !client)
        {
            Debug.Log("this is host");

            DataStorage.x = (float)pos.x;
            DataStorage.y = (float)pos.y;
            DataStorage.z = (float)pos.z;

            if (NetworkManager.Singleton.StartHost())
            {
                Debug.Log("host");
            }
            else
            {
                Debug.Log("host failed");
            }
        }
        else if (DataStorage.solo == true)
        {
            SpawnPlayer(currentHeight, pos);
            Debug.Log("player");
        }
    }

    float[,] GenerateNoiseMap(int size, float scale, int seed, int octaves, float presistance, float lacunarity, Vector2 offset)
    {
        float[,] noiseMap = new float[size + 1, size + 1];

        System.Random prng = new System.Random(seed);
        Vector2[] octaveOffsets = new Vector2[octaves + 1];

        for (int i = 0; i <= octaves; i++)
        {
            float offsetX = prng.Next(-100000, 100000) + offset.x;
            float offsetZ = prng.Next(-100000, 100000) + offset.y;

            octaveOffsets[i] = new Vector2(offsetX, offsetZ);
        }

        if (scale <= 0)
        {
            scale = 0.0001f;
        }

        float minNoiseHeight = float.MaxValue;
        float maxNoiseHeight = float.MinValue;

        float halfSize = size / 2;

        for (int z = 0; z <= size; z++)
        {
            for (int x = 0; x <= size; x++)
            {

                float amplitude = 1;
                float frequency = 1;
                float noiseHeight = 0;

                for (int i = 0; i <= octaves; i++)
                {
                    float sampleX = (x - halfSize) / scale * frequency + octaveOffsets[i].x;
                    float sampleY = (z - halfSize) / scale * frequency + octaveOffsets[i].y;

                    float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
                    noiseHeight += perlinValue * amplitude;

                    amplitude *= presistance;
                    frequency *= lacunarity;
                }

                if (noiseHeight < minNoiseHeight)
                {
                    minNoiseHeight = noiseHeight;
                }
                else if (noiseHeight > maxNoiseHeight)
                {
                    maxNoiseHeight = noiseHeight;
                }

                noiseMap[x, z] = noiseHeight;
            }
        }

        for (int z = 0; z <= size; z++)
        {
            for (int x = 0; x <= size; x++)
            {
                noiseMap[x, z] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, z]);

                float fallOffX = z / (float)size * 2 - 1;
                float fallOffZ = x / (float)size * 2 - 1;

                float value = Mathf.Max(Mathf.Abs(fallOffX), Mathf.Abs(fallOffZ));

                noiseMap[x, z] = Mathf.Clamp01(noiseMap[x, z] - Evaluate(value));
            }
        }

        return noiseMap;
    }

    void GenerateTree(float currentHeight, int x, int z, System.Random prng)
    {

        PosibleTrees++;

        int d = prng.Next(0, 10);
        int c = prng.Next(0, 10);

        double X = prng.NextDouble();
        double Z = prng.NextDouble();
        double Y = prng.NextDouble();

        if(Y < .5f)
        {
            Y = .5f;
        }

        if (treeHeightMap[x, z] >= Y && currentHeight > 1.5 && currentHeight < 10 && d >= 8)
        {
            GameObject tree = Instantiate(treePrefab);

            tree.transform.position = new Vector3((float)(x + X), currentHeight, (float)(z + Z));

            trees++;
        }
    }

    float Evaluate(float value)
    {
        float a = 3;
        float b = 2.2f;

        return Mathf.Pow(value, a) / (Mathf.Pow(value, a) + Mathf.Pow(b - b * value, a));
    }


    [System.Serializable]
    public class Layer
    {
        public Texture2D texture;
        public Color tint;

        [Range(0,1)]
        public float tintStrength;

        [Range(0, 1)]
        public float startHeigth;

        [Range(0, 1)]
        public float blendStrength;

        public float textureScale;
    }

    /*private void OnDrawGizmos()
    {
        Gizmos.color = Color.black;
        for (int i = 0; i < vertices.Length; i++)
        {
            Gizmos.DrawSphere(vertices[i], 0.1f);
        }
    }*/
}

LevelManager:

using System.Threading.Tasks;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelManager : MonoBehaviour
{
    public static LevelManager instance;

    public GameObject _loaderConvas;
    [SerializeField] private Slider _loaderSlider;
    [SerializeField] private InputField input;
    [SerializeField] private InputField IPinput;

    //public NetworkVariable<int> seedClient = new NetworkVariable<int>();

    // Start is called before the first frame update
    void Awake()
    {
        if(instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public async void LoadScene(string sceneName)
    {
        int seed = 0;
        int.TryParse(input.text, out seed);

        if(seed == 0)
        {
            seed = Random.Range(-2147483647, 2147483647);
        }

        DataStorage.seed = seed;
        DataStorage.multiplayer = false;
        DataStorage.client = false;
        DataStorage.solo = true;

        var scene = SceneManager.LoadSceneAsync(sceneName);
        scene.allowSceneActivation = false;

       _loaderConvas.SetActive(true);

        do
        {
            await Task.Delay(500);
            _loaderSlider.value = scene.progress;
        } while (scene.progress < 0.9f);

        scene.allowSceneActivation = true;
    }

    public async void LoadSceneHost(string sceneName)
    {
        int seed = 0;
        int.TryParse(input.text, out seed);

        if (seed == 0)
        {
            seed = Random.Range(-2147483647, 2147483647);
        }

        DataStorage.seed = seed;
       // seedClient.Value = seed;
        DataStorage.multiplayer = true;
        DataStorage.client = false;
        DataStorage.solo = false;

        var scene = SceneManager.LoadSceneAsync(sceneName);
        scene.allowSceneActivation = false;

        _loaderConvas.SetActive(true);

        do
        {
            await Task.Delay(500);
            _loaderSlider.value = scene.progress;
        } while (scene.progress < 0.9f);

        scene.allowSceneActivation = true;
    }

    public void JoinWorld()
    {

        DataStorage.multiplayer = true;
        DataStorage.client = true;
        DataStorage.solo = false;
        //DataStorage.seed = 2415;

        NetworkManager.Singleton.GetComponent<UnityTransport>().ConnectionData.Address = IPinput.text;

        if (NetworkManager.Singleton.StartClient())
        {
            Debug.Log("succes");
        }
        else
        {
            Debug.Log("World not found");
        }
    }
}

Take a look at OnValueChanged, you can use that as a callback for when the seed value changes. You’ll likely also want to use OnNetworkSpawn as well in case the seed value was set before the client joined.

Send an RPC with the seed (uint?) as parameter. :wink:

If you have late joining clients you may want to use the network variable since those get synchronized to late joining clients. Otherwise an RPC is the easier and more efficient solution.

I made this, but now client didn’t connect to host. It’s print succes, but client get stuck in MainMenu scene and don’t connect to host.

async void Awake()
{
    mesh = new Mesh();
    GetComponent<MeshFilter>().mesh = mesh;
    mesh.name = "Mesh";


    if (!menu && !IsHost && !IsClient) { seed = DataStorage.seed; }
    if (!menu && IsHost && !IsClient) { seed = DataStorage.seed; }
    if (IsClient) { GetSeedRpc(); Debug.Log("Seed: " + seed); }

    heightMap = GenerateNoiseMap(Size, scale, seed, octaves, presistance, lacunarity, offset);
    treeHeightMap = GenerateNoiseMap(Size, scale, seed + 3, octaves, presistance, lacunarity, offset);



    seedGen = new System.Random(seed + 3);

  

    CreateShape();
    UpdateMesh();

    await Task.Delay(500);

    if (!menu)
    {
        LevelManager.instance._loaderConvas.SetActive(false);
    }
    else
    {
        GameObject.FindGameObjectWithTag("LoadingPlaneMenu").SetActive(false);
    }
}

[Rpc(SendTo.Server)]
public void GetSeedRpc()
{
    SendSeedRpc(seed);
}

[Rpc(SendTo.NotServer)]
void SendSeedRpc(int _seed)
{
    seed = _seed;
}

If all of your Netcode code looks like this it‘ll be super hard to spot any issues or follow the flow of logic mentally! Especially with all the negation on top, and the needless double-checks.

Try spelling that out loud:
If not in the menu and not being the host and not being a client then set the seed. (huh? why?)
If not in the menu and being the host and not being a client then set the seed. (just like above, but: the host is also a client!)

Also: no Netcode in Awake! Awake runs before the object has spawned and thus its IsXxxx checks will likely all be false. Except maybe for the host.

Is start function ok?

No because the order of execution of Awake, Start and OnNetworkSpawn depends on whether it‘s an in-scene or spawned object, and a few other cases change that behaviour too. Any Netcode mehods and properties should only be used in or after OnNetworkSpawn ran.