- Home /
Rotation-Trouble
I'm a unity-newbie and need some help with my input-script:
When pushing left- and right-buttons, a spaceship shall rotate clockwise- and counterclockwise (z-axis). Doesn't sound too difficult but no matter which method I try (transform.rotate, transform.localrotation, rigidbody.moverotation, ...) it just won't rotate. I've no problems with the other keys - e.g. moving forward with transform.translate when hitting the tab-key.
Here is one attempt of my many trials. The point of interest is the block "// LEFT-Spin":
function Update () {
var stepx : float;
var stepz : float;
var minacc : float;
var maxacc : float;
maxacc = 80; //Acelleration
minacc = 10; //Minimum forward-drift
stepx = 8.5; // Booster Forward-steps
stepz = 1.5; //Sideward steps Slider
// The ship's local z- and x-axis are switched
// therefore "Vector3.right" is used (instead of "Vector3.forward")
// Nothing pressed
constantForce.relativeForce = (Vector3.right * minacc);
// UP
if(Input.GetKey("w") || Input.GetKey("up")) {
if(constantForce.relativeForce.x <= maxacc){
constantForce.relativeForce = (Vector3.right * maxacc);
}
}
//TABULATOR (Booster)
if(Input.GetKey("tab")) {
transform.Translate(Vector3.right * stepx); //Booster just moves Obj. forward
}
// DOWN
if(Input.GetKey("s") || Input.GetKey("down")) {
if(constantForce.relativeForce.x >= minacc) {
constantForce.relativeForce = -(Vector3.right * maxacc * 1.15); // breaks a bit stronger than accell - Problem: backwards-flying occurs
}
else {
constantForce.relativeForce = (Vector3.right * minacc);
}
}
// LEFT-Slide
if(Input.GetKey("q")) {
transform.Translate(Vector3.forward * stepz);
}
//LEFT-Spin
if(Input.GetKey("left") || Input.GetKey("a")) {
//Syntax:
// transform.Rotate (eulerAngles, relativeTo)
transform.localRotation(Vector3.right*20);
Debug.Log("Object was Rotated");
}
// RIGHT-Slide
if(Input.GetKey("e")) {
transform.Translate(Vector3.forward * -stepz);
}
//RIGHT-Spin
if(Input.GetKey("right") || Input.GetKey("d")) {
transform.RotateAround(Vector3.forward * -20 * Time.deltaTime);
}
}
I applied the script to an object-tree, since my spaceship is made of many parts, including light and camera which all shall move and rotate at the same time, so they behave as if they were one object. Also, there is a second C-script applied reading the mouse-input for X- and Y-axis using quaternions. Could a conflict cause the problem? I studied the half script-reference but none of the alternatives to transform.rotate seem to work.
Thanks for any help in advance.
For your inputs, use the input manager ins$$anonymous$$d of hardcoding them like that. It adds another layer of abstraction to your code, making it more readable, and it also allows the user to change the values as they see fit.
$$anonymous$$y original lines for the left-key were:
//LEFT-Spin
if(Input.Get$$anonymous$$ey("left") || Input.Get$$anonymous$$ey("a")) {
transform.Rotate(Vector3.right*20);
Debug.Log("Rotated");
}
The game is starting without messages in the console.
What wasn't working? Obviously this isn't framerate-independent, but that can be easily fixed, but it should be doing something at least.
Answer by spacepilot · Nov 03, 2011 at 06:47 AM
I think I found a solution myself: Java-Script-Mouselook together with a solved possible problem from here. Thanks for the help.
I finally figured it out: Once rotations with quaternions are in use, standard-rotation-functions don't work anymore. Furthermore quaternion-rotations have to be don with the "*="-operand (rather than just "=") to combine several of them.
The final script looks like this:
///$$anonymous$$ouselook-script with keyboard-input for Z-rotation
///Rename the input "Horizontal" to "Spin" in input manager.
var sensitivityX = 15.0;
var sensitivityY = 15.0;
var sensitivityZ = 1.0;
var $$anonymous$$imumX = -360.0;
var maximumX = 360.0;
var $$anonymous$$imumY = -60.0;
var maximumY = 60.0;
var $$anonymous$$imumZ = -360.0;
var maximumZ = 360.0;
var rotationX = 0.0;
var rotationY = 0.0;
var rotationZ = 0.0;
function Update ()
{
// Read the mouse input axis
rotationX += Input.GetAxis("$$anonymous$$ouse X") * sensitivityX;
rotationY += Input.GetAxis("$$anonymous$$ouse Y") * sensitivityY;
rotationZ += Input.GetAxis("Spin") * sensitivityZ;
// Call our Adjust to 360 degrees and clamp function
Adjust360andClamp();
// Do the rotations using quaternions:
// ---------------------------------------
// X-Axis:
transform.localRotation = Quaternion.AngleAxis (rotationX, Vector3.up);
// $$anonymous$$ultiply other Quaterion so we don't loose X we just transformed
// Y-Axis:
transform.localRotation *= Quaternion.AngleAxis (rotationY, Vector3.forward);
// Z-Axis:
transform.localRotation *= Quaternion.AngleAxis (rotationZ, Vector3.left);
} // EndFunction Update
function Adjust360andClamp ()
{
// This prevents your rotation angle from going beyond 360 degrees and also
// clamps the angle to the $$anonymous$$ and max values set in the Inspector.
// Don't let X go beyond 360 degrees + or -
if (rotationX < -360)
{
rotationX += 360;
}
else if (rotationX > 360)
{
rotationX -= 360;
}
// Don't let Y go beyond 360 degrees + or -
if (rotationY < -360)
{
rotationY += 360;
}
else if (rotationY > 360)
{
rotationY -= 360;
}
// Don't let Z go beyond 360 degrees + or -
if (rotationZ < -360)
{
rotationZ += 360;
}
else if (rotationZ > 360)
{
rotationZ -= 360;
}
// Clamp angles to the $$anonymous$$ and max set in the Inspector
rotationX = $$anonymous$$athf.Clamp (rotationX, $$anonymous$$imumX, maximumX);
rotationY = $$anonymous$$athf.Clamp (rotationY, $$anonymous$$imumY, maximumY);
rotationZ = $$anonymous$$athf.Clamp (rotationZ, $$anonymous$$imumZ, maximumZ);
}
Answer by DRP.du · Nov 02, 2011 at 10:34 AM
try For turning right: transform.eulerAngles.z += turnspeed * Time.deltaTime;
for turning left: transform.eulerAngles.z -= turnspeed * Time.deltaTime;
(turnspeed is a variable)
That only works in Javascript, I'm afraid. C# doesn't like you modifying the members of transform.eulerAngles directly.
At least part of the posted code here is in CS. I think the problem is because of bad interactions between conflicting scripts, actually.
Answer by spacepilot · Nov 02, 2011 at 01:11 PM
Okay, it seems there is a conflict with the 2nd script "mouselook.cs". I don't remember where I got it from. I think it was some standard-script:
using UnityEngine;
using System.Collections;
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityZ = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumZ = -60F;
public float maximumZ = 60F;
public enum invz { InvertedZ = -1, RegularZ = 1 } // Z-Inversion? Possible Values: -1 or 1
public invz Inverted = invz.RegularZ;
float rotationX = 0F;
float rotationZ = 0F;
float vz = 1;
Quaternion originalRotation;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
// Read the mouse input axis
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationZ += Input.GetAxis("Mouse Y") * sensitivityZ;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
rotationZ = ClampAngle (rotationZ, minimumZ, maximumZ);
if (Inverted == invz.InvertedZ ){
vz = -1;
}
else {
vz = 1;
}
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
Quaternion zQuaternion = Quaternion.AngleAxis (rotationZ, vz*Vector3.forward);
transform.localRotation = originalRotation * xQuaternion * zQuaternion;
}
void Start ()
{
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
}
public static float ClampAngle (float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp (angle, min, max);
}
}
I did remove the else-if-lines for not needed X-only and Y-only-rotation (the script offers a combobox in inspector to choose one of three modes.) The line...
rigidbody.freezeRotation = true;
...seems to disallow rotation. I changed it to false but there is no effect. Since I don't know C-programming I don't understand what exactly is happening in the script, why freezing was enabled and why a change don't take effect. When I disable the script, the transform.rotate in my own javascript-script works.
I don't understand. Why do you need to know c for this?
Because the mouselook.cs-script is a unity-standard-script and it is written in C. I did slightly modify it to get Y- and Z-axis switched. Y-axis with mouse is Y-axis for game-object too now. Z-axis however, still is locked. Even when I set the mentioned boolean to false.
Don't get confused: The above posted script is always using variables like "rotation.z". This is because y and z are switched in the script. I replaced all ....y-variables with ....z variables to get the mouselook i want.
$$anonymous$$y question now is: how do I get the objects Z-Axis (for the script the Y-Axis) unlocked for rotation? It is a C-script.
It's written in C#. Not c. There's an important difference.
Rigidbody.freezeRotation stops rotation from occuring because of physics- it doesn't prevent rotation from scripts. You use it on rigidbodies which you want the motion of controlled by physics, but you want to manage the rotation of (for example, most characters).
The problem here is that your mouselook script is overriding the output for your movement script! Is there actually any reason why you need it? It's supposed to be used for first-person controls, but it seems you are using a control scheme which works a little differently from that.
Uhm,...I have trouble to follow you. The C#-script overrides my JS-script - even though the Z-Axis is not affected by it's applied physics?! So what is "rigidbody.freezeRotation" for? No, I don't want to manage the rotation of most characters with the C#-script. It's applied to an object-tree, containing one rigidbody - as it would be if it was used in an ego-shooter. Only difference actually is switch of Y- and Z-axis.
"Physics" meaning the inbuilt rigidbody simulation. As I said, this happens outside of any scripts, JS or C#, standard assets or user produced. Honestly, I don't care that its an object tree- you'd be hard-pressed to find any complex characters which don't use something like this. As long as they are all in a transform hierarchy, you need only treat it as a single object from the top.
Get rid of the mouselook script. You don't need it, and it's just getting in your way.
Answer by Bezzy · Nov 02, 2011 at 08:04 PM
transform.rotation = Quaternion.AngleAxis(turnSpeed Time.deltaTime, transform.up);
or
transform.rotation = Quaternion.AngleAxis(turnSpeed Time.deltaTime, Vector3.up);
if you want the rotation to be world relative, rather than relative to itself. If the whole gameplay is 2D, it won't make a difference, but if you want to add roll (Which would be transform.rotation *= Quaternion.AngleAxis(rollAngle, transform.forward);), that'd feed back and mess you up.
Your answer
Follow this Question
Related Questions
Rotating child doesn't move parent Rigidbody? 1 Answer
Scale gameObject 1 Answer
How to prevent Z axis rotation ? 1 Answer
Bouncing Ball Problem( bounces vertically forever) 1 Answer
Drag object in a circle path 1 Answer