# Rotating dice based on which side is up

In my 3d board game project I am rolling dice then moving them into a camera position where they are easily seen by the camera. So the dice rolls on the mat then they move up to the camera so the player can chose which dice to keep. How would I rotate them to straighten them out? The problem is the X,Y,Z coordinates could all be different depending on which face they land on. I need to be able to rotate them slightly so they are not crooked like in the screenshot attached. The 1 and the 2 or on different axis’s.

Concerning the perspective you wont be able to fight it, you will only be able to attenuate it at best. The operation you are looking for is known as “snaping”. Whether you want to attenuate the perspective by aligning the dice with the camera direction, or making it look at the camera, or align the dice with a surface normal, you need a direction to be aligned with and a direction to align.

In some circumstances a simple euler angle snaping suffice.

Otherwise pick the forward, right and up vectors of your dice transform, the one that is the most aligned with the axis you want to be aligned with will be used for snaping.

The most aligned will be the one for which:
Mathf.Abs( vector3.Dot( forward/right/up, snap_vector ) ) will be the greatest.

Then you compute:
Quaternion.FromToRotation( forward/right/up, Mathf.Sign(Vector3.Dot(forward/right/up, snap_vector)) * snap_vector ) and rotate your dice using the resulting quaternion.

Link to sample code project: ANGLE_SNAP.zip - Google Drive

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;

#endif

//****************************************************************************
//
//****************************************************************************

static public class SnapOrientation
{
#if UNITY_EDITOR

//************************************************************************
//
//************************************************************************

[ MenuItem( "GameObject/SNAP/X", false, 10 ) ]

static public void SnapX( MenuCommand cmd )
{
GameObject obj = ( cmd.context != null ) ? cmd.context as GameObject : Selection.activeObject as GameObject;

Snap( obj, Vector3.right );
}

//************************************************************************
//
//************************************************************************

[ MenuItem( "GameObject/SNAP/Y", false, 10 ) ]

static public void SnapY( MenuCommand cmd )
{
GameObject obj = ( cmd.context != null ) ? cmd.context as GameObject : Selection.activeObject as GameObject;

Snap( obj, Vector3.up );
}

//************************************************************************
//
//************************************************************************

[ MenuItem( "GameObject/SNAP/Z", false, 10 ) ]

static public void SnapZ( MenuCommand cmd )
{
GameObject obj = ( cmd.context != null ) ? cmd.context as GameObject : Selection.activeObject as GameObject;

Snap( obj, Vector3.forward );
}

#endif

//************************************************************************
//
//************************************************************************

static public void Snap( GameObject obj, Vector3 snap )
{
if( obj  == null         ) return;

if( snap == Vector3.zero ) return;

Transform   xform = obj.transform;

float   align_max = Mathf.Abs( Vector3.Dot( xform.forward, snap ) );

Vector3 candidate = xform.forward;

float align = Mathf.Abs( Vector3.Dot( xform.right, snap ) ); if( align_max < align ) { candidate = xform.right; align_max = align; }

align = Mathf.Abs( Vector3.Dot( xform.up,    snap ) ); if( align_max < align ) { candidate = xform.up; }

float      sign      = Mathf.Sign( Vector3.Dot( candidate, snap ) );

Quaternion snap_quat = Quaternion.FromToRotation( candidate, sign * snap );

xform.rotation       = snap_quat * xform.rotation;
}
}
``````