Game was working fine, made some changes, elsewhere, and now it hangs. Literally on stating the game I just get the Godot logo and then nothing. Basically have to force quit the game and sometimes even the editor.
I did a lot of tracing/commenting and determined that is is hanging on:
addchild(instance)
Researching and the only advice was to call deferred. I changed to:
call_deferred("add_child",instance)
But same issue. Game just hangs. It was working great all along so I have no idea why this decided to stop working or how refactoring a bunch of code elsewhere (other scripts) would somehow blow this line up. If I comment out the addchild line everything goes back to working normally. Iāve even changed almost all process, physics and ready to pass but that did not make a difference.
And this is what calls the create. If I comment out the addchild line above, this all works perfectly, and then just stopped with no changes to this code or to the structure.
func _ready() -> void:
for n in 5:
create_visitor()
pass
With additional testing Iāve now determined that if the agent is placed anywhere other than 0,0,0 it freezes. Any other transform starting point crashes it. So the add child is actually working fine. However it is still freezing⦠when the agents are created now (at 0,0,0) they start moving to their target paths and after a handful of seconds everything just freezes again.
What happens if you only create one instead of five? What happens when you remove navigation agent node? Whereās the code that sets targets? Provide more information.
Tried almost all of that already. After another lengthy comment/uncomment session tracing through the code literally line by line I found the offending line which is in a whole separate area of code that was never touched in my refactoring. It makes no sense how this line caused a freeze and even more confusing when I replace the IF conditions with a PRINT to see what the values actually are and everything looks exactly as expected. There is no reason I can think of that would cause a freeze here. (my 2D array is x/y while the 3D coordinates are x,0,z)
The offending line is:
if move_to_x != int(global_position.x) and move_to_y != int(global_position.z):
which is part of
func find_next_square():
var found_good_spot = false
while not found_good_spot:
move_to_x = rng.randi_range(-24,24)
move_to_y = rng.randi_range(-24,24)
target = Vector3(move_to_x,0,move_to_y)
if global.path_array.has(str(move_to_x) + "," + str(move_to_y)):
if move_to_x != int(global_position.x) and move_to_y != int(global_position.z):
set_target(target)
found_good_spot = true
Which is legit as only a few coordinates are valid to move to initially. It should be verifying the first two donāt match and the second two donāt match. If a match is found, then try to find new coordinates to move to. Itās worked perfectly for weeks. I guess something I did somewhere messed it up but in my decades of coding experience Iāve never been stumped this bad.
But at least the issue is found and I can work around it.
In what sense? I create an array of valid points that can be moved to as the player is placing path objects. Since most of the playing field wonāt be paths Iām creating a simple array of the valid coordinates. Easy enough to append to and remove from as paths are created or destroyed.
The other option would be a 2D array however that only works if I stick with integers. I havenāt decided yet if Iāll allow for free form placement which would make the 2D array approach unusable. Instead itās just a list. It may be slight less efficient to ā.hasā the list as it stands now but if/when I allow decimal placement I feel this approach is the best Iāve been able to come up with.
As to the and/or⦠yeah, probably will get changed to OR but with AND it causes the visitors to walk more than just essentially a straight line that could occur with OR.
How do you convert only one way? Do you not convert to strings when populating the array?
Itās a bad idea because of floating point precision and rounding errors. The āsameā number might have a slightly different value, depending on the way it was calculated, resulting in different strings. You should never do it.
Agreed if I went out to lots of digits. I donāt need super precise placement so rounding to a couple of decimal points would work fine for my application.
Correct. Everything is converted to a string and compared that way. But at no point do I convert the string back into integer (or decimal) to use anywhere. Itās literally just a āreference listā of allowable locations that I check against.
Just donāt do it. Itās a very bad idea that will bite you in the butt sooner or later. For the same reason you donāt use operator == to compare floating point numbers. Consider this:
As expected when extrapolated way out floating point gets squirrely.
First line is the result of foo
(0.0, 0.099998)
false
I do understand this āissueā and rarely work to any level of precision that would need this. Usually I end up rounding to a few decimal places.
Interesting though in my day job, my company make highly precise measuring equipment. Weāre talking the kind of equipment that measures so small it allows chip makers to use it in lining up the etchings on their chips. Currently the top of the line devices we offer are now measuring into pico meters. In that area we really do need ALL the decimal places.
Regardless though, thanks for the feedback and insights. Itās always good to review.
Itās not about decimal places or precision in absolute sense. Itās the impossibility of some decimal numbers to be represented accurately in binary notation.
Hereās another example. Note that this is not some super-precision. It happens with only one decimal place:
var foo = Vector2(0.0, 50.0) - Vector2(0.0, 49.1)
var bar = Vector2(0.0, 50.0 - 49.1)
print(foo)
print(bar)
And hereās a particularly funky one:
var foo = Vector2(0.0, 1.0) - Vector2(0.0, 0.9)
var bar = Vector2(0.0, 0.1)
print(foo)
print(bar)
print(foo == bar)
Converting numbers to strings is in general an inefficient and bug prone way to handle things. Try to come up with a solution that doesnāt do it.
It reminds me of how 0.999999999⦠is exactly equal to 1 mathematically. I know, you think ābut it never gets to oneā, but it is simple to prove mathematically. They are identical. (I know this is not the same thing, it just reminds me of it)