Topdown camera focus with angle - unity3d

I'm making a topdown game with the camera at 40 degree angle. What I want to do is when i click an gameobject, It will move the camera and position the object at the left side from the center of the camera view regardless of its rotation. So that I can place a menu at the right side. How do I get the offset of the angled camera so that the object is in the middle left side of the camera view?
Right now i use lerp but it overshoots the target because of the cameras angle. Sorry for the noob question I'm new to unity3d.
transform.position = Vector3.Lerp(transform.position, new Vector3(target.transform.position.x, transform.position.y, target.transform.position.z), 0.1f);

First of all you should start by finding point that your camera will move/lerp to.
In your case in can be simplified to 2D-Space:
It shouldnt be tough to find that one.
Use transform.forward of camera to get vector (Vector3 cameraDir) of direction your camera is looking at
Rotate by horizontal fov / 4 around y axis:
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov/4f, Vector3.up) * cameraDir;
-cameraDirRotated will be vector from Cube To point P you're looking for, u can also scale it:
Vector3 PtoMoveTo = cube.transform.position - cameraDirRotated.normalized * 5f;
Full:
Vector3 FindCameraTarget(Transform targetObj, float hFov)
{
Vector3 cameraDir = transform.forward;
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov / 4f, Vector3.up) * cameraDir;
Vector3 target = targetObj.transform.position - cameraDirRotated.normalized * 5f;
return target;
}
Then:
transform.position = Vector3.Lerp(transform.position, FindCameraTarget(target, 90f) , 2f * Time.deltaTime);
For performance u can save that target vector once if Cube is not moving. Search web how to precisely count horizontal fov. Multiply speed by Time.timeDelta if u lerp in Update().

Related

Unity 2D, rotate Vector2 to NEW Vector2 in animation

My game is 2D from a top down-ish perspective, my character movement vector2 being fed into the animator blend to determine which direction my sprite faces: (example sprite)
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
anim.SetFloat("hor", movement.x);
anim.SetFloat("ver", movement.y);
However, I would like my sprite to rotate to it's new target vector2 rather than instantly switch to it. So if I was facing right, and I pushed left, the movement vector2 would travel over time to a new movementTarget vector2, the sprite changing from facing right, to up, to left.
I cannot figure or find a way to do this and have been on it many hours. I've tried things like Vector3.RotateTowards and angles, but each approach I can't get what I'm looking for as this aspect of math just confuses me.
Could someone point me in the right direction?
Vector2 targetMovement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (targetMovement != movement) coroutine?????
I don't want to rotate the sprite image, or the object transform, just the movement Vector2 variable over time. So if I am facing right (1,0) and press left, I want the Vector to travel through (0,1 - up) then finally to (-1,0 - left) but gradually.
Managed to do it like this. Unsure if best way?
float currAngle, targAngle;
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (movement != Vector2.zero)
targAngle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;
if (Mathf.Abs(currAngle - targAngle) > 1f) {
currAngle = Mathf.LerpAngle(currAngle, targAngle, 10f * Time.deltaTime);
Vector2 newVec = new Vector2(Mathf.Cos(currAngle * Mathf.Deg2Rad),
Mathf.Sin(currAngle * Mathf.Deg2Rad));
anim.SetFloat("hor", newVec.x);
anim.SetFloat("ver", newVec.y);
}

Unity - rotated objects flips in a strange way when using Quaternions

I'm trying to create a system in VR in which an object rotation follows the rotation of the player's hand. Unfortunately, when the hand rotates at a high angle, the rotated object flips in a strange way as if it had a problem with the rotation change from 360 degrees to 0. I tried many ways to solve this problem, but each one that worked did not allow me to change "sensitivity" on the basis of:
1 - target is rotating 1: 1 ratio with hand
2 - target is rotating twice as much as hand
etc.
// In FixedUpdate
Quaternion deltaRotation = Quaternion.Inverse(target.rotation) * hand.rotation;
deltaRotation.ToAngleAxis(out float angle, out Vector3 axis);
target.rotation *= Quaternion.AngleAxis(angle * sensitivity, axis);
Any help would be appreciated!
So the problem is in
Quaternion deltaRotation = Quaternion.Inverse(target.rotation) * hand.rotation;
if the sensitivity is != 1 these objects rotations get desynchronized so the deltaRotation will not give you the value you expect. You probably wanted to check how much hand rotated since last frame, like that:
Quaternion _lastFrameRotation;
void Awake()
{
_lastFrameRotation = transform.rotation;
}
private void FixedUpdate()
{
Quaternion deltaRotation = Quaternion.Inverse(_lastFrameRotation) * transform.rotation;
deltaRotation.ToAngleAxis( out float angle, out Vector3 axis );
target.rotation *= Quaternion.AngleAxis( angle * sensitivity, axis );
_lastFrameRotation = transform.rotation;
}

How do I get my character to move correctly using New Input System & Rigid Body physics? Unity3D

I have been experimenting with trying to recreate a 3rd person character controller from a Brackeys tutorial, but using the new input system and rigid body physics.
The rotation works properly, but moving forward or back moves me forward compared to the camera, and moving left or right moves me backward.
The desired effect is changing the input should change my rotation to match the input direction relative to the camera and then move in the direction the player model is facing
Here is where I'm at:
private Vector3 GetMoveInput()
{
return new Vector3(_input.MoveInput.x, 0f, _input.MoveInput.y); //convert input Vector2 into a Vector3
}
private void PlayerMove()
{
if (_playerMoveInput.magnitude > 0.01f){ //only update rotation if player is moving
float targetAngle = Mathf.Atan2(_playerMoveInput.x, _playerMoveInput.z) * Mathf.Rad2Deg + _mainCamera.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
//down here is where the problem lies I believe
_playerMoveInput = new Vector3(_playerMoveInput.x * _movementMultiplier * _rigidBody.mass,
_playerMoveInput.y,
_playerMoveInput.z * _movementMultiplier * _rigidBody.mass);
_rigidBody.AddRelativeForce(_playerMoveInput, ForceMode.Force);
}
}
I have tried setting y and z to 0f, multiplying by transform.forward, setting _playerMoveInput to transform.forward, and Quaternion.Euler(0f, angle, 0f) * transform.forward but no positive results.

Unity 3D Ball Follow the finger

I am trying to create a 3d game like ketchapp ball race, in which the cube slides along a road, and the left right movement is controlled using touch
The problem I am facing is that the touch senstivity seems to react different on different devices, due to which I am not able to calculate the left-right displacement for all devices.
This is how I am calculating the left-right displacement of the cube:
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition ;
transform.Translate(touchDeltaPosition.x * .1f * Time.deltaTime, 0, 0);
However this is not working properly all device . Any help will be highly appreciated
See this answer: https://stackoverflow.com/a/25740565/10063126
Basically, ScreenToWorldPoint was used.
World position is computed; not screen touch position.
But you have to manually solve for delta position.
Example:
Vector3 currPos = Input.mousePosition;
Vector3 startPos = Camera.main.ScreenToWorldPoint(currPos);
Vector3 endPos = Camera.main.ScreenToWorldPoint(prevPos);
Vector3 deltaPos = endPos - startPos;
transform.Translate(deltaPos.x * sensitivity * Time.deltaTime, 0, 0);
prevPos = currPos;
How about using 2 buttons on your screen one for left control and one for right control and then when the left button is pressed you can give a value to go left and same for right button. This way your ball's movement will be independent from the touched position's X value.

How to rotate the object in the direction it is travelling based on only accelerometer tilt in Unity?

I wish to rotate my object in the direction it is travelling. How can I calculate the Vector difference from the previous frame and current frame and hence give a direction to aim towards to make it rotate in the direction it is travelling. The following is the code being used to control the object by accelerometer.
Vector3 getAccelerometer(Vector3 accelerator){
Vector3 accel = this.calibrationMatrix.MultiplyVector(accelerator);
return accel;
}
void Start(){
calibrateAccelerometer();
}
void Update(){
Vector3 dir = getAccelerometer(Input.acceleration);
if (dir.sqrMagnitude > 1)
dir.Normalize();
transform.Translate(dir * speed * Time.deltaTime);
}