I think I can help you a bit.
To make the scanning more efficient you have some options:
Reduce the number of frames with scan
You need to check every time when at least one of your criteria changes:
- object with property gets added
- object with property gets removed
- object gets property added
- object gets property removed
- object with property enters scan distance
- object with property leaves scan distance
I guess you know when objects are added (1.) or removed (2.). This should not happen that often. After that you need a new scan.
I think 3. and 4. can be excluded as long as you do not manipulate the properties via Python. But you should know when that happens. So you need to scan after that.
From the information you provided I can't exclude any object to run into 6. and 7. any time. You might isolate objects that are not moving (as they do not change distance) as long as the player is not moving. A moving player needs a scan after each single step.
Reduce the number of scanned objects
Unless you can make some assumptions, there is nothing to isolate candidates.
This depends on your specific situation (e.g what objects can move what objects can't move).
In your example you can create a list of candidates via property containment (as in your code).
I assume you have much less objects with the property then without.
When you cache the candidates:
candidates = [object for object in scene.objects if "property_name" in object]
owner["candidates"] = candidates
You can iterate over the them at a later time:
candidates = owner["candidates"]
# do distance check with candidates
You update the list when on the events from above (1. - 4.).
When you use both methods (reducing scans + reducing number of candidates) you should reduce the processing time quite a lot.
Lets do some estimates:
-> you are where you are now, scan all objects at each single frame
-> nothing to do
-> a little overhead to check there is nothing to do
This is hard to determine as it depends on your situation. So this is just a wild guess:
- 100 of 5000 objects have the property
- 10 of the candidates are constantly moving
- the player moves frequently (~50% of the time)
- candidates are added/removed every 10 seconds
You update the candidates every 10 seconds (iteration over 5000).
You scan 100 candidates all the time (iteration over 100).
You can get more efficiency
- when no candidate is moving (as you need to check only when the player moves).
- when you can isolate candidates even further (e.g. exclude a complete group of candidates).
I know this is still a bit vague, but it should provide you an idea.