x


Rolling cubes one space and one rotation at a time, with a delay

I am about a week in to Unity but reading through all the tutorials, guides and documentation I can as quickly as I can.

I have what I'm sure is a simple scenario but I'm having trouble determing the method to tackle it in Unity.

What I want to do is have a row of cubes roll 90 degrees and one position downward followed by a delay of 2 seconds (an arbitrary number of seconds), and then repeat. Put another way, I want the cube to roll over on its side in the direction it is rolling.

From what I've gathered so far, I thought one way would be to transform the cube at set intervals:

private var cubeTimer : float = 0.0;
private var currentCube : GameObject;

private var cubeTime : float = 2.0;
private var cubeSpeed : float = 50.0;

function Update () {
    cubeTimer += Time.deltaTime;
    spinAmount = Time.deltaTime * cubeSpeed;

    if (cubeTimer > cubeTime){
        transform.position.x = transform.position.x +1;
        cubeTimer = 0.0;
    }
    transform.Rotate(0, 0, -spinAmount);
}

That's rotating it, but that rotation doesn't match up with the movement in the x-axis properly, so it looks awful. How could I sync the roll to exactly match up with the x-asix movement?

Should I be doing this as a RigidBody and AddMotion instead? I tried that, but the roll didn't seem predictable depending on where the block was on the plane.

There are animation curves I know, but I wonder how I would sync the rotation and movement on the x-axis.

more ▼

asked Nov 25 '09 at 04:20 AM

TedB gravatar image

TedB
26 2 3 7

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

A simple solution is to do the rotation as an animation where at the end of the animation the cube has moved the +1 distance.

Alternatively use Transform.rotateArount to rotate around a point on the edge of the cube you're currently rolling over.

If not clear what I mean, let me know, can make an example or so.

EDIT: too much fun to pass, here sample code in C# (sorry not too fond of javascript but shouldn't be too hard to convert if you need), Just create new C# class called RollCube and copy/paste code below over it.

EDIT2: now have rotation done from Coroutine so we can delay after rolling to a side.

using UnityEngine;
using System.Collections;

public class RollCube : MonoBehaviour {

    public float cubeSize = 1f; 
    public float cubeSpeed = 50f;
    public float delay = 2f;

    private float totalRotation = 0f; // determines if we're past the 90 degrees
    private float startHeight = 0f; // for correcting height errors

    // next two vars are for determining the corner
    // to rotate over
    private float fwdWeight = 0.5f;
    private float upWeight = -0.5f; 


    // Use this for initialization
    void Start () {
    	startHeight = transform.position.y;
    	StartCoroutine(CORollCube());
    }

    IEnumerator CORollCube() {
    	while (true) {			
    		// we calc the spinamount but make sure it won't shoot over the 90 degrees
    		float spinAmount = Mathf.Min(Time.deltaTime * cubeSpeed, 90f - totalRotation);

    		// we rotate around one of the edges of the cube (the stationary one of course)
    		transform.RotateAround(transform.position + (fwdWeight * transform.forward + upWeight * transform.up) * cubeSize, Vector3.right, spinAmount);

    		// add to amount of spin in this update the total rotation
    		totalRotation += spinAmount;

    		// check if we have to move to the next edge
    		if (totalRotation >= 90f) {
    			// we move to next corner as pivot point
    			totalRotation -= 90f;
    			float t = fwdWeight;
    			fwdWeight = -upWeight;
    			upWeight = t;

    			// make sure height stays correct
    			Vector3 pos = transform.position;
    			pos.y = startHeight;
    			transform.position = pos;

    			// wait for delay amount of seconds
    			yield return new WaitForSeconds(delay);
    		}
    		else {
    			// ready for this frame
    			yield return 0;
    		}
    	}
    }
}
more ▼

answered Nov 25 '09 at 04:36 AM

Jaap Kreijkamp gravatar image

Jaap Kreijkamp
6.4k 20 26 70

Thanks for the quick answer and code for rotating and moving the cube forward at the same time. Looks great!

I'm having trouble applying it though with a delay after the move. I figured I could pause it after a 90 rotation with a yield WaitForSeconds(2) but that doesn't stop it at all. My goal is to be able to start and stop the cube advancing one position at a time if a player does something, otherwise, keep moving, with a pause between moves. Am I on the right track? Any idea what's up with yield not yielding?

Nov 28 '09 at 04:41 AM TedB

That update with the coroutine works great. I was trying to do the coroutine in JavaScript but evidently not correctly. I'll leave it as C# for now.

Nov 30 '09 at 02:51 AM TedB

That came handy to me! Was not trying out for any of these things but obviously there was a rotation and shifting of pivot points! Thanx!!!

Jan 25 '12 at 07:58 AM ArunChnadran
(comments are locked)
10|3000 characters needed characters left
// Reposting this non-working answer because it was unreadable when posted as a comment to the previous answer

var cubeSize : float = 1; 
var cubeSpeed : float = 80;

private var totalRotation : float = 0; // determines if we're past the 90 degrees
private var startHeight : float = 0; // for correcting height errors

// next two vars are for determining the corner
// to rotate over
private var fwdWeight : float = 0.5;
private var upWeight : float = -0.5; 


// Use this for initialization
function Start () {
    startHeight = transform.position.y;
}

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

    DoRoll(2);

}

function DoRoll (delay: float) {
    var spinAmount : float = Time.deltaTime * cubeSpeed;
	var t : float;
	var pos : Vector3;

    // we rotate around one of the edges of the cube (the stationary one of course)
    transform.RotateAround(transform.position + (fwdWeight * transform.forward + upWeight * transform.up) * cubeSize, Vector3.right, spinAmount);

    // add to amount of spin in this update the total rotation
    totalRotation += spinAmount;

    // check if we have to move to the next edge
    if (totalRotation >= 90) {
            // we move to next corner as pivot point
            totalRotation -= 90;
            t = fwdWeight;
            fwdWeight = -upWeight;
            upWeight = t;

            // make sure height stays correct
            pos = transform.position;
            pos.y = startHeight;
            transform.position = pos;
        	print ("At rotation " + totalRotation);
			yield WaitForSeconds(delay);

    }
}
more ▼

answered Nov 28 '09 at 04:48 AM

TedB gravatar image

TedB
26 2 3 7

thanx for the conversion too!!

Jan 25 '12 at 08:49 AM ArunChnadran
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x5084
x3791
x2168

asked: Nov 25 '09 at 04:20 AM

Seen: 4150 times

Last Updated: Jan 25 '12 at 08:49 AM