Can anyone help me with this please
I want to be able to rotate a 3D object around a stationary 3D object. Well there will be no movement involved as I just want to draw the objects at their locations once the game starts and then they will remain there for the remainder of the game.
Say for instance I have a object X that is stationary in 3D space. I then have 2 other objects, Y1 and Y2. Both of these objects are stationary as well and cant be moved. All 3 objects are on the same x and y axis. Lets say X is at (0,0,0) and Y1 is at (0,0,-50). I want to draw Y2 at a 45 degree angle from Y1 around the Y-axis but keep it the same distance from X.
Can anyone please suggest the best way of doing this please?
I have tried the following but that just rotates the object around its origin. So I guess I have to rotate it around the world origin? How is this done?
Matrix.CreateRotationY(Rotation)
I'm not sure what you want, but this is one method for rotate one object around another:
Vector3 Origin; // Stationary Object
float Yaw, Pitch; // Angles
float Distance;
Vector3 OrbitOffset = Vector3.UnitX * Distance;
// Other approach that consider the initial pos of the object to rotate
// Vector3 OrbitOffset = OrbitPos - Origin;
Matrix Rotation = Matrix.CreateFromYawPitchRoll(Yaw, Pitch, 0);
Vector3.Transform(ref OrbitOffset, ref Rotation, out OrbitOffset);
Vector3 OrbitPos = Origin + OrbitOffset; // Final position of the rotated object
if you dont need rotation about more than 2 angles at once, you can use basic Euler method.
see :
http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
thats a mathematical approach tough... but it works..
Just if you want a rotation around multiple axes, you will have serious problems with gimbal lock
Related
I'm trying to make the camera rotate around an object according to the movement of the mouse, and this is what I've come up with:
void Start()
{
direction = new Vector3(1f,0f,0);
direction.Normalize();
Debug.Log(direction);
mousePosCurr = Input.mousePosition;
}
void Update()
{
mousePosPrev = mousePosCurr;
mousePosCurr = Input.mousePosition;
mouseVector = (mousePosCurr - mousePosPrev);
mouseVector = mouseVector * sensitivity;
direction = Quaternion.Euler(mouseVector.y, mouseVector.x, 0) * direction;
direction.Normalize();
Debug.Log(direction);
this.transform.position = (target.position + tOffset + (direction * distance));
transform.LookAt(target.position + tOffset, Vector3.up);
}
Now, I'm sure that there are at least a million problems with this code, however the main one I'm facing right now is that the x rotation does not work correctly, unless the y rotation is in a specific direction.
What's happening is basically that the more I rotate in the y axis the more "inprecise" the x movement becomes. So for example, when the camera is south of the object I'm rotating it around, the x rotation works exactly as it should, you move the mouse up, and the camera points up and viceversa, but when it's west of it the movement of the mouse required for the vertical rotation is no longer vertical, but diagonal, and when it's north of the object the movement is inverted: moving the mouse up makes the camera point down and viceversa.
This seems most likely caused by the fact that regardless of the horizontal rotation of the direction vector, I'm still rotating along the x axis in the same direction, as if the camera was south of the object.
However, even having (hopefully) identified the problem, I'm still clueless as to how to solve it, so I'm asking for help here.
Note: I just noticed that I probably used the term "rotation" wrong in this post. When I write "rotation of the camera", I'm actually referring to the rotation of the "direction" vector.
alright so I am not the best in Unity so this might be completely useless but when I try to rotate my camera around an object I create an empty game Object and make the camera a child of it, like this
so that I can just just rotate the Game Object to rotate the camera around a fixed point maybe your code will work
When I try to rotate an object towards a point, it starts spinning, but I want it to be able to freely spin, while still rotating towards that point. I can't just clamp the y rotation, because obviously it's already rotating towards a point and setting the absolute y rotation while doing so and you can't access an object's relative angles in Unity. As seen here, the blue gizmo always faces the top of the sphere (the centre of the sphere is the point I'm rotating towards). I want it to be able to move freely.
Here's my rotation code:
Quaternion dir = Quaternion.LookRotation((target - transform.position).normalized) * Quaternion.Euler(new Vector3(-90, 0, 0));
transform.rotation = Quaternion.Slerp(transform.rotation, dir, smooth);
Does anyone know how to fix this?
I feel like this is a solvable problem but I am just to stupid to solve it.
I want to able to move a player around a cube in third person in a 3D game. Before I worry about the corners where 3 edges of the cube meet I would first like to be able to move around two edges. If I use the LookAt method while jumping around a corner some problems occur with the vertical rotation of the player. So if he enters the trigger of the edge he turns around 180 degree somehow. That is why I am searching for a different solution.
(Green rectangle is the player. The dotted area is a trigger.)
So what I am given on the entry of the trigger is the edge position P2 and obviously the player position P3. The player should be able to stop the velocity while being mid air, so he could just fall down to the edge thanks to the gravity. That means that I can not just lerp it from the entry point to some exit point. The entry and exit points are dynamic.
What I already calculated is the distance from the player to the edge. Therefore I could tell if the player is closer to the right surface or the left surface judging by whether X or Y is higher.
But if the player enter on a higher position the numbers are also higher.
I am very confused about how to solve this. I need to lerp rotate the player around the corner P2 as long as he is within the two dotted lines.
Here's something to get you started. This will rotate your player so that their down is pointing at the edge, and their forward vector tries to remain unchanged as much as possible. This will mean that moving in playerTransform.forward will move them where they are facing but will rotate them so that as they move around the edge, they will rotate around it.
transform playerTransform;
Vector3 edgeWorldDirection;
Vector3 edgeWorldPosition;
Vector3 playerWorldPosition;
// Determine up direction
Vector3 player2Edge = edgeWorldPosition - playerWorldPosition;
Vector3 playerUpDirection = (
Vector3.Dot(player2Edge, edgeWorldDirection) * edgeWorldDirection
- player2Edge).normalized;
// rotate player to align local up with playerUpDirection and forward with
// previous forward as much as possible.
Vector3 playerRightDirection = Vector3.Cross(playerUpDirection, playerTransform.forward);
// handle player looking "up"
if (playerRightDirection == Vector3.zero) playerRightDirection = player.Transform.right;
Vector3 playerForwardDirection = Vector3.Cross(playerRightDirection, playerUpDirection);
playerTransform.rotation = Quaternion.LookRotation(playerForwardDirection, playerUpDirection);
For corners it's actually easier because your up is based on the location of the corner, you don't have to calculate the closest point on a line.
transform playerTransform;
Vector3 cornerWorldPosition;
Vector3 playerWorldPosition;
// Determine up direction
Vector3 playerUpDirection = (playerWorldPosition - cornerWorldPosition).normalized;
// rotate player to align local up with playerUpDirection and forward with
// previous forward as much as possible. Same logic here as previously.
Vector3 playerRightDirection = Vector3.Cross(playerUpDirection, playerTransform.forward);
// handle player looking "up"
if (playerRightDirection == Vector3.zero) playerRightDirection = player.Transform.right;
Vector3 playerForwardDirection = Vector3.Cross(playerRightDirection, playerUpDirection);
playerTransform.rotation = Quaternion.LookRotation(playerForwardDirection, playerUpDirection);
Depending on how you're handling movement & player orientation, you may not actually want to rotate the player's transform, but with the results of Quaternion.LookRotation(...) you can multiply the local direction the player tries to go by that rotation to get the world direction that would correspond to.:
Vector3 localDesiredMove;
Quaternion boxOrientationQuat = Quaternion.LookRotation(
playerForwardDirection,
playerUpDirection);
Vector3 worldBoxOrientedMove = boxOrientationQuat * localDesiredMove;
I tried to make a first person controller in Unity so that I know every single detail of it. I made the movement, but when I created the camera rotation i simply got stuck. Ok, it worked on the x axis, on the y axis, but why does the z axis also change?
void Update () {
transform.position = Character.transform.position + offset;
float h = Input.GetAxis("Mouse X") * horizontalSpeed;
float v = Input.GetAxis("Mouse Y") * verticalSpeed;
transform.Rotate(h, v, 0, Space.World);
}
When working with rotations and euler angles you have to understand that there are different coordinate spaces, like the object's local space and a world space. the x,y,z directions in world space will always look at the same direction, whereas the local space is the coordinate space of the local object (for example your camera). Thats why I would recommend you to rotate vertically in local space and horizontally in world space.
transform.Rotate(0,h,0,Space.World);
transform.Rotate(-v, 0, 0, Space.Self);
Rotating your camera vertical in local space will change the object's local up axis (y-axis). this is why then rotating around that axis will give you your unwanted result. Just select the gameobject in your Scene view and observe it's local coordinate system while rotating and you might be able to better visually understand.
To also give you a simple,fun reallife example to observe yourself, sit upright on your office chair and look straight ahead and rotate on your chair. If you now look a little upwards or downwards and rotate your head instead you will notice a difference in rotation between rotating your neck and rotating on your chair, which should always have the same up-axis, which is different from the local up axis of your neck.
ps.: there are already many solutions to implement a first person camera, like in Unity's own standard assets, or SmoothMouseLook
Looking at tutorials, following them and trying to understand them might bring you further than trying to figure it out on your own.
Euler angles are weird. When you rotate with euler angles, the rotations stack, and a rotation around one axis changes the other axis of rotation. It's best not to "add" euler angles (essentially what transform.Rotate() is doing) and best to work with them in absolute terms. In this case, your code should keep the "z axis" at 0 if you do the following:
void Update () {
transform.position = Character.transform.position + offset;
float h = Input.GetAxis("Mouse X") * horizontalSpeed;
float v = Input.GetAxis("Mouse Y") * verticalSpeed;
# Get the current euler angle in absolute terms
Vector3 eulers = Character.transform.localEulerAngles;
# now modify that euler angle, creating a new absolute euler angle
eulers.x += h;
eulers.y += v;
eulers.z = 0;
# and now assign the new euler angle back to the transform, overwriting the old value
Character.transform.localEulerAngles = eulers;
}
In general I'd advise against using Transform.Rotate() for... most everything. I would also advise using quaternions wherever you're able. You don't need a complete understanding of quaternions for them to be very powerful.
I have an object with a Vector2 Position, and a cursor with Vector2 Position.
When I hold a certain key, I want the object to circle around the object, but I'm having trouble calculating the correct coordinates.
I've managed to make the object circle around the cursor (but it's not going in a perfect circle, but more of a spiral) with this code:
Vector2 diff= Vector2.Normalize(cursor.Location - this.Location);
float angle = (float)Math.Atan2(diff.Y, diff.X) + (float)(90 * (Math.PI / 180));
this.Position += new Vector2((float)(speed * Math.Cos(angle)), (float)(speed* Math.Sin(angle)));
I calculate the angle between cursor's and object's locations, and add 90° (in radians) to that value, which, by my logic, should make the object travel in a perfect circle. However, the distance between the cursor and the object quickly spreads.
What am I calculating wrong here?
Usually when you want something to circle around a point, you define the distance to an amount and you incrementally change the angle in your Update method. THEN in your draw method you can draw it where you should by calculating the position from the cursor.Location, the distance from the cursor and the desired distance.
In most situations like these you want your orbiter to have the same loation like your cursor, so calculating the new position in the Draw method works best, given that these calculations are cheap and super fast (you generally do not want to hog down your Draw method).
I am not able to check it right now, but what you should be doing is something in these lines:
Given that your object should rotate D distance away from your cursor with an angular velocity of AngularVelocity (per second), then when this initially happens, set a variable angle to zero. Then in your update do:
angle += (gameTime.ElapsedGameTime.TotalSeconds * AngularVelocity)
and in your Draw method do:
var displacedPosition = new Vector2(D * Math.Sin(angle), D * Math.Cos(angle));
and render your orbiter using the displacedPosition instead of the normal position if it is currently orbiting.