- Home /
Rotation used as movement
Hi everybody. I'm trying to setup a control scheme using only object rotation. If the object rotates on Z, it moves forward/backward on X. If it rotates on X, it moves on Z.
Imagine someone trying to balance a broomstick on their hand. If it tilts forward, the person must move forward to keep it in balance. That's the general idea I'm going for. I'm a good artist but very new at scripting, so I'm probably going about this the worst way possible. Here's what I have so far:
var rotSpeed = 5.0;
var traSpeed = 0.5;
function Update () {
var rotX = Input.GetAxis("Mouse Y") * Time.deltaTime * rotSpeed;
var rotZ = Input.GetAxis("Mouse X") * Time.deltaTime * rotSpeed;
var traX = rotZ * traSpeed;
var traZ = rotX * traSpeed;
transform.Rotate(rotX,0,rotZ);
transform.Translate(traX,0,traZ);
}
Answer by wccrawford · Oct 11, 2011 at 01:27 PM
You're just looking for general advice? You don't have any actual issues with your code so far?
It looks like you've got the right idea to me, and I don't see how it could be any simpler.
If it really was like a broomstick, it'd be a lot more complicated, though. To get the broomstick upright again, you have to actually outpace the stick for a short time to make it be upright again.
Answer by clondike7 · Oct 11, 2011 at 08:43 PM
Thanks for replying!
"To get the broomstick upright again, you have to actually outpace the stick for a short time to make it be upright again."
Absolutely no idea what that means, sorry. As it is, the rotation input is directly tied to the translate, which makes the character move pretty freely and not in the direction of the rotation. I also need the character to move in a continuous direction as long as it is tilted in that direction. I hope that clears things up a bit.
I've stopped and put this into a test project, and it appears my 3d math isn't good enough for this yet.
I think I can give some tips, though:
You want to store the tilt and re-use and or subtract from it, ins$$anonymous$$d of just using the mouse axis raw. Something like this.
var rotSpeed = 5.0;
var traSpeed = 0.5;
var tiltX = 0;
var tiltZ = 0;
function Update () {
tiltX += Input.GetAxis("$$anonymous$$ouse Y");
tiltZ += Input.GetAxis("$$anonymous$$ouse X");
var rotX = tiltX * Time.deltaTime * rotSpeed;
var rotZ = tiltZ * Time.deltaTime * rotSpeed;
var traX = tiltX * Time.deltaTime * traSpeed;
var traZ = tiltZ * Time.deltaTime * traSpeed;
transform.Rotate(rotX,0,rotZ);
transform.Translate(traX,0,traZ);
}
I'll play around with this idea. I hadn't thought of storing the tilt as variables. Thanks for the tip!
Answer by aldonaletto · Oct 11, 2011 at 11:21 PM
If you want to do something like a Segway, that moves to the side you tilt, you can't use Rotate - Rotate will spin the object continuously in the direction you're going. You should set the eulerAngles and calculate the velocity proportionally to the joystick input:
var traSpeed = 6.0;
var maxAngle = 20.0;
function Update () {
// get the value of the axes (-1..+1)
var rotX = Input.GetAxis("Vertical");
var rotZ = Input.GetAxis("Horizontal");
// set the eulerAngles
transform.eulerAngles = Vector3(rotX * maxAngle, 0, -rotZ * maxAngle);
// calculate the displacement (frame rate independent)
var traX = rotZ * traSpeed * Time.deltaTime;
var traZ = rotX * traSpeed * Time.deltaTime;
// and move the object
transform.Translate(traX, 0, traZ, Space.World);
}
Segway! That's a much better analogy for the kind of control I'm going for. And yes, I was having the "endless rotation" problem, I was looking for a way to limit it. I am researching eulerAngles as we speak, actually.
I tried your code, but it only moves on XZ axis, no rotation. Dumb question: how do I set eulerAngles?
Thanks for the help!
$$anonymous$$y fault: you're using $$anonymous$$ouse X and Y, not a joystick! I had the joystick in my $$anonymous$$d, and even writing $$anonymous$$ouse X and $$anonymous$$ouse Y I didn't notice that! I'll edit the answer.
I modified the script in my answer to use the Vertical and Horizontal axes: you can use a joystick or the keys A-D (Horizontal) and W-S (Vertical).
Using $$anonymous$$ouse X / Y is more complicated, because the values returned are way smaller, and depend on the mouse velocity. If you really need to use $$anonymous$$ouse, define a "gain" variable, multiply by the values returned and clamp between -1 and +1:
var gain = 5.0; // adjust the sensibility here
function Update(){ rotX = $$anonymous$$athf.Clamp(gain Input.GetAxis("$$anonymous$$ouse Y"), -1, 1); rotZ = $$anonymous$$athf.Clamp(gain Input.GetAxis("$$anonymous$$ouse X"), -1, 1); ... The result isn't good because the values read vary a lot, making the character unstable.
The WASD will work for now. I'll take this small victory and study your code to better understand it (I hope). I'll tackle the $$anonymous$$ouse conversion tomorrow. Thanks so much! I'll work on the mouse conversion tomorrow.
Answer by clondike7 · Oct 20, 2011 at 05:34 PM
Hey guys. I'm almost 90% of the way there and wanted to share. I got the mouse controls to work, up=forward, down=backward, left and right. However, if I do a circle, which combines movements, it tends to get stuck or stutter for a sec or so. Here's what I got:
var mousePos : Vector2 = Input.mousePosition; //Mouse position
var maxX = Screen.width/2; //Changes mouse position on X
var maxZ = Screen.height/2; //Changes mouse position on Y
var mouseDistance : Vector2 = mousePos - new Vector2(maxX, maxZ);
var rotX = mouseDistance.x / maxX;
var rotZ = mouseDistance.y / maxZ;
transform.eulerAngles = Vector3(rotZ * maxAngle, 0, -rotX * maxAngle);
var traX = rotX * traSpeed * Time.deltaTime;
var traZ = rotZ * traSpeed * Time.deltaTime;
var controller : CharacterController = GetComponent(CharacterController);
var moveDir : Vector3 = Vector3(traX, 0, traZ);
controller.Move(moveDir);