I am starting out to create a minigolf game in Unity. I want to aim by draggin the screen with my mouse which rotates the camera around the ball. Basically I want to draw an aim line (line renderer or any other good method) from the ball to where the camera is pointing. Right now I just draw the line I want from beginning, but in the end I want it to rotate with the camera like the red line in picture below.
The code for rotating the camera is working great, where previousCameraPosition is set when I click the mouse and Rotate() is called when mouse button is being held down:
private void Rotate()
{
// Get the movement vector
Vector3 cameraMoveDirection = previousCameraPosition - mainCamera.ScreenToViewportPoint(Input.mousePosition);
// Rotate around the ball
mainCamera.transform.position = ballObject.transform.position;
// Make the rotations
mainCamera.transform.Rotate(new Vector3(1, 0, 0), cameraMoveDirection.y * 360);
mainCamera.transform.Rotate(new Vector3(0, 1, 0), -cameraMoveDirection.x * 360, Space.World);
// Set the camera a certain amount away from the ball
mainCamera.transform.Translate(new Vector3(0, 0, -ballObject.transform.position.z*2.5f));
// Update the previousCameraPosition during the movement
previousCameraPosition = mainCamera.ScreenToViewportPoint(Input.mousePosition);
}
I tried to create a helper object which was set to rotate exactly like the camera which made the line exactly like I wanted it, except it was backwards (180 degrees wrong, facing into the camera instead of away) and it was 1 unit long since it was normalized. I am stuck on this for far too long now, any help or guidance would be very appreciated.
First you can simply use the camera's forward vector without having to deal with any Quaternion rotation at all:
var forward = Camera.main.transform.forward;
Then what you actually seem to want is not exactly this direction but rather map it onto a flat XZ plane:
var actualForward = Vector3.ProjectOnPlane(forward, Vector3.up).Normalized;
then finally you can use this direction to draw your line e.g. between the points
var startPoint = ball.position;
var endpoint = startPoint + actualForward * lineLength;
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?
This is a school project. I have a big cube which is like a planet. I have a small cube that can move on every side of the cube planet. The player moves forward automatically on its local z axis and I rotate it by 90 or -90 degrees to move left or right- but the player can control it like it's an up-down-left-right movement (made a script so they don't have to rotate the cube with 2 keys). It's like a Tron game so if I press the up key, I can't press down immediately because I leave a trail so I have to press the left or right keys. I have a problem with my camera movement. The camera follows the little cube from above, but I want it to lean a little when the little cube player gets close to the edge of a side so it lets me see the other side - where I'm planning to go.
I have a script where I use the center of the cube planet and the player's center as the direction vector and multiply it with the camera-player distance.
Vector3 direction = (target.position - center.position).normalized;
transform.position = target.position + direction * distance;
Then I point my camera's forward vector to the player cube's direction. I tried two codes but none of them worked perfectly. First I tried to rotate the camera with:
transform.rotation = Quaternion.LookRotation(-direction);
Shown in video. The problem with this is that since I don't tell the program the Up and Right vectors (I think), it sets them for itself to some random numbers so the camera sometimes do its own thing like it does a pirouette.
Next I tried this:
Quaternion rot = Quaternion.FromToRotation(transform.forward, -direction);
transform.Rotate(rot.eulerAngles, Space.World);
Shown in video. It's almost good but as the little cube moves, the camera starts steering slightly in the beginning and it gets worse and worse.
Do you have any ideas how can I make it work? I hope you understand what I would like to achieve. I'm trying to set the camera as to always show that when I press Up, my cube moves upward, when I press Right my cube always goes right etc. and when I reach the edge of my side the camera leans a bit towards the side I'm moving to.
Use dot product to find which orthogonal direction of your cube is closest to the camera's current up.
Vector3 closestToUp;
float greatestDot = 0f;
foreach (Vector3 dir in new Vector3[]{
target.forward, target.right, -target.forward, -target.right})
{
float curDot = Vector3.Dot(dir,transform.up);
if (curDot > greatestDot)
{
greatestDot = curDot;
closestToUp = dir;
}
}
Than, use that direction as the second parameter of Quaternion.LookRotation. This will keep its local up direction as aligned with the cube's "top" as possible given whatever new forward direction:
transform.rotation = Quaternion.LookRotation(-direction, closestToUp);
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;
while following some guides to make an object move, I have this issue.
So, all objects on the scene are 0, 0, 0, on rotation except for the camera. The camera, then is 0, 180, 0. The script says - for a object to move to the left
:
void Update () {
transform.Translate(Vector3.left * (ScrollSpeed * Time.deltaTime));//access transform component and moves it left by 20 times the frame rate
}
So technically it moves left, but the camera perspective is at 180 degrees to look at the game from the front. So is my only solution to rotate the platform on Y to match the perspective to make it in reverse so when working on things I dont have to keep using negative numbers to do the opposite of the actual scene?
Instead of using Vector3 static variables which are define in the world space, you can use the transform of the Camera, so the moving directions are depending on the Camera. That is to say in your case:
void Update () {
transform.Translate(
-Camera.main.transform.right * (ScrollSpeed * Time.deltaTime));
}
Notice the - in front of Camera.main.transform.right, the opposite of the right direction is the left direction ;-)
If you have several Cameras in your scene, use a reference to the Camera you want instead of Camera.main
I found the issue.
So the original scene itself was 0, 0, 0, but I needed to play the scene -180 on the Y axis and face the camera at 0, 0, 0, this way the only thing rotated is the design of the background.