JarkkoPar / Utility_AI_GDExtension

This repository contains the binaries and example project for the Utility AI GDExtension.
MIT License
75 stars 2 forks source link

Question: How is NQS Query Scores Calculated #14

Open Franz-Inc opened 9 months ago

Franz-Inc commented 9 months ago

I've been playing with the NQS nodes (and your cover-taking example where the enemies run from the player and hunker down behind cover) and I have a few questions:

  1. Just to check my understanding, Use for Filtering means that if the value falls outside of the paremters, it won't even be included in the Query Results. For example, if the value falls outside of the Min/Max of a UtilityAIDistanceToVector2SearchCriterion, it will be filtered out.
  2. What about Use for Scoring = True, but Use for Filtering = false, and it falls outside of the Min/Max? If a Activation Curve is being used, does it assume x value is 1, and picks a score accordingly?
  3. Use for Filtering vs Is_Filtered --- what does Is_filtered indicate?
  4. If you have multiple search criterion, how do the scores add up to the eventual Query Result Scores (see screenshot)? - I've set up 3 criteron similar to your example: DotProduct filter to eliminate cover where the player is behind it; Distance from Player to Cover; and Distance from AI to Cover When I run things, the Query Results are all the same and suspiciously close to the Distance from AI to Cover max score result image I'm not sure how to tweak these values as I don't really understand how the scoring works, and can't really find information about it in the documentation.

Thanks a lot!

JarkkoPar commented 9 months ago

Hi,

This is a very good set of questions and helps me plug a hole in the docs!

  1. Yes, that is correct, "Use for Filtering" uses the criterion's results to remove nodes from processing and what you described is the idea.
  2. If the Use for Scoring = true, the score is calculated and clamped to 0..1 range. If you set Use for Scoring = false, the score will always be 0. If you've set the curve and the value is less than 0, the value at x=0 should be returned. And similarly if x > 1, it should just get the value from the curve at x=1.
  3. is_filtered is the result of the latest node that was processed. I will create a subgroup "Debugging" in the inspector and move is_filtered and score properties there. Basically you can test out the search with a single node, for example, and see what the results become for the different criteria.
  4. The scores are multiplied between the criteria. Or, that is the intention, I will double-check code that I don't have any logical error there.

The logic for a criterion goes as follows:

  1. Set is_filtered to false and score to 0.0.
  2. Check if "Use for Filtering" is true. If it is, check the filtering condition and assign the result to the is_filtered property.
  3. Check if "Use for Scoring" is true. If it is, do the scoring calculation.
  4. If scoring was used and if the activation curve has been assigned, use the score as the input-value (x-axis) and get what ever is the y-value at that point on the curve as the final score.

For the custom criterion the values are what ever the custom code assigns them to, so in that criterion there are no checks in place.

JarkkoPar commented 9 months ago

I checked through the code and I did find a bug. I've attached the fixed versions of the dll-files. Could you check if with these you get the results you are expecting?

libutilityai.windows.template_release.x86_64.zip

JarkkoPar commented 9 months ago

Oh and for this build I set the score to be 1 if ”Use for Scoring” is false. It should work better like that if you need to disable scoring for in-between criteria.

Franz-Inc commented 9 months ago

I just wrote up a whole paragraph with photos about how I thought it still wasn't working, but then I realized I had one of the criterion deactivated from previous testing. Oops. But in conclusion, the fix seems to work as expected! and thanks for the thorough explanation.

If you want some more feedback on documentation, there are a few other areas where some clarification could be useful (I am merely mentioning this because I was a bit confused and did my own testing to verify): Explaining the graph a bit better, perhaps with a picture. Definitively indicate that the value that you apply to the range value will convert to a sensor value of 0-1, which is on the X part of the graph, which is used to calculate the Y value, which is the resultant score. I was 90% sure this is how it worked, but when I wasn't seeing expected results I began to doubt, so some specificity here would have been helpful.

Thanks again!