Relative Rotations and Position calculation

I’m currently working on a random level generator prototype that uses templates blocks with a child object EntryPoint.

The EntryPoint behaves as a potential point at which the next chunk of the level is loaded to as a child.

Its a bit difficult to explain directly for me with words and by default is a challenge to solve, But I’m having issues with rotations and positions relative to these points:


To help me explain, here is a scenario I’m currently using to Dev this:

There will be three prefabs, lets call them A, B, C.

A and C are both connected to B when the level is generated.

A has 1 EntryPoint, Ill call it A1. It is a room with a single entrance/exit.
B has 2 EntryPoints, Ill call them B1, B2. It could be a corner, staircase, which ever.
C has 1 EntryPoint, Ill call them C1. It is a room with a single entrance/exit.

As of the moment, when the level generates,

  • A1 will spawn B as a child of it
  • B translates so that either B1 or B2 is facing the opposite direction of A1
  • The Next Free EntryPoint will then spawn C as a child to the EntryPoint
  • C translates so that C1 is on the Free EntryPoint

As a summary EntryPoints behave as an ‘attachment point’ for the level to generate upon.

The current issue is that the calculated rotations and offsets are as completely incorrect. While I know how to do Initiate the child object, the issue comes with relative rotations so that the entry points match as opposites.

Could anyone give me pointers on how I should calculate the points?

Aaaand I Solved this. (Dunno maybe next time I should wait for 24 hours before asking a question, as it takes a good while for a question to be accepted as a question but these sort of odd rotation issues seem to occur)

Luckily I’m stubborn enough to just keep trying to approach a solution until I solve it, or simply give up after a few days.

As reference to others:

Instead of moving by transform.position, and transform.rotation, I used the inherit method transform.Translate and transform.Rotate, which rotate the object by its own reference. So Barely any math needed.

So after Initiating with the rotation and position of the spawning EntryPoint, I then use these to move and rotate so that the points match the opposite of each other.

// Game Object Intantiate
		this.setUsed( true );
		brush = GameObject.Instantiate(tileEntity,  this.transform.position, this.transform.rotation ) as GameObject;
		// Get Available Entry Points
		entryPoints = brush.GetComponentsInChildren<EntryPoint>();
				
		if(entryPoints != null){ //
			
			// Select Random entry Point
			EntryPoint selectedEntry = entryPoints[ Random.Range(0, entryPoints.Length)];
			selectedEntry.gizmoColor = this.gizmoColor * 0.8f; // Debug Color
			
			selectedEntry.setUsed(true);
			
			Vector3 eulerRotation = Quaternion.Inverse(selectedEntry.transform.localRotation).eulerAngles;
			eulerRotation.y += 180; // Locally rotate 180 on y. Its the opposite to result y
			brush.transform.Rotate(eulerRotation); 
			
			brush.transform.Translate( -selectedEntry.transform.localPosition); // Relative to self, move 

		// TODO: prolly garbage collect here later to remove unnecessary
		}else{
			throw UnityException("Gameobject " +brush + " does not contain any entries" );	
		}

You must first rotate the new block so that its EntryPoint is facing the EntryPoint to which it must connect, then calculate the block offset. All EntryPoints must obey a consistent orientation rule - the forward direction of each EntryPoint points outside the block, for instance.

You could use Instantiate(newBlock) to create a new block without worrying about its position and rotation, then adjust it with a function like below, where ep1 is the reference EntryPoint and ep2 is the new block’s EntryPoint:

function AlignNewBlock(ep1: Transform, ep2: Transform){
  // find relative rotation that makes ep2 face ep1:
  var rot: Quaternion = Quaternion.FromToRotation(ep2.forward, -ep1.forward);
  // convert the rotation to parent space:
  rot = rot * Quaternion.Inverse(ep2.localRotation);
  // rotate the ep2 parent:
  var block: Transform = ep2.parent;
  block.rotation *= rot;
  // find offset of new block relative to ep2:
  var offset: Vector3 = block.position - ep2.position;
  // position block so that ep2 is at ep1 position:
  block.position = ep1.position + offset;
}

NOTE: I’ve not tested this, thus let me know if something is wrong.