Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback & Requests #3

Open
Yogoda opened this issue Sep 3, 2020 · 30 comments
Open

Feedback & Requests #3

Yogoda opened this issue Sep 3, 2020 · 30 comments

Comments

@Yogoda
Copy link
Owner

Yogoda commented Sep 3, 2020

You can use this issue to discuss the plugin.

@Yogoda Yogoda changed the title Discussion Feedback & Requests Sep 3, 2020
@Gulbasaur
Copy link

Firstly - thanks, this is exactly what I was looking for.

Secondly - would this work with a LOD? So you could have a low-poly version of a zone operating as scenery that's then swapped out on triggering the zone loading.

Thirdly - have you had any issues with saving and loading games?

@Yogoda
Copy link
Owner Author

Yogoda commented Sep 17, 2020

Thank you, I'm happy that it is useful :)

For LOD version of zones, I think it should be possible without too many modifications if there is only one LOD level.

  • In the zone_trigger.gd, add a new variable zone_path_LOD that will contain the LOD version of your zone.

  • Then, in zone_loader.gd, in _on_zone_exited, you request and attach the LOD version, and in _on_zone_entered you remove the LOD version. Basically it is the same code as the normal zones, but inverted.

I've not had any issue with saving/loading games, but I only save very few data. For example, if I kill monsters in a zone and come back later, they will be back, but this is normal for my game. If you need to keep the zone state, you need to save each zone data when they are unloaded, I don't know if that is your issue.

@rmvermeulen
Copy link
Contributor

Hi, just started playing with the template project. The character runs fast enough to launch itself out of all the zones and you can see them being unloaded and brought them back when you come down. It does exactly what I wanted to implement so far.

As to the workflow, I guess it comes down to

  • creating the real map (in full or in part)
  • setting up the zones and triggers
  • removing the map nodes

I'm thinking that maybe it would be nice for the zone to show the map-node it will load later while in the editor. In case you have to line things up again. But either way, very useful, thanks

@Yogoda
Copy link
Owner Author

Yogoda commented Sep 30, 2020

You mean have all the zones attached in the editor to see the whole world? Unfortunately doing so Godot would load all the zones at the start of the game, defeating the system purpose (only load what is needed).

@rmvermeulen
Copy link
Contributor

rmvermeulen commented Sep 30, 2020

You can use the Engine.editor_hint in tool scripts to run some code only in-game, or in-editor.

tool extends Node
func _ready():
  if Engine.editor_hint:
    # in-editor behavior
    show_always() # or use VisibilityNotifier ?
  else:
    # regular behavior
    use_triggers()

I'll cook up a prototype, if it works I'll share it in a PR

EDIT you obviously know all that. I think the misunderstanding is the loading part; Godot only saves parts of the scene that are owned by the current_scene. If you add the map-part to the editor from scripts, but leave the owner blank, it will not be saved. Then when loading the level in-game only the triggers are there, as intended.

@Yogoda
Copy link
Owner Author

Yogoda commented Sep 30, 2020

Wow, that is some seriously cool stuff, didn't know it was possible. It's a great addon to the system, I will merge it when I have time, thank you :)

@Wrzlprnft
Copy link
Contributor

Wrzlprnft commented Oct 4, 2020

How about turning off the "monitorable" property for the ZoneX Area2D's? As far as i can see, they only need to detect the player entering and exiting, but do not need to be detected, as in any overlap between each other? (haven't looked much into the 3D variant, but from what i see i assume this works much the same in that case).
I am barely starting to use this great system, but that seems like an easy performance gain for to me. I am just not sure wether this is needed when having a lot of zones, and wether i am missing something.

edit: Additional thought, would a visibilityEnabler2D also work to just disable trigger areas off screen, or that be unnecessary (too)?

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 5, 2020

Hello!

I use "zone.get_overlapping_areas()" to detect which zones are connected to each other, so "monitorable" is needed, and without "monitoring" the zone won't be able to detect the player entering it. Anyway, I don't think it is a problem performance-wise since there is only the player and the triggers on this physics layer.

I think it is possible to improve the system for 2D with VisibilityNotifier2D, I need to work on this.

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 5, 2020

Ok, I updated the 2D detection system and demo, there is actually no need to use VisibilityNotifiers or Enablers.

The 2D player now has an Area2D that covers the whole screen making zones attach as soon as they become visible.

@Wrzlprnft
Copy link
Contributor

That was quick! Thanks!
About my performance concerns:
I am not sure wether the change adresses any performance concerns i had, but from the further reading i did, having them on a seperate layer to all other collisions is apparently enough for most cases. The thought behind the VisibiltyEnabler-Idea was to disable collision checking completely if an area is too far off screen/away from the player position. looks like this isn't necessary, and without a large enough project at hand that actually struggles just optimization for optimizations sake.

about the 2D specific change:
One thing the change makes sure though, is that the view on the screen, not the player character causes the zones to load, which is a better default for the 2D example!

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 5, 2020

Yes, exactly my thoughts, also the physical engine is optimized for collision detection, so I don't think it is a big deal, unless we have hundreds of areas. In that case it is possible to have a culling process that disables the colliders according to the distance from the camera.

@Wrzlprnft
Copy link
Contributor

Wrzlprnft commented Oct 10, 2020

A 2D game, where the perspective is not straight top down, but rather a 45 degree-ish angle (or an isometric view, now that i think about it), needs some Y-Sorting so things properly occlude each other. I guess there is a clever way of using nested YSort-Nodes, or brute force reparenting the player to the zone they are currently in, so the default YSort behavior works. Could this be something added to the demo project?

Edit: I think i figured it out, i overlooked Z-Index. Basically, in the demo2d Scene, change the types of World and ZoneLoader to YSort-Nodes, and change the root node of the Zone to YSort nodes, then change either the background stuff a Z-Index lower, or the Player and Obstacles/Enemys a Z-Indexhigher.
image
Now it is only a question wether that should be added to the demo.

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 11, 2020

Hello, I mainly use Godot for 3D stuff, so I don't know the issues with 2D sorting very well, if you think your solution can help most of the 2D games that will use this system, can you submit a pull request?

Much appreciated!

@Wrzlprnft
Copy link
Contributor

If the 2D game is 100% top down view, then this will be not needed. If it isn't, and the viewing angle of the assets is more like 45 degree (e.g. Undertale), something like this will be necessary so the perspective makes sense(otherwise you will either always be in front or behind everything in every zone). I'll test around a little more to make sure I am not missing anything, and then I'll create a pull request. Glad I can contribute.

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 25, 2020

Ok, I converted the 3D demo with the new node structure, unified the scripts, and removed the basic 2D demo, the tilted demo is now the standard 2D demo.

@Wrzlprnft, can you check if everything looks fine?

@Wrzlprnft
Copy link
Contributor

Oh, i didn't think of just calling connect from the zone on the trigger... whoopsie

Yeah, looks good to me 👍

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 28, 2020

I get the following error when quitting after a 2D zone have been unloaded:

ERROR: remove_shape: Index p_index = 0 is out of bounds (shapes.size() = 0).
At: servers/physics_2d/collision_object_2d_sw.cpp:132

Any idea ?

@Wrzlprnft
Copy link
Contributor

Wrzlprnft commented Oct 28, 2020

I traced it down to a zone having a tilemap with YSort enabled after being loaded and the unloaded at the point of quitting causing that error. i haven't found out why at this point, though.

I've yet to reproduce it on my personal project under the same circumstances, i do not get the error there.

@Yogoda
Copy link
Owner Author

Yogoda commented Nov 7, 2020

Good news, I was able to fix the issue, so I submitted a new version to the Asset Library (waiting for approval) :)

The issue was when freeing a loaded zone that was not in the tree, with NPC. I changed free() to queue_free() and it seems to have fixed the issue.

Thanks for your patience!

@Gamemap
Copy link

Gamemap commented Feb 14, 2021

If someone wants to have a larger viewing distance he can increase the area ZoneTrigger with .scale.x (also .scale.y and z) in the code.

I hope it helps you.
Gamemap

@Wrzlprnft
Copy link
Contributor

Would be a system to hand off NPC's traversing between zones within the scope of this project?
I assume one would put objects that block pathfinding on the connecting points between the zones, and handle the logic of finding things seperatly from the actual pathfinding. Once an NPC decides to leave a loaded zone, it walks up to that connection area and is unloaded, while more custom logic handles the desired behaviour of it while unloaded/when to come back in.

@Yogoda
Copy link
Owner Author

Yogoda commented Feb 14, 2021

I think it is a bit too specific to be included in the system. We would add a section to the readme on how to handle this problem if you have a good solution.

But I don't know much about pathfinding, I don't use it in my game. I know you have a navigation mesh and a navigation agent, but can you split the mesh across multiple zones and have it work?

@Wrzlprnft
Copy link
Contributor

Ill dabble with it and see if i can come up with something. Might take a while, though, as i am just starting with the entire topic of pathfinding.

@Wrzlprnft
Copy link
Contributor

It's been a while. Here are my conclusions on the npc stuff so far:

Would be a system to hand off npcs traversing between zones within the scope of this project?

Basically, it would need a "level of detail" like system for moving npcs:

  • "forgettable" npcs: just populating the space. do not have persistent change of state throughout the game.
  • "named" npcs: do have some sort of persistence. need to be tracked when unloaded (whether that is location or just story progress or so)
  • "trackable" npcs: named npcs whose movement/progress throughout the world need to make sense/be "real" to not ruin the players immersion

Godot does offer addind/subtracting polygons from nav-meshes. Therefore zones could on loading and unloading add/subtract their navmesh polygon to/from a global "currently loaded" navmesh. Npcs could be reparented to the zone they are currently entering to prevent them going out with their starting zone. On loading and unlading zones could handle populating/depopulating the world areas they control, and hand over control of the remaining npc behaviours to their parent nodes/the world.

The real issue i encounter which always blows stuff out of proportion is the information npcs need to function. What if their goal got unloaded? What if they need to exit the loaded zones into a currently not loaded one?

There is a bottomless pit of system design here, because it is either super game specific or overkill for most games. It basically ranges from "well, we just want to have city guards be able to run across the whole city which consists of 2 zones" so therefore it would just need to be one navmesh for both zones to "well, we basically need a full economic simulation across all zones to have the traveling merchants be very believable in what they carry and where they go" which requires a whole separate set of logic.

I think it is a bit too specific to be included in the system. We would add a section to the readme on how to handle this problem if you have a good solution.

It appears that not the pathfinding is the problem, but rather information doesn't have the same visibility as the player, and therefore it isn't trivial to add this to a system that is based on player visibility.
I do agree: adding a section with npc considerations to the readme is the preferred solution.

... unless someone comes around the corner with a finished system. (initial ideas on basically making a second layer of zones only consisting of information for npcs and have that load/unload based on npc behaviour instead of player behavious seemed promising, but i'd need way more time to make it actually work and useable)

@blisterPrinkles
Copy link

Can we make it while working on editor viewport?

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 3, 2021

@blisterPrinkles what do you mean?

@blisterPrinkles
Copy link

@blisterPrinkles what do you mean?

I was thinking in saving power while editing a 3d open-world... however I did not realized that there is other methods to join by script chunks and I bet that your system works with that too!

@Yogoda
Copy link
Owner Author

Yogoda commented Oct 4, 2021

There is a "preview" flag that allows to show/hide zones in the editor.

@HeroRobb
Copy link

I kept having my game crash and I think I've found what's causing it. In background_loader.gd, line 237 or so there's a line that is

if resource_instance != null:

and there were some times when I freed the world to change scenes to a menu or whatever and then when I changed back to the world scene, it would crash. I changed the above line to

if is_instance_valid(resource_instance):

and it no longer crashes. Thanks.

@Yogoda
Copy link
Owner Author

Yogoda commented Jan 12, 2022

Happy you were able to fix your issue :)

Normally, if you need to go to a main menu, you should stop the loading system by calling:

BackgroundLoader.request_stop()
yield(BackgroundLoader, "loading_process_stopped")

This will properly unload all used resources (might take a few seconds).

Hope it helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants