I am spawning these 2 tyers on either side of the cube using Raycast hit.
tyer.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
But as you can see both the tyers have a different spin directions which is Positive Y axis in the Hinge Joint.
I want them to spin in same direction when attached in opposite sides.
If i use tyer.rotation = Quaternion.LookRotation(hit.normal); it works fine but on a different tyer where Z axis is pointing outwards.
How can I make it work with this tyer where Y axis is point outwards ?
Related
I have a camera, it is attached to the capsule, and rotates independently of it.
But I need the capsule to rotate along the Y axis following the camera. How to get the Y-axis rotation values of the camera? Tried through transform.rotation.y. But it gives an error.
Transform.rotation returns a Quaternion (see also Wikipedia - Quaternion) - it has not 3 but 4 components x, y, z and w!
=> Unless you know exactly what you are doing - which is almost never the case ^^ - you do never want to touch any of its components directly.
Unfortunately also the Transform.eulerAngles are not really reliable for your use case.
So what I would do is rely on Vector3 instead.
// take camera's forward vector
private forward = yourCamera.transform.forward;
// erase the Y axis => vector is now only on the XZ plane rotating around Y
forward.y = 0;
// rotate the capsule so its forward vector aligns with "forward"
yourCapsule.transform.rotation = Quaternion.LookRotation(forward);
// could also do
//yourCapsule.transform.forward = forward;
see also Quaternion.LookRotation
Quaternion FromToRote = Quaternion.FromToRotation(Vector3.right, new Vector3(roadEnd.x, roadEnd.y, roadEnd.z) - road.position);
road.transform.rotation = FromToRote;
I have this piece of code handling my rotation. It rotates a GameObject to the position of my mouse, but the x axis rotates to -90 when moving towards the right.
https://gyazo.com/91fa0caee3f62b353b33e6a175e93e55
I tried to fix the x axis to 0, but that caused all the axes to default to 0. I'm not at all good with quaternions so I have no clue how to approach this.
Overview
I've been looking around for a while and haven't found an answer so hopefully the community here can help me out. I am re-working my look-at camera (written pre 2000) and am having trouble getting rid of an issue where the look-at and up vectors become aligned causing the camera to spin wildly out of control. I originally understood this to be gimbal lock, but now I'm not so sure of that.
From my understanding of gimbal lock, when pitch becomes aligned with roll, pitch becomes roll; and in essence this is what it appears to be, but the problem is that the rate of change shouldn't increase just because the axes become aligned, I should just get a smooth roll. Instead I get a violent roll in which I can't really tell which way the roll is going.
Updating the Camera's Position
When the user moves the mouse I move the camera based on the mouse's X and Y coordinates:
Vector2 mousePosition = new Vector2(e.X, e.Y);
Vector2 delta = mousePosition - mouseSave;
mouseSave = mousePosition;
ShiftOrbit(delta / moveSpeed);
Within the ShiftOrbit method, I calculate the new position based on the look-at, right, and up vectors in relationship to the delta passed from the mouse event above:
Vector3 lookAt = Position - Target;
Vector3 right = Vector3.Normalize(Vector3.Cross(lookAt, Up));
Vector3 localUp = Vector3.Normalize(Vector3.Cross(right, lookAt));
Vector3 worldYaw = right * delta.X * lookAt.Length();
Vector3 worldPitch = localUp * delta.Y * lookAt.Length();
Position = Vector3.Normalize(Position + worldYaw + worldPitch) * Position.Length();
This works smoothly as it should and moves the camera around its target in any direction of my choosing.
The View Matrix
This is where I experience the problem mentioned in the overview above. My Up property was previously set to always be 0, 0, 1 due to my data being in ECR coordinates. However, this is what causes the axis alignment as I move the camera around and the view matrix is updated. I use the SharpDX method Matrix.CreateLookAtRH(Position, Target, Up) to create my view matrix.
After discovering that the Up vector used when creating the view matrix should be updated instead of always being 0, 0, 1, I encountered another issue. I now caused roll when yaw and pitch were introduced. This shouldn't occur due to a requirement so I immediately began pursing a fix.
Originally I performed a check to see if was coming close to being axis aligned, if I was, then I set the Up used to create my view matrix to the local up of the camera, and if I wasn't then I used only the Z axis of the local up to ensure that up was either up or down.
float dot = Math.Abs(Vector3.Dot(Up, Position) / (Up.Length() * Position.Length()));
if (dot > 0.98)
Up = localUp;
else
Up = new Vector3(0, 0, localUp.Z);
However, this was a bit jumpy and still didn't seem quite right. After some trial and error, along with some extensive research on the web trying to find potential solutions, I remembered how linear interpolation can transition smoothly from one value to another over a period of time. I then moved to using Vector3.Lerp instead:
float dot = Math.Abs(Vector3.Dot(Up, Position) / (Up.Length() * Position.Length()));
Up = Vector3.Lerp(new Vector3(0, 0, localUp.Z), localUp, dot);
This is very smooth, and only causes any roll when I am very near to being axis aligned which isn't enough to be noticeable by the every day user.
The Problem
My camera also has the ability to attach to a point other than 0, 0, 0, and in this case, the up vector for the camera is set to the normalized position of the target. This causes the original issue in the overview when using Vector3.Lerp as above; so, in the case where my camera is attached to a point other than 0, 0, 0 I do the following instead:
Up = Vector3.Lerp(Vector3.Normalize(Target), localUp, dot);
However, even this doesn't work and I have no idea how to get it to do so. I've been working at this problem for a few days now and have made an extensive effort to fix it, and this is a big improvement so far.
What can I do to prevent the violent spinning using Vector3.Lerp when the up isn't equivalent to 0, 0, z?
Imagine a vertical plane that is rotated around the vertical axis by yaw (ϕ):
The camera is only allowed to rotate with the plane or in the plane, its in-plane orientation given by the pitch (θ):
ϕ and θ should be stored and incremented with the input delta. With this setup, the camera will never tilt, and the local up direction can always be computed:
d and u are the local front and up directions respectively, and are always perpendicular (so alignment won't be an issue). The target can of course be taken as the position + d.
But wait, there's a catch.
Suppose if you move your mouse to the right; ϕ increases, and you observe:
If the camera is upright, the view rotates to the right.
If the camera is upside-down, the view rotates to the left.
Ideally this should be consistent regardless of the vertical orientation.
The solution is to flip the sign of increments to ϕ when the camera is upside down. One way would be to scale the increments by cos(θ), which also smoothly reduces the sensitivity as θ approaches 90 / 270 degrees so that there is no sudden change in horizontal rotational direction.
I have a script that just essentially rotates the x and the y axis of a camera.
void Update () {
float xRot = Input.GetAxis("Mouse X");
float yRot = Input.GetAxis("Mouse Y");
Vector3 rotate = new Vector3(xRot, yRot);
transform.Rotate(rotate);
}
It appears as the input from the Mouse X is the actually the Mouse Y and vice versa. I know I can fix the problem just by flipping the xRot and the yRot in the assignment of the Vecort3 variable. So I was wondering if there is a better way to get the x and y axis of the mouse or if I just accidentally modified my project some how. Also would appreciate it to know how to fix the problem.
This is not a problem, just how things are.
Left and right are the horizontal axis. Your first thought would be assign them to the x value. Problem is that the rotation rotates around the given axis and most likely left/right should be rotating the object towards the left or the right.
But to do so, you can think of a pole (like a pole dancer) and you'd be rotating around it. If you are real close to it, it'd be like rotating left-right. But this axis is going up, and it is the up vector.
It means that to rotate left-right, you rotate around the up vector but use the left-right buttons which are the horizontal axis.
Obviously, if you want to rotate so that you can look down-up, you will rotate around the right (x) axis and use the vertical movement.
To conclude, there is no more simple or more logic solution than inverting the input. You could change the input setting so that horizontal is vertical and vice-versa but I would not recommend it.
var pos = Input.mousePosition;
var x = pos.x;
var y = pos.y;
The bottom-left of the screen or window is at (0, 0). The top-right of the screen or window is at (Screen.width, Screen.height).
Actually, i'm programming a little spaceshooter game (2.5D, Topdown View). The player can move along the XZ Axies and rotate the spaceship via right ministick (gamepad) or look to the cursor position (keyboard + mouse).
So, the movement and rotation (Y-Axies, Yaw) are seperated.
The whole thing works fine and looks good - but now i want to do the following:
If the spaceship moves sideways, it should rotate around the X / Pitch axies / lean left and right a bit, dependent on the sideways speed.
So, i have to compute the sideways speed from the following, given input:
Velocity Vector (Movement on X and Z Axies, Y is always '0')
Direction Vector (Rotation on Y Axies, X and Z are always '0')
And with the amount of sideways speed, i could rotate my spaceship around the X axies and multiply the resulting quaternion by the rotation around the y axies.
Anyone who has a solution for this?
Solution: Just "rotate" the velocity vector by the heading of the spaceship and use the "roll/z" axis as the sideways rotation about the X axis (the axis, where your ships nose points towards):
Quaternion Rotation = Quaternion.Euler(0, mHeading.y, 0);
Vector3 RealVeloctiy = Quaternion.Euler(0, -mHeading.y, 0) * Velocity;
float Angle = RealVeloctiy.z * 2.5f;
Rotation = Rotation * Quaternion.Euler(Angle, 0, 0);
A couple of possibilities:
Compare the velocity vector with local left direction of the spaceship (make sure they're in the same coordinate space first). You could use the Vector3.Angle function, or a dot product to do the comparison. Scale the result appropriately, and apply a local rotation around the forward axis.
Take user input directly. If the user is strafing in a direction, apply a roll value. You could use a float between -1 and +1, along with a rate of change. If they're strafing left, move the value towards -1 at that rate, or if they're strafing left, to +1. If neither key is being pressed, move the value back towards 0. (You might like to play around with the Lerp, SmoothStep and SmoothDamp functions too). Scale the value to apply an appropriate rotation about the relevant axis.