Roll cuboid does not work properly
Hello, I am trying to make a game, with the movement behavior, like in the game Blockorz (See gameplay video), but I can't make it roll properly. In the scripts I have used by searching this forum, I have made the cuboid to roll at the edge, but this is not working properly. I suspect its because I always use 0.5f as the half cube size, but the cuboid is a 1 width and 2 height cuboid.
Please help me, I have no clue how I can resolve this. The script I am using is this
using UnityEngine;
using System.Collections;
public class MoveCube : MonoBehaviour {
public float speed = 1.0f;
private Transform pivotPoint;
private float halfCubeSize = 1.0f;
private bool isRotating = false;
// Use this for initialization
void Awake () {
pivotPoint = (new GameObject("pivot")).transform;
}
// Update is called once per frame
void Update()
{
if (!isRotating)
{
if (Input.GetKey(KeyCode.RightArrow))
{
StartCoroutine(RotateCube(Vector3.right * halfCubeSize, -Vector3.forward));
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
StartCoroutine(RotateCube(-Vector3.right * halfCubeSize, Vector3.forward));
}
else if (Input.GetKey(KeyCode.UpArrow))
{
StartCoroutine(RotateCube(Vector3.forward * halfCubeSize, Vector3.right));
}
else if (Input.GetKey(KeyCode.DownArrow))
{
StartCoroutine(RotateCube(-Vector3.forward * halfCubeSize, -Vector3.right));
}
}
}
// Coroutine that rotates the cube on its bottom edges.
IEnumerator RotateCube(Vector3 refPoint, Vector3 rotationAxis)
{
isRotating = true;
pivotPoint.localRotation = Quaternion.identity;
pivotPoint.position = transform.position - Vector3.up * halfCubeSize + refPoint;
transform.parent = pivotPoint;
float angle = 0.0f;
while (angle < 90.0f)
{
angle += Time.deltaTime * 90.0f * speed;
pivotPoint.rotation = Quaternion.AngleAxis(Mathf.Min(angle, 90.0f), rotationAxis);
yield return null;
}
transform.parent = null;
isRotating = false;
yield return null;
}
}
Answer by Fattie · Dec 12, 2015 at 07:15 PM
It's basically extremely hard to do this. if you're just getting started programming, I'd forget about it.
In short you do this:
You need to make a "control point" (that is to say, just an empty game object, a "point" or often called "a marker") and you move that around to the point where you want to "rotate the object around".
{Aside - during development you will surely want to attach a tiny gizmo ball, or whatever, to that point so you know where it is.}
Additionally you need to locate all these points, something like this...
(they may perhaps be built-in to your scenery, with a whole lot of markers, or, you may calculate them ... )
You then need to be very adept at moving the parenting of the cuboid around so that the cuboid is flexibly a child of the marker.
You then rotate the marker (never the cuboid). There are then very many other issues to deal with such as "knowing" which side is up and so on with the cuboid, which is a whole other issue.
All of your code is not really on the right track. Regarding the rotation of the marker, really you would try to do this ideally with a Unity animation, or something. (You'll need to master that anyway .. as a basic skill if you're trying to make a game like this.)
Anyway that's the answer to your question, the trick is you move around a marker (which has no parent, it's free) which will be the "rotation point". And only then you re-parent the cuboid to that "rotation point". And then rotate that marker, not the cuboid. This is completely commonplace in vid game development.
Note that if you have a lot of complicated code (maybe, finger dragging .. whatever) that all just sits very easily on the rotator-marker, very simple.
Note too that there's the call Transform.RotateAround
which is a revalation - but basically for the type of mechanic you mention, the solution is the "moving re-parenting marker" thing! Enjoy!
I am not sure what you mean... I am already trying to set an emtpy game object as the marker, which the cuboid will rotate around, in the script, which I have supplied.
Can you please help me with some code examples? And how can I deal with the issues as knowing which sides is up and so, and why is it important in my scenario??
I am already trying to set an emtpy game object as the marker, which the cuboid will rotate around I'm so sorry! O$$anonymous$$ so you're on track.
Next you will have to do this:
"you will surely want to attach a tiny gizmo ball, or whatever, to that point so you know where it is"
use this: http://docs.unity3d.com/ScriptReference/Gizmos.DrawSphere.html
When you roll, make the point visible using a gizmo ball and leave it for say 5 seconds (so you can see what is going on .. is it in the wrong place etc?) and then roll it slowly. You'll soon figure out the problem, or post a video.
I believe your fundamental present problem is that you are making the rotator point based on your cuboid. You really can't do this - you have to make it based on the floor, that information has to come from the "layout" as it were.
To make sort of a bad analogy - say you were program$$anonymous$$g bejeweled. You can't, really, make the gems move around "by themselves". (You can't have a gem move "one meter" .. you know?) The BOARD moves the gems around. So, the "board" says, I'll move a certain gem from position blah to position blah. the board "knows" all the positions.
I hope that makes sense!!!
note that you CAN do what you're trying to do (make the objects sort of "move itself" independently),
by simply CHEC$$anonymous$$ING ITS "OWN" SIZE EVERY TI$$anonymous$$E,
it is very easy to get the size of an object in Unity. Here's some posts on it,
http://answers.unity3d.com/questions/432009/resizing-a-gameobject-based-on-mouse-position.html
Actually, this is an extremely common technique. You can imagine, very often, you have to - for example - move an object "by it's own length".
Be careful to ONLY use global coordinates, since you want the object to have "new" xyz, so to speak, each time. Hope it helps!
$$anonymous$$hh. Now I have tried to modify my code using the cuboids size, however I still can't figure out how to do it right.
I got my cubes size by using
transform.getComponent<Renderer>().bounds.size
But when I am trying to use the size as the value for the variable 'halfCubeSize' It still won't behave like I want to.
I am beginning to give up on this 'simple' mechanic, since I can't figure out what I am doing wrong atm.