godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.17k stars 98 forks source link

Change behaviour of the 'scattering' property in the new TileMap Editor to directly correlate with the probability of an empty tile being placed #4591

Open snailrhymer opened 2 years ago

snailrhymer commented 2 years ago

Describe the project you are working on

Any project involving use of scattering tiles with the TileMap Editor.

Describe the problem or limitation you are having in your project

The scattering parameter in the TileMap Editor can take values from 0 to some scattering_max (currently 1000), with scattering = 0 being no scattering, i.e. a tile is always placed. As scattering increases, so does the probability of no tile being placed. This can be used to place randomly scattered tiles over an area.

I suspect that most users will want control of the proportion of filled to unfilled tiles (or equivalently, the probability of a tile being placed or not). Writing s for the value of scattering and p for the probability of a tile being placed, we currently have:

p = 1 / (1 + s)

Which feels a bit unintuitive. Here are some of the s values you need to get a given fill percentage:

Fill s
5% 19
10% 9
15% 5.66
20% 4
25% 3
30% 2.33
...
50% 1
75% 0.33

The function can also never reach 1, though given that the current min p is 1 / 1001, that's probably not too much of a concern.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I would propose having scattering as the probability of a tile not being placed. At 0 a tile is always placed and there is no scattering, while at 1 no tiles are placed. 0.5 means that 50% of tiles are filled etc.

The main purpose of this proposal isn't to discuss the range of [scattering_min, scattering_max], however. If the range is to be kept at it's current [0, 1000], I think the proposal is still worth implementing, by changing the relationship between the scattering parameter and the probability of a tile being placed to be linear.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I previously implemented it in godotengine/godot#61411; it involves tweaking a few lines in tile_map_editor.

If this enhancement will not be used often, can it be worked around with a few lines of script?

It's core to how the scattering functionality of the TileMap Editor works.

Is there a reason why this should be core and not an add-on in the asset library?

It's core to how the scattering functionality of the TileMap Editor works.

groud commented 2 years ago

As stated in the PR, I am personally not convinced about that. Scattering may require painting very few tiles, maybe one out of 100 or 1000 in some situation. This solution makes it difficult to edit small values, while the current one stays easy. It's easier to type 100 or 1000 than to type 0.01 or 0.001, and it's also easier to increase/decrease the value with integers than dealing with fractional numbers.

I understand the desire to have precises values, but I think user don't care that much. I think most people just mess around with the value until they get something that fits more or less what they want. So I would not improve the precision at the price of worsening the ease of use.

snailrhymer commented 2 years ago

The key point of the proposal is switching to a linear relationship, so it could be scaled up by a factor 1000. Then to get a 10% fill rate, you'd set s = 900, or s = 990 for a 1% fill rate. Nice integer values are not mutually exclusive with this proposal.

I plotted them in the hopes of that being persuasion via pretty picures, but I can see more where you're coming from with the higher granularity at lower fill rates now. Current: image

vs proposed

image

I'm still concerned about the lack of meaning of the current numbers and that users may avoid using a tool they don't understand, but I'm happy enough that things make sense left as is. One alternative could be allowing users to toggle between the modes as an option in the settings dropdown:

image

but I appreciate the need to keep things minimal/maintainable.

snailrhymer commented 2 years ago

I've had another play with scattering with (hopefully) a better understanding of the intended behaviour, and I'm back to thinking that 1/(1+s) isn't the best option.

Having the scattering value just be the percentage of tiles not placed would tick a lot of boxes:

Criterion Current method Probability [0,1] Probability scaled [0-100] (%) Probability scaled [0,1000]
1 Easy to type numbers
2 Obvious parameter interpretation
3 Easy to set specific probability
4 Standard representation of probability in code
5 High granularity at low probabilities

I think 2 is important to reduce friction for new users, while without 3, the tool feels very uncomfortable for me to use. 4 probably isn't very important, given that most users will rarely, if ever, interact with editor tools via code.

As for 5: As I see it, this is the strength of the 1/(s + 1) system over any of my linear ones, by giving finer control for probabilities nearer to 0. For example, it dedicates scattering values 99-1000 (90% of its range) to probabilities <= 0.01. With probabilities this low, manipulating the scattering value by a handful of units won't have much appreciable difference when judging things by eye unless covering very large spaces, which is the user behaviour this approach is designed to improve. I don't think this criterion is worth weighting very strongly.