how to limit the rotation of a game object in unity3d - unity3d

I am making a game where there is a tank that shoots some objects.
I want to rotate the gun of the tank in between the llimits of -90 to 90 degrees in "X".
I used transform.rotate but it rotates the gun with some float values (0.0 to 1.0) and the rotation I see on the inspector is something different. How to solve this issue?

Use below code from Mathf class
static float Clamp(float value, float min, float max);
e.g.
var angle = Mathf.Clamp(angle, 90, 270);
Quaternion target = Quaternion.Euler(0, 0, angle); // any value as you see fit
transform.rotation = target;

I found the answer I used eularAngles to limit the rotations as follows
if((gun.eulerAngles.z<90)||(gun.eulerAngles.z>270))
{
gun.Rotate(0,0,turnAngle);
}

Related

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;
}

Object does not rotate in the correct direction from Atan2 to Quaternion

I am trying to rotate an object on its z axis, given a point I calculated at an angle with Atan2 function. Then I create a Quaternion to enter it in the rotation of the object. However, it does not rotate in the supposedly correct direction. If I diagram the angles given by the Atan2 functions, I visualize a clockwise system of angles, but if I diagram the angles that should be so that my object is rendered in the correct direction, I visualize an anti-clockwise system. The solutions creating a dictionary with the values received by the Atan2 function as keys and their values are the angles with which the object will rotate the correct direction. But I still don't understand what is happening. I hope someone can help me understand it because there is no worse solution than the one that solves but without knowing what is happening.
public class ArrowMovement : MonoBehaviour
{
public Vector2Variable currentPlayerDirection;
public Vector3Variable currentPlayerPosition;
public InputAxis inputAxis;
private float anglePassed;
private Dictionary<float, float> realAngles = new Dictionary<float, float>();
void Awake()
{
realAngles.Add(-135, -135);
realAngles.Add(-90, 180);
realAngles.Add(-45, 135);
realAngles.Add(0, 90);
realAngles.Add(45, 45);
realAngles.Add(90, 0);
realAngles.Add(135, -45);
realAngles.Add(180, -90);
}
void Update()
{
Vector3 offsetVector = new Vector3(0.2f, 0.05f, 0);
transform.position = currentPlayerPosition.Value;
// Rotation
float angle = Mathf.Atan2(inputAxis.horizontal, inputAxis.verticall) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(0, 0, realAngles[angle]);
transform.rotation = rotation;
}
}
First of all, you should know what inputAxis is.
I can guess from your diagram that you expect that for inputAxis.verticall == 0 the angle must be 0. Let's look at Mathf.Athan2(y,x) - it is equivalent to arctan(y/x), so result will be zero only when y is zero. But, in your code Mathf.Atan2(inputAxis.horizontal, inputAxis.verticall) will give 0 when inputAxis.horizontal == 0 - it is vertical direction (your first diagram).
Second issue - wrong rotation direction. This can happen when one of the input axes is inverted. Probably, inputAxis is measured in a different coordinate system relative to your object, i.e. Z of your object is -Z of your inputAxis. Anyway, inputAxis.verticall can be inverted
float angle = Mathf.Atan2(inputAxis.horizontal, -inputAxis.verticall) * Mathf.Rad2Deg;
Also, you should avoid solving a simple geometric problem by "creating a dictionary" or anything like that. Even if you don't know how inputAxis works and result is wrong - make two step to fix it: 1. fix rotation direction - just invert the angle Quaternion.Euler(0, 0, -angle); 2. fix the zero position - add some static rotation. It is 90 deg in your case Quaternion.Euler(0, 0, 90 - angle). And it is the second way to solve the problem.
Creating a dictionary is not the best way because it does not take into account the angles between the ones you set so to convert from one diagram to the other I would create a function that looks like:
float ChangeAngleDiagram(float angle) {
return -(angle + 90f)+180;
}

I want a camera that displays a wider picture when the player is facing that direction unity2D

hi everyone I make 2D platformer games and the camera I use now always makes the player in the middle. I want my camera to show the front of the player wider.
public Transform target;
Vector3 velocity = Vector3.zero;
public float smoothTime = 0.3f;
void FixedUpdate()
{
Vector3 targetPos = target.position;
targetPos.z = transform.position.z;
transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref velocity, smoothTime);
}
Just move the targetPos in the according direction e.g. using
// Adjust this via the inspector
public float Offset = 1;
// Depending on your setup you might have to change "forward" to "right" or "up"
Vector3 targetPos = target.position + target.forward * Offset;
targetPos.z = transform.position.z;
Create a float variable public float offset = 10.0f. Subtract offset value from your targetPos.z as such: targetPos.z=transform.position.z - offset;
Note that the value of offset is something you have to experiment with to get right. Advisably, make the offset variable public, that way you can play the game in unity editor, play with the variable till its okay, copy the value of offset, stop the game the change the value of offset in your code to the new value. Goodluck
If you're using an Orthographic camera projection, you should change the viewport Size of the Camera.
You can update this value by code : Camera.main.orthographicSize = myNewSize;
Put a smaller value to zoom in, and a larger value to zoom out.
The value represent the half-screen projection on the vertical axis.
It's mean that a value of 0.5 will make a 1m cube fit the screen.

Unity2D: Rotate object keeping looking at front

I am trying to archive without success a z-axis rotation movement around a moving object keeping always "looking at front". So it should looks like this:
The closest I got was with:
transform.RotateAround(targetPosition, Vector3.forward, moveSpeed);
But it does not keeps looking "at front".
Could someone give me a hand with this?
Thank you in advance.
Best regards.
If your object ("Lightning Bolt") has no world rotation, i.e. aligned with the world axis as your example image seems to suggest, then the easiest is to simply set the world rotation to the Quaternion Identity:
transform.rotation = Quaternion.identity;
Note that the image wont rotate if its parent object rotates. It will essentially "Billboard" your lightning object. If you want to your lightning bolt to be aligned with a parent object, then try something like:
transform.rotation = transform.parent.rotation;
Fitst store the current rotation, then rotate around point, lastly apply the previous rotation.
var rot = transform.rotation;
transform.RotateAround(targetPosition, Vector3.forward, moveSpeed);
transform.rotation = rot;
A simple solution would just manipulate actual coordinates and ignore rotation ^^ If an object moves and you want it to keep rotating around it, just make it a child object.
This is a 3d solution where we rotate around Y:
void Start() { angle = 0.0f }
void Update() {
angle += speed * Time.deltaTime; //Your starting angle that will be modified every frame
CheckAngle(ref angle);
float x = Mathf.Cos(angle * Mathf.Deg2Rad) * Radius;
float z = Mathf.Sin(angle * Mathf.Deg2Rad) * Radius;
}
static void CheckAngle(ref float Angle) //It should probably return a value by it's name here tho not ref, not sure which is the correct way of doing this
{
if (Angle > 360) //You don't want your angle to go past the boundaries of an INT
Angle = 0;
}

Topdown camera focus with angle

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().