Rotate+Align object based on position and direction of sub objects

(My last post vanished - apologies if this has come through twice…)

I don’t usually have too much trouble with this sort of thing, but I’ve spent so much time trying to nut this out. I feel much further away from the solution than when I started.

I’m trying to rotate, position, and align Actors based on components within the Actor.

Top of image = before, lower = after.

I know the process is essentially:

  1. Rotate the Actor around the child component (arrow B) so that it faces the inverse forward vector of the alternate actor’s component (arrow A)
  2. Move the Actor so that the child components occupy the same location

Does anyone have any straightforward approaches or solutions to this kind of scenario?

I suspect I’m missing something blatantly obvious, as something like this should be reasonably trivial with Quaternions…

Step2 is trivial, that’s OK. I suspect I’m just not grasping or understanding part of the approach to “external” translations such as Step 1.

After coming back to the problem fresh, I realised I was probably over complicating things.

I’m sure there is a better and more efficient way of doing this, but for the time being this has worked:

//Assume, parentA and parentB are AActors, and childA and childB are USceneComponents

//rotate parentA to align with own child's rotation
FQuat parentQuat = parentA->GetActorRotation().Quaternion();
FQuat childQuat = childA->GetComponentRotation().Quaternion();
parentA->SetActorRotation(childQuat .Inverse() * parentQuat );

//rotate again to align external entrance
parentQuat = roomA->GetActorRotation().Quaternion();
childQuat = childB->GetComponentRotation().Quaternion();
parentA->SetActorRotation(childQuat * parentQuat );

//flip 180 to "face" the intended target
FVector newRotation = parentA->GetActorRotation().Euler() + FVector(0, 0, 180);
parentA->SetActorRotation(FQuat::MakeFromEuler(newRotation));

//shift to offset by child locations
parentA->SetActorLocation(room->GetActorLocation() -
	(childA->GetComponentLocation() - childB->GetComponentLocation()));

Will definitely revisit this once my understanding of how this sort of thing is handled in UE4 is better.

1 Like

Is there a way to do this with blueprints? I am trying to accomplish the same thing, connecting rooms together via doorways.

hey you can use so called group behaviors the one you looking for I believe is Alignment, there is more Separation Cohesion or Flocking to name just a few. here a pseudo code for alignment

FVector Alignment(TArray<FVector> NeighborsVelocity)
{
	FVector AverageNeighborsHeading(0.0f);

	// neighbors counter
	int NeighborCount = 0;

	// Sum Neighbors HeadingDirection
	for ( ; NeighborCount < NeighborsVelocity.Num(); NeighborCount++)
	{
		AverageNeighborsHeading += NeighborsVelocity[NeighborCount]->HeadingDirection();
	}

	// if object has one or more neighbors average their HeadingDirection
	if (NeighborCount > 0)
	{
		AverageNeighborsHeading /= static_cast<float>(NeighborCount);

		AverageNeighborsHeading -= YourObjectVector->HeadingDirection(); // this should be your object's velocity heading direction
	}

	return AverageNeighborsHeading;
}

by combining this with Separation behavior you can achieve what you want and much more

thanks to your work, I was able to create the blueprint myself. The key to making this work though is by making sure the target room is a Child Actor Component to the parent room.

Edit: I had to update the photo since my math was actually wrong. I’ve tested this equation with many types of rooms, all of which had doorways at different locations & rotations, and I have concluded that this equation is perfect.

yes this can be used by stationary objects it is the alignment force witch aims to keep’s the object heading (rotation) aligned with it’s neighbors just place a vector in the middle of each room set it’s linear length to 1 and set it’s heading to the current room rotation, the neighbors are the rooms that are around the target room so if you want to align “this” room to other room than other room is the neighbor. Combine this behavior with separation and there you go

I don’t understand this code. It uses velocity, but my rooms are stationary. Also, what are neighbors? Perhaps this can be used for stationary objects? I’m just not seeing the light… I need enlightenment, my friend.

Hey I had a go through my portfolio procedural generation code and I realized that to move this object to the front instead of using Separation behavior you could perhaps use Pursuit behavior I know the steering forces should be calculated in tick but you can implement it in while loop or perhaps use recursion and stop it at convenient time, can you some more details on how you will calculate the position that the object should move to ? is it matter whats the distance between the objects after the alignment ? is it matter if the object will be aligned at the back or the front of the target object ?

this is how the pursuit behavior works

Yes, the doorways must be connected with precision math. Thank you for your suggestions, but is there any performance gains using Separation behavior or Pursuit behavior instead of the blueprint I created above? Here is an example of how I used the blueprint function to connect 3-stair blueprints together to create a golden staircase into the heavens. Notice how the blue arrow (entrance doorway marker) connected precisely to the pink arrow (exit doorway marker). I generated 100 “rooms”, or 300 stairs all within 0.3 milliseconds.

Also, yes, the objects must be connected no matter where the doorway exists. It could exist in any direction, on the ceiling, down a flight of stairs, diagonally, and the connecting rooms must connect precisely no matter what the situation is.

well there could be a difference in speed as steering force must be applied over the time witch means iterations, you can set bigger length of vectors to speed up the calculation but this causes lost of accuracy, so if you generate thousands of objects this could be a problem

Thanks for the reference - I’ll look into that!

There are some rare edge cases with the code I used above where the aligned vectors end up facing the same way, perhaps your approach is more reliable.

I’ve used steering behaviours in some projects and not only for AI, i have one unfinished procedural generation where I used separation and alignment to calculate rooms position it worked out pretty well, even if they have to be applied over the time witch may take more time, but you can tune them, to achieve precise results

Hello!
I am using your method and it’s working wonderfully! Except, it only works on the first child actor I add, on the others the location and rotations are off. I’m using it to add rooms to a level. When I’m adding the first room to the first door that spawned, it works fine. After that, I select a different door to add another room and it spawns misplaced and rotated the wrong way. Could you please elaborate a little bit on what step I’m missing here? Thanks so much!