# trying to make the inside of a rubik's cube

imagine being on a platform on the inside of an object which is like a 4X4 or 5X5 rubik's cube, we need to be able to look around and move whatever slices of the cube that have to be moved by pointing at them and choosing to move a 'vertical' or 'horizontal' slice.

the basic idea i had while tinkering around int eh gui was setting a slice as the child of the 'horizontal' or 'vertical'. can this be done dynamically in unity? changing the 'parent/child' relationships during gameplay by the player? any idea?

Yes, dynamic re-parenting can be done, but it's up to you if that's the best way to go in this case as there's going to be 3n - 2 (for an odd n) or 3n pivots (for an even n) to keep track of for an n x n x n cube. Since you're doing all the work of changing and re-calculating your slices anyways, it's less work to actually forget about the re-parenting in some cases. Also, depending on your use case, you may need to be concerned with misalignment of the slices.

To dynamically re-parent and rotate, you would do something like:

``````//Assuming you've figured out the objects in your slice, the pivot and axis to rotate on
function RotateSlice(slice : Transform[], pivot : Transform, axis : Vector3) {
for(var child : Transform in pivot) child = null; //clean out any old parenting
for(var cube : Transform in slice) cube.parent = pivot; //parent the slice
pivot.Rotate(axis, 90, Space.World); //Rotate
}

``````

The thing is that once you already have the cubes in your slice, determining the center might be more trivial depending upon your implementation. Once you have the center cube, you could just do something simple and not have to worry about the parenting at all:

``````for(var cube : transform in slice) cube.RotateAround(centerCube.position, axis, 90);

``````

There are any number of ways you can decide to force the alignment of the slices. Likewise, depending on if and how you want to track the rotations, either implementation might better suit your use case.

The problem comes with determining the axis. "horizontal" and "vertical" can change as your orientation relative to the surface changes (looking at the roof while turning in place or tilting your head while looking at a wall for example). You will need to resolve which way is which. Something like this could be done fairly easily, but is very dependent upon the setup of your scene:

``````var axis : Vector3;
if(rotateVertical) axis = mainCamera.transform.right;
else if(rotateHorizontal) axis = mainCamera.transform.up;

if(axis) {
var dot : float = Vector3.Dot(axis, Vector3.up);
//Check the cube up
if(dot >= 0.5) axis = Vector3.up;
else if(dot <= -0.5) axis = -Vector3.up;
else { //one of the sides is our axis
//Check the cube right
dot = Vector3.Dot(axis, Vector3.right);
if(dot >= 0.5) axis = Vector3.right;
else if(dot <= -0.5) axis = -Vector3.right;
//Check the cube forward
else if(Vector3.Dot(axis, Vector3.forward >= 0.5) axis = Vector3.forward;
else axis = -Vector3.forward;
}
}

``````

It's at worst 3 dot products to tell which axis to rotate around. You could obviously use the Rubik's cube's actual axes rather than the world axes, but it was simpler to assume a world-aligned cube than to assume a parent cube to all of the cubes that comprise it because of the parenting stuff. If you were to have a parent to all of the cubes (and pivots too if you like), instead of setting the parents to null, you would set them to the parent cube.

This post was about something similar, but was concerned with running atop the cube to rotate the slices. My answer there is much longer, but pretty much says the same thing.

Why not to base the selecting of slices on “subcubes” position?. A user could click a “subcube” and its position and the area where the user clicks it would determine the slice position and orientation. Once the slice position and orientation is sorted out, the whole slice is being selected as well as one of the six possible rotation axes (Vector3.up,-Vector3.up,Vector3.right,-Vector3.right,Vector3.forward,-Vector3.forward). That is just my solution and I have made available the code at http://virtualplayground.d2.pl.

Once the selection is made and target rotation calculated, I tween the rotation using Quaternion.Slerp on Update function, after temporary disabling of the cube interactivity for the tweening time.