Florens Kosicek
Florens Kosicek

Reputation: 5

How do I spawn objects on higher ground?

I have mountains, valleys and hills. But objects only spawn near valleys and in lower areas, not on hills:

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

public class ResourceGenerator : MonoBehaviour
{
    [Header("Spawn settings")]
    public GameObject resourcePrefab;
    public float spawnChance;

    [Header("Raycast setup")]
    public float distanceBetweenCheck;
    public float heightOfCheck = 1000f, rangeOfCheck = 30f;
    public LayerMask layerMask;
    public Vector2 positivePosition, negativePosition;

    private void Start()
    {
        SpawnResources();
    }

    void SpawnResources()
    {
        for(float x = negativePosition.x; x < positivePosition.x; x += distanceBetweenCheck)
        {
            for(float z = negativePosition.y; z < positivePosition.y; z += distanceBetweenCheck)
            {
                RaycastHit hit;
                if(Physics.Raycast(new Vector3(x, heightOfCheck, z), Vector3.down, out hit, rangeOfCheck, layerMask))
                {
                    if(spawnChance > Random.Range(0f, 101f))
                    {
                        Instantiate(resourcePrefab, hit.point, Quaternion.Euler(new Vector3(0, Random.Range(0, 360), 0)), transform);
                    }
                }
            }
        }
    }
}

Upvotes: 0

Views: 66

Answers (1)

derHugo
derHugo

Reputation: 90813

Well

  • your raycast is checking from a certain heightOfCheck downwards whether it hits your terrain / ground.

  • Further it is limited to only check at a maximum distance of rangeOfCheck from that heightOfCheck.

=> For rangeOfCheck you should make sure it can even reach far enough down to hit your surface -> rangeOfCheck should be at least >= heightOfCheck depending whether your terrain can also have ground levels < 0.

So for instance it can only hit the ground at places where ground level < heightOfCheck and at the same time where the rangeOfCheck is big enough to reach down to the ground.

So assuming your terrain has only positive ground levels with a maximum height of 200 I would use something slightly bigger like e.g. heightOfCheck = 205 and then ensure that rangeOfCheck can actually again reach 0 so I would again add a little buffer like e.g. rangeOfCheck = heightOfCheck + 5;.

The 5 is completely arbitrary - could be any positive value that ensures you start high enough and also end low enough, so you could use a single variable field and do e.g.

const float raycastBuffer = 5f;
public float maxTerrainHeight = 1000f;

void SpawnResources()
{
    ...

    var startPoint = new Vector3(x, maxTerrainHeight + raycastBuffer, z);
    if(Physics.Raycast(startPoint, Vector3.down, out var hit, maxTerrainHeight + 2 * raycastBuffer, layerMask))
            
    ...
}

Upvotes: 0

Related Questions