Previously, I published “Script to roll a cube” and the script for rectangular parallelepiped were requested. So I made it.

 

 

The script is the following

using UnityEngine;
using System.Collections;

public class moveRect : MonoBehaviour {

	public float rotationPeriod = 0.3f;		// period to move the next position
	Vector3 scale;							// the size of rectangle parallelepiped

	bool isRotate = false;					// flag for under rotation
	float directionX = 0;					// flag for rotation direction
	float directionZ = 0;					// flag for rotation direction

	float startAngleRad = 0;				// angle from the horizontal plane to the center before rotation
	Vector3 startPos;						// position before rotation
	float rotationTime = 0;					// past time since rotation start
	float radius = 1;						// radius of center (initialized by 1)
	Quaternion fromRotation;				// quaternion before rotation
	Quaternion toRotation;					// quaternion after rotation

	// Use this for initialization
	void Start () {

		// get the size of rectangle parallelepiped
		scale = transform.lossyScale;
		//Debug.Log ("[x, y, z] = [" + scale.x + ", " + scale.y + ", " + scale.z + "]");

	}

	// Update is called once per frame
	void Update () {

		float x = 0;
		float y = 0;

		// get key input
		x = Input.GetAxisRaw ("Horizontal");
		if (x == 0) {
			y = Input.GetAxisRaw ("Vertical");
		}


		// rotate rectangle parallelepiped if key was input and rectangle parallelepiped was not rotating
		if ((x != 0 || y != 0) && !isRotate) {
			directionX = y;																// set rotation direction (x or y is 0)
			directionZ = x;																//set rotation direction (x or y is 0)
			startPos = transform.position;												// keep the coordinate before rotation
			fromRotation = transform.rotation;											// keep the quaternion before rotation
			transform.Rotate (directionZ * 90, 0, directionX * 90, Space.World);		// rotate to 90 deg.
			toRotation = transform.rotation;											// keep quaternion after rotation
			transform.rotation = fromRotation;											// get the rotation of rectangle parallelepiped back to that of before rotation (shallow copy of transform is available?)
			setRadius();																// calculate the radius of rotation
			rotationTime = 0;															// set the past time of rotation to 0
			isRotate = true;															// set flag for during rotation
		}
	}

	void FixedUpdate() {

		if (isRotate) {

			rotationTime += Time.fixedDeltaTime;									// add past time of rotation
			float ratio = Mathf.Lerp(0, 1, rotationTime / rotationPeriod);			// the ration of past time per all time to rotation

			// move
			float thetaRad = Mathf.Lerp(0, Mathf.PI / 2f, ratio);					// get radian of rotation angle
			float distanceX = -directionX * radius * (Mathf.Cos (startAngleRad) - Mathf.Cos (startAngleRad + thetaRad));		// distance of X. "-" is for the moving direction.
			float distanceY = radius * (Mathf.Sin(startAngleRad + thetaRad) - Mathf.Sin (startAngleRad));						// distance of Y
			float distanceZ = directionZ * radius * (Mathf.Cos (startAngleRad) - Mathf.Cos (startAngleRad + thetaRad));			// distance of Z
			transform.position = new Vector3(startPos.x + distanceX, startPos.y + distanceY, startPos.z + distanceZ);			// set the present position

			// rotate
			transform.rotation = Quaternion.Lerp(fromRotation, toRotation, ratio);		// set the present angle using Quaternion.Lerp (what a convenient function!!) 

			// initialize all parameter after moving and rotation
			if (ratio == 1) {
				isRotate = false;
				directionX = 0;
				directionZ = 0;
				rotationTime = 0;
			}
		}
	}

	void setRadius() {

		Vector3 dirVec = new Vector3(0, 0, 0);			// vector of moving direction
		Vector3 nomVec = Vector3.up;					// (0,1,0)

		// change the moving direction to vector
		if (directionX != 0) {							// move to X direction
			dirVec = Vector3.right;						// (1,0,0)
		} else if (directionZ != 0) {					// move to Z direction
			dirVec = Vector3.forward;					// (0,0,1)
		} 

		// calculate radius and startAngle with the inner product between the moving direction and the face direction of object.
		if (Mathf.Abs (Vector3.Dot (transform.right, dirVec)) > 0.99) {						// moving direction is the same as x of object
			if (Mathf.Abs (Vector3.Dot (transform.up, nomVec)) > 0.99) {					// y axis of global is the same as y of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.x/2f,2f) + Mathf.Pow(scale.y/2f,2f));	// radius of rotation
				startAngleRad = Mathf.Atan2(scale.y, scale.x);								// the angle from horizontal plane to the center before rotation
			} else if (Mathf.Abs (Vector3.Dot (transform.forward, nomVec)) > 0.99) {		// y axis of global is the same as z of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.x/2f,2f) + Mathf.Pow(scale.z/2f,2f));
				startAngleRad = Mathf.Atan2(scale.z, scale.x);
			}

		} else if (Mathf.Abs (Vector3.Dot (transform.up, dirVec)) > 0.99) {					// moving direction is the same as y of object
			if (Mathf.Abs (Vector3.Dot (transform.right, nomVec)) > 0.99) {					// y of global is the same as x of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.y/2f,2f) + Mathf.Pow(scale.x/2f,2f));
				startAngleRad = Mathf.Atan2(scale.x, scale.y);
			} else if (Mathf.Abs (Vector3.Dot (transform.forward, nomVec)) > 0.99) {		// y axis of global is the same as z of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.y/2f,2f) + Mathf.Pow(scale.z/2f,2f));
				startAngleRad = Mathf.Atan2(scale.z, scale.y);
			}
		} else if (Mathf.Abs (Vector3.Dot (transform.forward, dirVec)) > 0.99) {			// moving direction is the same as z of object
			if (Mathf.Abs (Vector3.Dot (transform.right, nomVec)) > 0.99) {					// y of global is the same as x of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.z/2f,2f) + Mathf.Pow(scale.x/2f,2f));
				startAngleRad = Mathf.Atan2(scale.x, scale.z);
			} else if (Mathf.Abs (Vector3.Dot (transform.up, nomVec)) > 0.99) {				// y axis of global is the same as y of object
				radius = Mathf.Sqrt(Mathf.Pow(scale.z/2f,2f) + Mathf.Pow(scale.y/2f,2f));
				startAngleRad = Mathf.Atan2(scale.y, scale.z);
			}
		}
		//Debug.Log (radius + ", " + startAngleRad);
	}
}

 

Make Cube, set the scale of “Transform”, and add the above script to the object. That it!

 

This script is just an impromptu. I think there is better script.

 

Download “Colorful Dice” from the following link;

【Android】Colorful Dice -カラフルでポップなサイコロパズル-

 

Categories: memo

2 Comments

Hamza Younas` · 2018-08-07 at 19:06

How to get movement on button by right, left up and down arrow for mobile controls

    PiroMayo · 2018-08-07 at 22:24

    It depends on your design concept; how do you want to control the cube. So it is difficult to answer.
    You can find the tutorial about mobile and touch on unity in the following page.
    https://unity3d.com/learn/tutorials/s/mobile-touch
    If you want to use virtual controller, you can find it in the unity asset store and github.

    In my app “Colorful Dice“, I control the cube using the following script.

    if (Input.touchCount == 1 && manager.GetComponent ().isPlaying) {
        Touch touch = Input.GetTouch (0);
    
        if (touch.phase == TouchPhase.Moved) {
            float x = touch.deltaPosition.x;
            float y = touch.deltaPosition.y;
    
            if (Mathf.Abs (x) < reactionThreshold) { x = 0; }
            if (Mathf.Abs (y) < reactionThreshold) { y = 0; }
    
            if (Mathf.Abs(x) > Mathf.Abs(y) && !isRotate) {
                if ((x > 0 && transform.position.z + error < moveLimitZmax) || (x < 0 && transform.position.z - error > moveLimitZmin)) {
                    directionZ = x;
                    startPos = transform.position;
                    fromRotation = transform.rotation;
                    transform.Rotate (NormalizeFloat (directionZ) * 90, 0, NormalizeFloat (directionX) * 90, Space.World);
                    toRotation = transform.rotation;
                    transform.rotation = fromRotation;
                    rotationTime = 0;
                    isRotate = true;
                }
            } 
    
            if (Mathf.Abs(y) > Mathf.Abs(x) && !isRotate) {
                if ((y > 0 && transform.position.x - error > moveLimitXmin) || (y < 0 && transform.position.x + error < moveLimitXmax)) {
                    directionX = y;
                    startPos = transform.position;
                    fromRotation = transform.rotation;
                    transform.Rotate (NormalizeFloat (directionZ) * 90, 0, NormalizeFloat (directionX) * 90, Space.World);
                    toRotation = transform.rotation;
                    transform.rotation = fromRotation;
                    rotationTime = 0;
                    isRotate = true;
                }
            }
        }
    }
    

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.