the GameObject rotates incorrectly on the z-axis - unity3d

there is a circle, it needs to be rotated by pressing the button, with a certain speed along the z axis, and when it turns 90, the rotation will stop, but for some reason the rotation is not working properly
public GameObject Circle;
private bool RotationActive;
//rotation value at which the circle stops rotation
private float RotatePost;
private float RotationSpeed;
private float CircleRotateZ;
void Start()
{
RotationActive = false;
RotationSpeed = 0.5f;
RotatePost = 90;
}
//function is bound to a button
public void RotateActive(){
RotationActive = true;
}
void FixedUpdate()
{
if (RotationActive == true)
{
CircleRotateZ = Circle.transform.rotation.z;
//if the circle along the z axis is rotated more than Rotation Post...
if (CircleRotateZ >= RotatePost )
{
RotatePost = CircleRotateZ + 90;
RotationActive = false;
}
//assignment of a new coordinate
Circle.transform.Rotate(new Vector3(0,0,RotationSpeed + CircleRotateZ));
}
}

You are trying to grab the rotation from the Quaternion which is not the angle of the object. Instead you should use:
CircleRotateZ = Circle.transform.eulerAngles.z;
Also the way you are currently rotating will make it speed up over time. The Rotate functions rotates the object by the amount, not to the amount given, so if you only want to rotate by the rotation speed you should use:
Circle.transform.Rotate(new Vector3(0, 0, RotationSpeed));

What do you mean by not working properly. You mean it doesn't move at all? If it doesn't move at all, check if you dragged the circle game object to the game object field in the Inspector. One more thing, why didn't you call the 'RotateActive' function?

Related

Canvas rotating when I change it to worldSpace, Unity

I've got a canvas that changes from Overlay to worldSpace when an event occurs, but when it changes to Overlay from worldSpace, the rotation of the canvas is changed, which I don't want it to be.
Images:
As you can see in the order that the images are, it starts with no rotation in worldSpace, then the event occurs changes it to overlay and the rotation is now 140, after the event and I'm back in worldSpace, it is still 140 degrees.
I don't know what is wrong with this. Please help if you can
This happens because, internally, the Canvas is being transformed into camera space when set to Overlay. That's how it renders. Your solution would be to cache the transform before changing the Render Mode.
Something like this, given a component:
using UnityEngine;
[RequireComponent(typeof(Canvas))]
public class CanvasRenderModeSwitcher : MonoBehaviour
{
private Canvas canvas;
private Vector3 position;
private Vector3 scale;
private Quaternion rotation;
private void OnEnable()
{
canvas = GetComponent<Canvas>();
}
public void SetRenderMode(RenderMode renderMode)
{
if (renderMode == RenderMode.WorldSpace)
{
// Set the render mode before values are reset.
canvas.renderMode = renderMode;
// Restore the values.
transform.position = position;
transform.rotation = rotation;
transform.localScale = scale;
}
else
{
// Cache the values.
position = transform.position;
rotation = transform.rotation;
scale = transform.localScale;
// Set the render mode after values are cached.
canvas.renderMode = renderMode;
}
}
}

How to make limited camera movement in Unity C#

I am making a FNAF fan game using Unity, and I need limited camera movement, like shown in this video. I've been trying to figure this out but I found no tutorials nor any answers. If you could link a script for this I would be very greatful!
https://vimeo.com/710535461
Attach this code to the camera and you can limit the camera movement by setting two angles in the inspector. Remember that this code limits localEulerAngles values and always must set the camera rotation to zero, To adjust its rotation, place the camera as child of an empty object and then rotate the parent.
public class LimitedCamera : MonoBehaviour
{
public float LimitAngleX = 10f;
public float LimitAngleY = 10f;
private float AngleX;
private float AngleY;
public void Update()
{
var angles = transform.localEulerAngles;
var xAxis = Input.GetAxis("Mouse X");
var yAxis = Input.GetAxis("Mouse Y");
AngleX = Mathf.Clamp (AngleX-yAxis, -LimitAngleX, LimitAngleX);
AngleY = Mathf.Clamp (AngleY+xAxis, -LimitAngleY, LimitAngleY);
angles.x = AngleX;
angles.y = AngleY;
transform.localRotation = Quaternion.Euler (angles);
transform.localEulerAngles = angles;
}
}

How can I stop getting mouse position of UI Elements in Unity2D?

I'm making a mobile game where there is a simple circle with a handle attached to it, it can be controlled and can be rotated with mouse position, I'm using below code for handle control.
public class Controller : MonoBehaviour
{
private float m_force = 0.04f;
// amount of force for the player (circle and handle both)
public GameObject firePoint; // It is the tip of the handle which will shoot bullets
public float senstivity = 1f;
// senstivity control
public void ControlSenstivity(float index)
{
senstivity = index;
}
void Update()
{
//Get the Screen positions of the object
Vector2 positionOnScreen = Camera.main.WorldToViewportPoint(transform.position) ;
//Get the Screen position of the mouse
Vector2 mouseOnScreen = Camera.main.ScreenToViewportPoint(Input.mousePosition) ;
//Get the angle between the two points
float angle = AngleBetweenTwoPoints(positionOnScreen, mouseOnScreen) ;
// it will control the rotation of player (circle and handle both)
transform.rotation = Quaternion.Euler(new Vector3(0f, 0f, angle) * senstivity);
}
float AngleBetweenTwoPoints(Vector3 a, Vector3 b)
{
return Mathf.Atan2(a.y - b.y, a.x - b.x) * Mathf.Rad2Deg ;
}
// Below function for adding force to the player (both the circle and the handle), this function I added for mobile input whenever the button is pressed
public void AddForce()
{
transform.Translate(-firePoint.transform.localPosition.x, 0, 0 * m_force);
}
}
In this mobile game the user can rotate the player by dragging on the screen and can move the player by exerting force in the opposite direction of fire point whenever the add force button is pressed but the problem is that whenever I press the button the player takes Input.mousePosition of that button position and get rotated towards the button, that's why it will always move in one direction that is opposite of button. I wanted to know what can I do to not get Input.mousePosition of button which is in the canvas and can originally get position only of camera space. Any response will be appreciated, Thanks in advance!
You can use EventSystem.IsPointerOverGameObject. This method will check if your pointer(mouse/joystick) is on any of the UI elements.
Add if condition before getting mouse position.
// This will ignore all UI game objects
if (!EventSystem.current.IsPointerOverGameObject())
{
//Get the Screen positions of the object
Vector2 positionOnScreen = Camera.main.WorldToViewportPoint(transform.position);
}

I can't make a smooth rotation angle when pressing the button

public float tilt =-5f;
public float horizontal;
public float vertical;
Rigidbody player;
void Start()
{
player = GetComponent<Rigidbody>();
}
void Update()
{
player.velocity = new Vector3(horizontal, vertical, 7f);
var clamX = Mathf.Clamp(player.position.x, xmin, xmax);
var clamY = Mathf.Clamp(player.position.y, ymin, ymax);
player.position = new Vector3(clamX, clamY, player.position.z);
player.rotation = Quaternion.Euler(vertical*tilt,0, horizontal * tilt);
}
//turn on the left
public void Onleft()
{
horizontal = -7f;
}
//turn on the right
public void OnRigth()
{
horizontal = 7f;
}
public void Up()
{
horizontal = 0f;
}
// I added an event trigger on my buttons, and ofcourse added some function to this event: OnLeft(),OnRight(), but after added buttons the angle of the ship's turn became very fast, how to fix it so that the angle of rotation of the ship, when pressing the button to the left or right, was little bit smooth?
Well, there is a difference between smooth and slower.
To achieve an slower rotation, simply multiply your rotation value for another value.
rotationValue = 10;
speed = 1/2;
//newRotationValue
rotationValue *= speed; //5;
But if you want to smooth your movement transitions/rotations, I highly recommend you to use Lerp, more concretly as you are using rotations, Quaternion.Lerp .
Lerp will make your rotations to linearly interpolates between two points (your start rotation and your final rotation) and normalize the result, so it will seem more "smooth".

Object X pos is drastically changing after screen shake ends

I'm using the code below to move my player, named balloon, left and right on the x axis by calculating the difference between where you first touched (or clicked) and where you're currently touching, using ScreenToWorldPoint.
void Update()
{
if (gameStarted)
if (Input.GetMouseButtonDown(0))
{
firstTouch = Camera.main.ScreenToWorldPoint(Input.mousePosition);
startPos = balloon.position;
}
if (Input.GetMouseButton(0))
CheckTouchPosition();
}
}
void CheckTouchPosition()
{
Vector2 currentTouch = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float horizontalDif = currentTouch.x - firstTouch.x;
balloon.position = new Vector2(startPos.x + horizontalDif * 1.2f, balloon.position.y);
}
This works normally except after I run into an obstacle and call my trigger shake function, which performs a typical screen shake. After the screen shake ends the player is translated across the X axis, from what I can tell in the inspector roughly doubling its X position.
public class ScreenShake : MonoBehaviour {
Vector3 initialPosition;
float shakeDuration;
public bool shaking;
[SerializeField] float shakeMagnitude = 0.5f;
[SerializeField] float dampingSpeed = 1.0f;
void Update()
{
if (shakeDuration > 0)
{
shaking = true;
transform.localPosition = initialPosition + Random.insideUnitSphere * shakeMagnitude;
shakeDuration -= Time.unscaledDeltaTime * dampingSpeed;
}
else
{
shakeDuration = 0f;
transform.localPosition = initialPosition;
shaking = false;
}
}
public void TriggerShake(float duration, Vector3 position)
{
shakeDuration = duration;
initialPosition = position;
}
}
I can't figure out why the balloon's X is changing after the screen shake, but it doesn't happen if I don't call that function. I think maybe it has to do with ScreenToWorldPoint being messed up because I'm changing the position of the camera?
EDIT: I forgot to add that the weird repositioning of the balloon ONLY occurs if youre currently holding touching the screen (or holding down the mouse button) when the screen shake occurs. Otherwise everything happens normally.