Download

Something very strange about Iterators...

There’s some mega-wierdness happening with Iterators, especially Object Iterators.

I’ve been struggling for a while to figure out why both my own homing missile code and the default Unreal homing missile code doesn’t work correctly. I’ve now started drawing debug sphere’s around objects that a missile or weapon is locked onto, only to find that the object iterator is picking up instances of objects in OLD positions, which also **never ** move. I checked out Object Iterators in the documentation, and there’s a (somewhat measly) note that they also pick up Editor objects. So basically, I think it’s messing with the missile code and causing them to veer off in unfathomable directions.

I’m hoping this is what the problem is, since I can’t see anything else that would cause it. Is it possible to check in code whether an object exists in the game world or in the Editor world? This is what I’m doing right now:



		for (TObjectIterator<UBZGame_GameObjectComponent> Itr; Itr; ++Itr)
		{
			AActor* GOCOwner = Itr->GetOwner();
			if (GOCOwner)
			{
				FVector TargetLocation = GOCOwner->GetActorLocation();
				FVector RelativeLocation = TargetLocation - EyeLocation;

				/* Discard Instigator and any actors being destroyed */
				if (GOCOwner == NULL || GOCOwner == Instigator || GOCOwner->IsPendingKillPending() || !GOCOwner->GetWorld())
				{
					continue;
				}


Surely there’s another check I can do to exclude Editor objects? Otherwise I have to build out to see if it’s actually working correctly or not.

Also, this caveat could do with better highlighting in the documentation, or at least on the Wiki.

Actor’s are inherently members of a specific World and as such their iterators take a World pointer and will only return Actors that belong to that world. However, Object’s generally don’t have a strong conception of World (though there is a virtual GetWorld() function that allows you to try and build a reference to the World they belong to) so the Object iterator returns all Objects regardless of World. In your case since you are operation on Components, they do (generally) have a strong concept of World, so if you were to simply filter on Itr->GetWorld() == WorldICareAbout, then you only will be dealing with Components in the specific PIE world you are operating in.

Thanks Marc. The way I got around it for now is by caching a UWorld before the For Loop with this->GetWorld(), then checking if the world in the iterator matches the world of the class that’s performing it. That works well enough for me for this case though it is an extra check to perform for each iterator. I’m just wondering if there’s a super-fast or better way to achieve it.

No, that’s probably the best approach.