我有高山、山谷和丘陵。但物体只会在山谷附近和较低的区域生成,而不是在山上:
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);
}
}
}
}
}
}
嗯
您的光线投射正在从某个
heightOfCheck
向下检查它是否击中您的地形/地面。
此外,仅限于距
rangeOfCheck
最大距离 heightOfCheck
处进行检查。
=> 对于
rangeOfCheck
,你应该确保它甚至可以到达足够远的地方以击中你的表面 -> rangeOfCheck
应该至少为 >= heightOfCheck
,具体取决于你的地形是否也可以有地面 < 0
。
例如,它只能在
ground level < heightOfCheck
的地方撞击地面,同时rangeOfCheck
足够大,可以到达地面。
因此,假设您的地形只有正地面,最大高度为
200
,我会使用稍大的东西,例如heightOfCheck = 205
,然后确保rangeOfCheck
实际上可以再次达到0
,所以我会再次添加一点缓冲区,例如rangeOfCheck = heightOfCheck + 5;
。
5
完全是任意的 - 可以是任何正值,以确保您开始足够高并且结束足够低,因此您可以使用单个变量字段并执行例如
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))
...
}