Raycasting in For Loop

Im working on a procedural world builder and trying to instantiate grass meshes over a landscape. I’ve got everything working, but now I’m trying to prohibit the placement of grass if the normal of the ground is too steep. I’m doing this by calling my “grow” method every time a new triangle is created, done via a For Loop. Inside the grow method is some script which casts a downwards ray at the coordinates of the vertex, and returns the angle of the normal that it hits. If the angle within a certain range, no grass is placed. I’ve done a bunch of tests, and i’m almost positive that the issue is that the ray does not cast properly, as passing the hit.point values through the debug log consistently returns (0,0,0) for every point with the exception of SOME very rare points which return (-.9, -.4, -.4) for some reason. I’m completely out of ideas and any help would be greatly appreciated.

just for clarification, I’ve tested my angle gathering script on another object and it works fine, the grass instantiates as intended as soon as I get rid of all this “angle” business, and I’ve also tried moving the grass instantiation directly to the For Loop instead of going through the grow method.

    void growWorld(float x, float y, float z)
    {
        //spawn Grass
        if (Random.Range(0f, 200f) >= 20f && y >= 9)
        {
            GameObject grass;
            RaycastHit growCheck;

            Physics.Raycast(new Vector3(x, y + 1f, z), Vector3.down, out growCheck, Mathf.Infinity);
          
            Vector3 growHit = -growCheck.normal;

            if (Vector3.Angle(Vector3.up, growHit) >= 150f)
            {
                grass = (GameObject)Instantiate(Resources.Load("Prefab/Vegetation/Grass", typeof(GameObject)), new Vector3(x + Random.Range(-.75f, .75f), y, z + Random.Range(-.75f, .75f)), transform.rotation);
                grass.transform.localScale = grass.transform.localScale * (1 * Random.Range(.75f, 1.75f));
                grass.transform.rotation = Quaternion.Euler(new Vector3(transform.rotation.x, Random.Range(0, 360), transform.rotation.z));
                grass.transform.SetParent(transform);
            }

        }
    }

You are not checking the (bool) result of Raycast, always assuming a hit. This leads to the following questions

  • why do you assume there is always a hit. Receiving 0,0,0 is indicative of no hit. Did you perhaps move the mesh object and did not convert local to global space?
  • is there a collider attached to the mesh?
  • why don’t you add a Debug.Log to see which collider was hit
  • mayhaps double-check the layermask? No matter how much I try, I always seem to get it wrong the first time :slight_smile:

Are you using a heightmap or a fancier type of world? If you’re using a heightmap you can find the slop from there instead. That would be much simpler and much faster.

I forgot to mention, I originally had the raycasts in an IF statement, but had no luck with that so I tried it like this. However, that was before I started checking things with Debug.Log so I went back and tried that after reading your post, and every point registered that (-.9, -.4, -.4) position that I mentioned before (as opposed to just a couple here and there), and it stated that the collider that it hits is named “Cylinder” which would be one of the logs for my trees. The thing is, there are no tree objects at that position, so I’m still stumped.

Nope. I’m generating it from perlin noise. Its based on Brackey’s youtube tutorial but I went way further with it.

Also, I’m able to get the slope just fine; I’m specifically having an issue checking the slope for each grass mesh.

That sounds like your x, y and z aren,'t correctly passed to growworld. I’m sure you’ve done that already, but it probably would help to once more loig x,y,z to make sure you are iterating the correct coods (in global).

Just tried it and (x,y,z) is being correctly passed to growWorld()

Have you tried the Debug.DrawLine to see where the Ray is cast? It’s only visibl in scene view, but it should help you getting an idea where it’s going.