Godot Version
4.2.1
Question
Is there a better way to structure my project, instead of how I’ve got currently, with all the code taking place in GameMap? Would it be better I reorganize the code such that GameMap is controlling instances of a scene with each chunk individually?
class_name GameMap
extends Node3D
var num_chunks: int = 6
var chunks: Array[MeshInstance3D]
var static_bodies: Array[StaticBody3D]
var collision_shapes: Array[CollisionShape3D]
@export var uv_translate = Vector2(0.0, 0.0)
@export var uv_scale = Vector2(1.0, 1.0)
@export var chunk_size = Vector2i(180, 540)
var md: MeshDataTool = MeshDataTool.new()
var st: SurfaceTool = SurfaceTool.new()
var plane: PlaneMesh = PlaneMesh.new()
@export var plain_noise: FastNoiseLite = FastNoiseLite.new()
@export var mountain_noise: FastNoiseLite = FastNoiseLite.new()
@export var plain_scale: float = 30
@export var mountain_scale: float = 10
@export var camera_rig: Node3D = Node3D.new()
@onready var camera = camera_rig.get_child(0).get_child(0)
const RAY_LENGTH = 1000
var unit_scene = preload("res://Scenes/unit.tscn")
func _ready() -> void:
plain_noise.seed = randi() % 9223372036854775807
mountain_noise.seed = randi() % 9223372036854775807
for i in range(0, num_chunks):
chunks.append(MeshInstance3D.new())
static_bodies.append(StaticBody3D.new())
collision_shapes.append(CollisionShape3D.new())
build_mesh(i)
add_child(chunks[i])
static_bodies[i].add_child(collision_shapes[i])
chunks[i].add_child(static_bodies[i])
chunks[i].translate(Vector3(chunk_size.x * i - (chunk_size.x / 2), 0, 0))
func _process(delta) -> void:
#for i in range(0, num_chunks):
#build_mesh(i)
map_to_camera()
#func _physics_process(delta) -> void:
#var space_state = get_world_3d().direct_space_state
#var mousepos = get_viewport().get_mouse_position()
#
#var origin = camera.project_ray_origin(mousepos)
#var end = origin + camera.project_ray_normal(mousepos) * RAY_LENGTH
#var query = PhysicsRayQueryParameters3D.create(origin, end)
#
#var result = space_state.intersect_ray(query)
#print(result)
func build_mesh(i: int) -> void:
chunks[i].mesh = ArrayMesh.new()
# create plane array mesh with specified subdivs
plane.size = chunk_size
plane.subdivide_depth = chunk_size.y
plane.subdivide_width = chunk_size.x
chunks[i].mesh.clear_surfaces()
chunks[i].mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, plane.get_mesh_arrays())
# displace vertices
md.create_from_surface(chunks[i].mesh, 0)
md.set_material(preload("res://Shaders/terrain_shader_material.tres"))
for v in md.get_vertex_count():
var cyl_coord = cylinder_uv_to_xyz(md.get_vertex_uv(v) * uv_scale * Vector2(1.0 / num_chunks, 1.0) + Vector2(i * (1.0 / num_chunks), 0.0))
var plains = plain_noise.get_noise_3dv(cyl_coord) * (plain_scale)
var mountains = mountain_noise.get_noise_3dv(cyl_coord) * (mountain_scale)
var elevation = plains + (mountains - plains) * (mountains * 0.7)
if elevation < 0.0:
elevation *= 1.5
md.set_vertex(v, md.get_vertex(v) + Vector3(0.0, elevation, 0.0))
# rebuild normals
chunks[i].mesh.clear_surfaces()
md.commit_to_surface(chunks[i].mesh)
st.create_from(chunks[i].mesh, 0)
st.generate_normals()
# commit to mesh
chunks[i].mesh = st.commit()
collision_shapes[i].shape = chunks[i].mesh.create_trimesh_shape()
func cylinder_uv_to_xyz(uv: Vector2) -> Vector3:
return Vector3(1.0, uv.y * PI * 2, 0.0).rotated(Vector3.UP, uv.x * PI * 2)
func map_to_camera() -> void:
var map_width = chunk_size.x * num_chunks
for m in chunks:
var widths_from_camera = (m.global_position.x - camera_rig.global_position.x) / map_width
if (abs(widths_from_camera) <= 0.5):
continue
if (widths_from_camera > 0):
widths_from_camera += 0.5
else:
widths_from_camera -= 0.5
var widths_to_fix: int = widths_from_camera
m.global_position.x -= widths_to_fix * map_width