Bukan Churchill
Bukan Churchill

Reputation: 1

How to find the y position on a trimesh shape

I am still new in Godot engine. I followed this tutorial https://www.youtube.com/watch?v=OUnJEaatl2Q. I tried to create trees but I can't find the y position on my terrain. This is my code.

extends Node3D

@export_category("Terrain Settings")
@export var size: int = 100;
@export var subdivide: int = 99;
@export var amplitude: int = 16;
@export var treeModel: PackedScene;
@export var treeProbabilityThreshold: float = 0.3;
@export var treeProbabilityMultiplier: float = 0.5
@export var treeTriesCount: int = 250;

@export_category("Perlin Noise Settings")
@export var heightNoise: FastNoiseLite;
@export var treeNoise: FastNoiseLite;
@onready var rng: RandomNumberGenerator = RandomNumberGenerator.new();

@onready var groundMesh: MeshInstance3D = $Ground;
@onready var groundCollision: CollisionShape3D = $CollisionShape3D;
@export var player: CharacterBody3D;
@onready var camera: Camera3D = player.get_node("Neck/Camera3D");

func _ready():
    rng.seed = randi();
    heightNoise.seed = rng.randi();
    treeNoise.seed = rng.randi();
    
    GenerateMesh();
    GenerateTrees();

func GenerateTrees():
    var s = size / 2;
    var count = round(sqrt(treeTriesCount));
    for x: int in range(count):
        for y: int in range(count):
            var probability = (treeNoise.get_noise_2d(x, y) + 0.5) * treeProbabilityMultiplier;
            
            if probability > treeProbabilityThreshold:
                var posX = rng.randi_range(-s, s);
                var posZ = rng.randi_range(-s, s);
                
                var tree = treeModel.instantiate();
                add_child(tree);
                tree.position = Vector3(posX, 50, posZ);
                PositionYAlongTerrain(tree);

func PositionYAlongTerrain(node: Node3D):
    var raycast: RayCast3D = node.get_node("GroundRaycast");
    raycast.force_raycast_update();
    print(raycast.get_collider());


func GenerateMesh():
    var planeMesh = PlaneMesh.new();
    planeMesh.size = Vector2(size, size);
    planeMesh.subdivide_depth = subdivide;
    planeMesh.subdivide_width = subdivide;
    
    var surfaceTool = SurfaceTool.new();
    surfaceTool.create_from(planeMesh, 0);
    var data = surfaceTool.commit_to_arrays();
    var vertices = data[ArrayMesh.ARRAY_VERTEX];
    
    for i in vertices.size():
        var vertex = vertices[i];
        vertices[i].y = heightNoise.get_noise_2d(vertex.x, vertex.z) * amplitude;
        data[ArrayMesh.ARRAY_VERTEX] = vertices;
    
    var arrayMesh = ArrayMesh.new();
    arrayMesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, data);
    
    surfaceTool.create_from(arrayMesh, 0);
    surfaceTool.generate_normals();
    
    groundMesh.mesh = surfaceTool.commit();
    groundCollision.shape = arrayMesh.create_trimesh_shape();

I tried raycasting to the terrain at function PositionYAlongTerrain but when I tried it didnt work. When I see it with visible collision shape enabled, the raycast just clipped through the terrain.

Upvotes: 0

Views: 91

Answers (1)

Bukan Churchill
Bukan Churchill

Reputation: 1

So I found the solution. I just moved the raycast code to _physics_process. After a quick googling I found that collision only work on the first physics frame, so it's a new knowledge to me.

Upvotes: 0

Related Questions