Any efficient solution for RadiusActors ?

Discussions about Coding and Scripting
User avatar
sektor2111
Godlike
Posts: 6133
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Any efficient solution for RadiusActors ?

Post by sektor2111 »

While I was working at something in range using RadiusActors, I see this iterator making a mess with this radius...
I would like to know if you have some less expensive code (iterations in stage) for solving problem other way:
The code is:

Code: Select all

		foreach N.RadiusActors( class'NavigationPoint',N1,WorkRange,N.Location )
		{
			if ( VSize(N1.location-N.Location) > WorkRange )
			{
				log ("Discarding"@N1.Name@"captured over connect range for"@N.Name$".",'UScriptDevPath');
				continue;
			}
...
This test with the log looks logically useless but... it's not... The log shows the thing:

Code: Select all

...
TheNode: Done with PathNode51
UScriptDevPath: Discarding PathNode81 captured over connect range for PathNode52.
UScriptDevPath: Discarding PathNode91 captured over connect range for PathNode52.
...
I don't really need execution speed, I need only to save processing iterations.
Any better idea ? Purpose is to stay in said Range without to work in outside.
Buggie
Godlike
Posts: 1921
Joined: Sat Mar 21, 2020 5:32 am

Re: Any efficient solution for RadiusActors ?

Post by Buggie »

Code: Select all

(TestActor->Location - TraceLocation).SizeSquared() < Square(Radius + TestActor->CollisionRadius) ) 
So Just set CollisionRadius of N to 0 before loop. And restore back after.
Or call your loop from some actor which has CollisionRadius = 0 and pass location of desired place.
User avatar
sektor2111
Godlike
Posts: 6133
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Any efficient solution for RadiusActors ?

Post by sektor2111 »

So Radius is taken in account and that's why goes over Range. Now I understand.
Perhaps before putting on Zero radius I should save it elsewhere for recovering it after work. Hm, interesting.

EDIT:
Back and Ready ?
RadiusActors still captures points at higher range even if N.CollisionRadius is zero. As result I went for linked list (perhaps less iterations as average).
Higor was probably right saying that this iterator is a bit messed up. I cannot be 100% sure but in this case I'm not helped.

In class I have implemented a variable called "it". this increases in each iteration ("for" cycles, other radius actors where errors are accepted etc.).
As result I think I have a clue if I'm approaching a crash or it's a safe usage of the tool.

Code: Select all

UScriptDevPath: Deleting temporary markers...
UScriptDevPath: Created 1161 ReachSpecs through 199323 iterations.
UScriptDevPath: Paths build in 2.441015 seconds.
I think this is pretty normal and now I only need to polish things here and there.

And this is the same task operated in 469b

Code: Select all

UScriptDevPath: Deleting temporary markers...
UScriptDevPath: Created 1161 ReachSpecs through 199323 iterations.
UScriptDevPath: Paths build in 17.263552 seconds.
It's around 7 times slower. You can imagine that I won't get older waiting the same result like a doggy slow when I can do these 7 times faster in 436/440.

Task was about building paths in a testing map using 700 ScanRange for mapping specs, max paths list filled up to 6 - Paths[0-5]/upStreamPaths[0-5], and preventing multiple connections at overcrowded InventorySpots whithin 300 UU radius. No VisNoReach, No prunes, no other trash chain type bytes added, clean as a crystal.

Then let's see a sort of random WC example where I'm finding this thing useful:
This was initial stage - debug routes if you can:
InitialStage.PNG
And after building with more flexible settings:
AfterLoveStage.PNG
No node has been deleted, no monster has been killed, no bad "Edy-Scout" collision stuff has been encountered, no ambulance has been called during process, no helmet is even needed.

Year 2021 without Covid it would be a good year...
You do not have the required permissions to view the files attached to this post.
Buggie
Godlike
Posts: 1921
Joined: Sat Mar 21, 2020 5:32 am

Re: Any efficient solution for RadiusActors ?

Post by Buggie »

sektor2111 wrote: Fri May 07, 2021 10:17 pm UScriptDevPath: Discarding PathNode81 captured over connect range for PathNode52.
UScriptDevPath: Discarding PathNode91 captured over connect range for PathNode52.
Such message is pointless. You need display difference.

Code: Select all

local float S;
		foreach N.RadiusActors( class'NavigationPoint',N1,WorkRange,N.Location )
		{
			S = VSize(N1.location-N.Location);
			if ( S > WorkRange )
			{
				log ("Discarding"@N1.Name@"captured over connect range for"@N.Name@"(" $ (S - WorkRange) $ ")",'UScriptDevPath');
				continue;
			}
User avatar
sektor2111
Godlike
Posts: 6133
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Any efficient solution for RadiusActors ?

Post by sektor2111 »

By quickly replacing with Linked list and wrapping the trace and distance, I reduced even cycles used for some reason... maybe elsewhere it goes more evil.

Here I was interested to sort distances from 15 points in range which were delivered shuffled like a music list, big, small, medium, bigger, smaller and not in order of distance and I used a method copied from UT for sorting from closer to the far one, or from the far to the closer. I reverted cycle later. When maximum Paths list authorized by user is filled the rest of extra points are discarded remaining closer connected ones but not closer than 80 units and node having paths filled is marked - future nodes will except any marked node, it's already connected. Such 30-60-80 UU small distance ReachSpecs are mainly useless. I don't think a map will ever need paths with some 30 UU length generated by PathNodes near Inventories, unless place is really strangled.
If paths-mapper fails in doing some connections, other options are available, if it fails all over again, manual control solves issues.

To do or not to do:
#1 If a spec is modified - moved elsewhere (reachspecs can be re-used) it has to be relocated in navigation point which is Start and the other one which is End. I know how to do it manually and then it might be advisable to be done automatically. Why thinking ? Because these looks rare/seldom cases for editing AND moving a ReachSpec. Usually I went to adjust cylinder and reachflags, not connected points.
#2 Edy-Scout perhaps need a bit of love. When this boy is a big one and a good jumper, specs might go over Bot capabilities - in rare cases but it happens - and then perhaps I have to stop somewhere at Queen size forgetting Titan or using a different solution which I have to think about because my skill with UScript and 3D space is limited due to my tiny brain. Why thinking ? Because this sort of test returns even a valid jumpy route which Editor natively won't do, and this has benefits generating a less loaded network but enough jumpy featured.
User avatar
Feralidragon
Godlike
Posts: 5477
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Any efficient solution for RadiusActors ?

Post by Feralidragon »

On the radius subject, a simpler alternative would be:

Code: Select all

foreach N.RadiusActors(class'NavigationPoint', N1, WorkRange - N.CollisionRadius, N.Location)
Which is always preferable to changing the collision, since changing the collision is a much heavier operation (and messier) by comparison to a simple subtraction here.

Having that said, just like Buggie mentioned, along with logging whether or not an actor falls outside of that radius should also be the exact distance measured.
Especially because as it is you don't even know if you're picking stuff "outside" of it due to sheer floating point errors rather than the algorithm logic.

Also, do not forget that UScript is around 20 times slower than native code, so even if you iterate through less actors using your linked list, it may actually take more time to do so than letting the engine iterate through more actors internally in a foreach.

In other words, if you're thinking in "cycles", you have to consider that 1 cycle in UScript takes 20x more time than 1 cycle in C++.
Not strictly so, of course, there are plenty of other variables at play, just illustrating a point here, to show that a more naive native approach is often preferable to an optimized UScript one, which I already proved in the past through my own benchmarking.
User avatar
sektor2111
Godlike
Posts: 6133
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Any efficient solution for RadiusActors ?

Post by sektor2111 »

Feralidragon wrote: Sat May 08, 2021 12:45 pm On the radius subject, a simpler alternative would be:

Code: Select all

foreach N.RadiusActors(class'NavigationPoint', N1, WorkRange - N.CollisionRadius, N.Location)
Which is always preferable to changing the collision, since changing the collision is a much heavier operation (and messier) by comparison to a simple subtraction here.
Thanks for response. I tried already "WorkRange-(N.CollsionRadius+1)". Still going over and I don't get why. I such cases when I'm losing patience I'm switching method. Linked List it's indeed slower than iterator - perhaps I can stick with ForEach AllActors.

In the term of speed... due to simple reach checks if I'm comparing defining paths by Editor vs this builder, Editor is slower for some reasons:
- I'm using a limited range;
- I'm using also limited paths load;
- There is no Progressbar (I don't know if I can have access there) to be rendered;
- There is not much deal with pruning and creating PrevOrdered and all that spam data as the other extra bytes which Editor is doing wasting 20x+ speed for creating junks.
When 1200 Paths can be created under 3 seconds clocking even externally with my phone I think I'm in a good time. This machine also is old PIV HT CPU, and if this rig does paths in 3 seconds I cannot complain.
User avatar
Feralidragon
Godlike
Posts: 5477
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Any efficient solution for RadiusActors ?

Post by Feralidragon »

Again, for each detected case outside of that radius, log in the same line also the WorkRange and distance you got, so you can visually see by how much the difference really is, which should provide a clue to why that's happening.

It could turn out to be something really simple and obvious after you look directly at those values.

EDIT: Looking again at the code Buggie initially provided, what's being used is a TraceLocation, so it may be the case that perhaps the CollisionRadius of the actor being checked against is also taken into account, hence the results you're getting?
You may also want to log the CollisionRadius of that actor to check if the difference is equivalent to that.
Eternity
Experienced
Posts: 136
Joined: Sat Nov 30, 2019 10:56 pm

Re: Any efficient solution for RadiusActors ?

Post by Eternity »

If "RadiusActors" function considers an object's physics properties, then probably it is necessary to include both - CollisionRadius and CollisionHeight (as it is a collision cylinder) into the test calculations, for both of the actors being checked...
Buggie
Godlike
Posts: 1921
Joined: Sat Mar 21, 2020 5:32 am

Re: Any efficient solution for RadiusActors ?

Post by Buggie »

No, not necessary. because it break a lot of exists code. For use second object radius exists optional parameter in v469.
Eternity
Experienced
Posts: 136
Joined: Sat Nov 30, 2019 10:56 pm

Re: Any efficient solution for RadiusActors ?

Post by Eternity »

Feralidragon wrote: Sat May 08, 2021 2:59 pmit may be the case that perhaps the CollisionRadius of the actor being checked against is also taken into account
This seems to be correct.
With CollisionRadius of the actors being checked added into the "if" condition, this condition always returns False. Otherwise it returns True in some cases...
Spoiler
UT99_RadiusActors_Test.png
You do not have the required permissions to view the files attached to this post.
User avatar
sektor2111
Godlike
Posts: 6133
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Any efficient solution for RadiusActors ?

Post by sektor2111 »

Guys, I don't need to log distance, it's in Editor, I have the tools for figuring distances - it's over range, calculated with Both VSize and Higor's XC_EditorAdds. Yes, I had logs too, I was annoyed and I deleted them. At a moment I knew distance between two nodes and I didn't want a connection there but connection was created over my defined range reduced - that was the stage when I was about to fall from chair...

More than that, I got some speed by using "AllActors" instead of linked list known as NavigationPointlist. Because I solved this problem - somehow - I went at next stage: physics. Mapping paths for Bot using a giant it might be a bad idea or a good one depending on map. And then ? And then I went to split the build into Bot Paths and Mixed paths. Bot paths looks truly closer to what a Bot can do while Big Scout might do - rarely - fake reachable routes and causing impossible to navigate reachspecs.

Other chapter
As visual ergonomics, I went to update screen during building process at each 20 nodes pathed/connected - nice view... it slows down a bit the task, but it's still faster enough and Bot Part done with another Scout - a trooper type - it looks the best so far and I can see only very valid and clean paths. In old Editor all these paths are RED, but Bots are working like a charm. Big monsters will react like they don't have paths - that's it, it's Bot support not Monster Support. In other hand, primary pathing option from builder does paths even for normal Titans patrolling map, it's what original Editor won't do without shrinking Titan to another scale. I had tools in 227 for enlarging specs but now I have them in UT too...

"Da Manual"

Code: Select all

#define MAXMARKERS 3000 //bound number of turn markers
#define MAXREACHSPECS 3000 //bound number of reachspecs 
#define MAXCOMMONRADIUS 70 //max radius to consider in building paths
#define MAXCOMMONHEIGHT 70
#define MINCOMMONHEIGHT 48 //min typical height for non-human intelligent creatures
#define MINCOMMONRADIUS 24 //min typical radius for non-human intelligent creatures
#define COMMONRADIUS    52 //max typical radius of intelligent creatures
#define HUMANRADIUS     18 //normal player pawn radius
#define HUMANHEIGHT     39 //normal playerpawn height
For Bot Party I was picking 48 × 24 and split in arrays of 4 elements for reaching at 39 × 17 (okay they were writing 18 - perhaps for safety)
These are properties.

Code: Select all

defaultproperties
{
	MRadiuses(0)=24.000000
	MRadiuses(1)=22.000000
	MRadiuses(2)=20.000000
	MRadiuses(3)=17.000000
	MHeights(0)=48.000000
	MHeights(1)=46.000000
	MHeights(2)=42.000000
	MHeights(3)=39.000000
...
}
After a bit of fine tuning, this prick is delivering data for specs with an extreme compatibility with Bot. I could even see him in Editor as long as I was updating screen during process, first time after each node but it was too slow and I did a "stepping" solution for updating screen (ViewPort).

I would like to see Buggie participating with some C++ stuff in Editor's stage discarding Polge's stories and doing things based on Unreal's reality. A C++ based builder doesn't affect run-time compatibility because builder is part of editing not run-time.