Created
May 4, 2020 17:20
-
-
Save rburing/6ec80f44da7319ff8b9524dc486761b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# WorldChunkLoader | |
# Dynamically load and unload chunks on a 3D grid. | |
# | |
# Direct children should be scenes with Load As Placeholder checked. | |
# Direct children should be aligned on a grid. | |
# (To align in 3d scene editor: Transform -> Configure Snap -> Translate Snap.) | |
# Player should have a WorldChunkGPS component, which sends a signal to here. | |
# | |
# Algorithm: load current chunk and all neighbors around it; unload the rest. | |
extends Spatial | |
const CHUNK_SIZE = 100 | |
const CHUNK_EXTENT = CHUNK_SIZE/2 | |
var chunks = {} | |
class Chunk: | |
var name: String | |
var transform: Transform | |
var path: String | |
var loaded: bool | |
var scene = null | |
func _init(new_name, new_transform, new_path, new_loaded = false): | |
name = new_name | |
transform = new_transform | |
path = new_path | |
loaded = new_loaded | |
func _ready(): | |
SceneLoader.connect("on_scene_loaded", self, "_scene_loaded") | |
_init_chunks() | |
func _init_chunks(): | |
for placeholder in get_children(): # TODO: generalize? | |
if not placeholder is InstancePlaceholder: | |
continue | |
var child_transform = Transform() | |
var stored_values = placeholder.get_stored_values() | |
if 'transform' in stored_values: | |
child_transform = stored_values['transform'] | |
# TODO: check grid alignment here and/or in separate tool script | |
var int_pos = Vector3(floor(child_transform.origin.x/CHUNK_SIZE), floor(child_transform.origin.y/CHUNK_SIZE),floor(child_transform.origin.z/CHUNK_SIZE)) | |
chunks[int_pos] = Chunk.new(placeholder.name, child_transform, placeholder.get_instance_path()) | |
remove_child(placeholder) | |
placeholder.queue_free() | |
func _player_moved_to(int_pos): | |
if OS.is_debug_build(): print('Player moved to ', int_pos) | |
var neighbors = [] | |
for y in [0,-1,1]: # y = 0 first, probably most stuff is at the same vertical level | |
for x in [0,-1,1]: | |
for z in [0,-1,1]: | |
neighbors.push_back(int_pos + Vector3(x,y,z)) | |
for neighbor in neighbors: | |
if neighbor in chunks and not chunks[neighbor].loaded: | |
if OS.is_debug_build(): print('Start loading ', chunks[neighbor].name, ' at ', neighbor) | |
SceneLoader.load_scene(chunks[neighbor].path, { position = neighbor }) | |
for position in chunks: | |
if not position in neighbors and chunks[position].loaded: | |
if OS.is_debug_build(): print('Unloading instance ', chunks[position].scene, ' of ', chunks[position].name, ' from ', position) | |
remove_child(chunks[position].scene) | |
chunks[position].scene.queue_free() | |
chunks[position].loaded = false | |
func _scene_loaded(scene): | |
var position = scene.props.position | |
chunks[position].scene = scene.instance | |
chunks[position].scene.transform = chunks[position].transform | |
add_child(chunks[position].scene) | |
chunks[position].loaded = true | |
if OS.is_debug_build(): print('Loaded instance ', chunks[position].scene, ' of ', chunks[position].name, ' at ', position) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment