How do I smoothly rotate the camera in unity? - c#

I am making a 2d unity game with C#. Right now, I am trying to make the camera rotate and I am using this code:
rotateX = Random.Range (0, 50);
Camera.main.transform.eulerAngles = Vector3(0,0,rotateX);
But every time I try to run the game, it gives me an error.
Anybody have tips on how I can (smoothly) rotate the camera from side to side?

You can get rid of errors by changing your code to this:
void Update () {
float rotateX = Random.Range (0, 50);
transform.eulerAngles = new Vector3(0,0,rotateX);
}
And attaching script component containing it to the camera. But then it is rotating randomly all the time.
I'm not sure, from the question, what kind rotation do you want. But you can use for example this
void Update () {
transform.Rotate(Vector3.forward, 10.0f * Time.deltaTime);
}
to rotate the camera smoothly. Just change to first parameter to the axis around what you want to rotate.

Don't use Camera.main. Write a class for your camera and then add it to the camera in the scene. Use transform.rotation like this:
void Update ()
{
transform.rotation = Quaternion.Euler(y, x, z);
transform.position = Quaternion.Euler(y, x, z);
}
see this for more info:
http://wiki.unity3d.com/index.php?title=MouseOrbitImproved

The error is because you are missing the new initializer.
rotateX = Random.Range (0, 50);
Camera.main.transform.eulerAngles = new Vector3(0,0,rotateX); //<--- put 'new' before 'Vector3'

Easiest way is to place that code into your gameobject add current camera which you want it to rotate.
public class swipebutton : MonoBehaviour
{
public Camera cam;
void Update()
{
cam.transform.Rotate(Vector3.up, 20.0f * Time.deltaTime);
}
}

Related

Unity camera follows player script

I'm pretty new to Unity. I tried to create a script that the camera would follow the actor (with a little difference). Is there a way to improve the code? It works just fine. But I wonder if I did it the best way. I want to do it about as I wrote, so if you have any tips. Thank you
Maybe change Update to FixedUpdate ?
public GameObject player;
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("Cube"); // The player
}
// Update is called once per frame
void Update()
{
transform.position = new Vector3(player.transform.position.x, player.transform.position.y + 5, player.transform.position.z - 10);
}
Making the camera following the player is quite straight forward.
Add this script to your main camera.
Drag the reference of the player object to the script and then you are done.
You can change the values in the Vector 3 depending on how far you want the camera to be from the player.
using UnityEngine;
public class Follow_player : MonoBehaviour {
public Transform player;
// Update is called once per frame
void Update () {
transform.position = player.transform.position + new Vector3(0, 1, -5);
}
}
Follows player in the back constantly when the player rotates, no parenting needed, with smoothing.
Piece of Knowledges:
Apparently, Quaternion * Vector3 is going to rotate the point of the Vector3 around the origin of the Vector3 by the angle of the Quaternion
The Lerp method in Vector3 and Quaternion stand for linear interpolation, where the first parameter gets closer to the second parameter by the amount of third parameter each frame.
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.125f;
public Vector3 locationOffset;
public Vector3 rotationOffset;
void FixedUpdate()
{
Vector3 desiredPosition = target.position + target.rotation * locationOffset;
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
transform.position = smoothedPosition;
Quaternion desiredrotation = target.rotation * Quaternion.Euler(rotationOffset);
Quaternion smoothedrotation = Quaternion.Lerp(transform.rotation, desiredrotation, smoothSpeed);
transform.rotation = smoothedrotation;
}
}
This will always follow the player from the same direction, and if the player rotates it will still stay the same. This may be good for top-down or side-scrolling view, but the camera setup seems to be more fitting for 3rd person, in which case you'd want to rotate the camera when the player turns.
The easiest way to do this is actually not with code alone, simply make the camera a child of the player object, that way its position relative to the player will always stay the same!
If you do want to do it through code, you can change the code to be like this:
void Update()
{
Vector3 back = -player.transform.forward;
back.y = 0.5f; // this determines how high. Increase for higher view angle.
transform.position = player.transform.position - back * distance;
transform.forward = player.transform.position - transform.position;
}
You get the direction of the back of the player (opposite of transform's forward). Then you increase the height a little so the angle will be a bit from above like in your example. Last you set the camera's position to be the player's position and add the back direction multiplied by the distance. That will place the camera behind the player.
You also need to rotate the camera so it points at the player, and that's the last line - setting the camera's forward direction to point at the player.
Here is just another option. I always find it easier to have the variables which are populated in the inspector so you can adjust it and fine tune it as needed.
public GameObject player;
[SerializeField]
private float xAxis, yAxis, zAxis;
private void Update()
{
transform.position = new Vector3(player.transform.position.x + xAxis, player.transform.position.y + yAxis, player.transform.position.z + zAxis);
}

Clamping an object axis in Vuforia AR camera

screenshot hereI want to clamp Y-axis on a cube. I can do it in Unity camera. But, it does not react correctly when I am using it in Vuforia camera.
My problem was that the cube follows the camera. I would like the cube to stay in its position and ignore the AR camera position. I sense it has something to do with WorldtoViewpoint but I cannot figure it out. Can you teach me how to do this please? thankyou
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClampMovementController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 pos = transform.localPosition;
pos.y = Mathf.Clamp(transform.position.y, 0f, 0f);
transform.localPosition = pos;
}
}
This is my solution:
Actually its very simple. The INcorrect concept was my object attached to the AR camera, hence, object position is always moving related to camera position. Now. In order to make the object stays in its place. I need to get its localPosition. First. Store the localposition in Vector3 pos. And then do modification on Vector3 pos. At last, reassign the new value to the object localposition.
public class ClampMovementController : MonoBehaviour
{
public float currentPos;
public GameObject capsule;
void Update()
{
//store the value of object localPosition
Vector3 pos = capsule.transform.localPosition;
//modification on the value
pos.y = Mathf.Clamp(pos.y, currentPos, currentPos);
//rerassign the new value to the object localPosition
capsule.transform.localPosition = pos;
}
}
First of all your cube is moving with the camera because your image target is child of your ARCamera. Therefore, when you move the camera image target moves, then your cube moves as well. Make sure your ImageTarget has no parent.
I did not understand why you have to lock any movement in Y axis. I guess you are doing something wrong with lean touch when you move object. I have not used lean touch but i have achieved this with keyboard inputs. You can convert it to lean touch by modifying following script. Just add these line to your ImageTarget's DefaultTrackableEventHandler script:
//Variables for getting capsule and checking if ImageTarget is tracked
private bool isTracked = false;
private GameObject capsule;
Then create an Update method for getting input from user like this.
void Update()
{
if(isTracked)
{
if(Input.GetKey(KeyCode.W))
{
//using forward for moving object in z axis only.
//Also using local position since you need movement to be relative to image target
//Global forward can be very different depending on your World Center Mode
capsule.transform.localPosition += Vector3.forward * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))
{
capsule.transform.localPosition -= Vector3.forward * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A))
{
//Using Vector3.left and right to be make sure movement is in X axis.
capsule.transform.localPosition += Vector3.left * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.D))
{
capsule.transform.localPosition += Vector3.right * Time.deltaTime;
}
}
}
As you can see there is no movement in Y axis because i used forward, left and right vectors to make sure movement in in only X and Y axis.
Last you have to make sure isTracked is updated. In order to do that you have to add isTracked = false; in OnTrackingLost method and isTracked = true; in OnTrackingFound method. Good luck!

Why does my directional light only rotate from 90º to -90º (Unity 5.5)

I have tried both of these C#scripts to rotate my directional light:
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
void Update ()
{
transform.rotation = Quaternion.Euler(transform.eulerAngles.x + 1.0f,
transform.eulerAngles.y,
transform.eulerAngles.z);
}
}
and
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
void Update ()
{
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x + 1.0f,
transform.localEulerAngles.y,
transform.localEulerAngles.z);
}
}
They both seem to function exactly the same: If I change transform.eulerAngles.y to transform.eulerAngles.y + 0.5f, the light will rotate along the y-axis, and the same works for the z-axis. However, when I try to do this with the x-axis, it will rotate until it hits 90º, at which point it will continue to attempt rotation but it immediately and continuously shoved back to 90º. If I reverse the direction, it does the same thing at -90º. For example, the rotation might be: 88.5,89.0,89.5,90.0, 90.5, 89.93, 90.24, 89.4, etc.
What is causing this clamping and how do I fix it?
I think this is what you are looking for: http://answers.unity3d.com/questions/187073/rotation-locks-at-90-or-270-degrees.html
In order to fix your problem, you need to use an additional vector, change it inside Update every frame, and then pass it to the eulerAngles propriety of the transform.
Vector3 vect = Vector3.zero;
float rotationSpeed = 10f;
void Start () {
vect = transform.eulerAngles; //Set the vect rotation equal to the game object's one
}
void Update ()
{
vect.x += rotationSpeed * Time.deltaTime;
//Pass unique eulerAngles representation to the object without letting Unity change it
transform.eulerAngles = vect;
}
This happens btw because there're multiple euler angles representation of a single physical rotation in the 3D space, and when you work directly on the eulerAngles propriety of the transform, Unity makes some work behind the scenes, which can lead to a gimbal lock.
Use Quaternions. It's what Unity3d uses internally and doesn't have any of the side effects of euler angles.
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
public Vector3 RotationAxis = Vector3.right;
Quaternion _startRotation;
float _rotationIncrement = 0;
void Start()
{
_startRotation = transform.rotation;
}
void Update ()
{
Quaternion rotationMod =
Quaternion.AngleAxis(_rotationIncrement, RotationAxis);
_rotationIncrement += 1;
transform.rotation = _startRotation * rotationMod;
}
}
However, you probably want to use something like Quaternion.RotateTowards or Quaternion.Lerp along with Time.time and a rate. You will get much smoother results that way.
if you only want to rotate along the X-axis then set the other axis as 0.

Why the script is not rotating my sphere object?

Well, I am new to unity 3d and C sharp. I was trying a script to rotate my spehere object . But it's not working.
I was following a youtube video. This code worked for him. But in my case it is not working.
I added the transform object.
using UnityEngine;
using System.Collections;
public class cubescript : MonoBehaviour {
public Transform sphereTransform;
// Use this for initialization
void Start () {
sphereTransform.parent = transform;
}
// Update is called once per frame
void Update () {
transform.eulerAngles = new Vector3 (0, 180*Time.deltaTime, 0);
}
}
It's kind of working but stuck at 2.981877-3 Y rotation .. And not rotating around the cube..
The problem is that you are trying to rotate, but eulerAngles only sets to ABSOLUTE angles (if you want to add angles to the current frame angle, you will use Rotate).
So, if you use transform.eulerAngles you will be all the frames setting the angle change to what 180 * Time.deltaTime returns, that will depend on how many FPS you are running, thats why you get constant number.
If you use transform.Rotate it will add the new angle change to the current angle frame. Say that you want to increment by 10 degress, so frame 1 = (0,0,0), frame 2 = (0,10,0), frame 3 = (0,20,0).
In eulerAngles you will get all the time (0,10,0), because it sets ABSOLUTE angle, Rotate adds to the current angle what you want.
Change this
transform.eulerAngles = new Vector3 (0, 180*Time.deltaTime, 0);
To this
transform.Rotate(new Vector3 (0, 180*Time.deltaTime, 0));
This is the official Unity Documentation for eulerAngle and Rotate
As said in another answer, when you set transform.eulerAngles, you are setting an absolute rotation. You can use transform.Rotate() but you can also use Time.time to ensure that you get linear rotation: transform.eulerAngles = new Vector3(0, 180*Time.time, 0);

How do I make a function that fires a bullet from the gun in a straight line to the right in c#?

First: I'm a real noob.
Here's my code for my shoot function:
using UnityEngine;
using System.Collections;
public class Gun : MonoBehaviour
{
public float fireRate = 0; // makes it a single fire per click weapon
public float Damage = 10;
public LayerMask notToHit; // tells us what is valid for being hit by the weapon
public float Range = 100;
float timeToFire = 0;
Transform firePoint;
// Use this for initialization
void Awake ()
{
firePoint = transform.FindChild ("firePoint");
if (firePoint == null)
{
Debug.LogError ("No FirePoint object found as a child of the cannon");
}
}
// Update is called once per frame
void Update ()
{
Shoot ();
if (fireRate == 0)
{
if (Input.GetButtonDown ("Fire1"))
{
Shoot ();
}
}
else
{
if (Input.GetButtonDown ("Fire1") && Time.time > timeToFire) {
timeToFire = Time.time + 1 / fireRate;
Shoot ();
}
}
}
void Shoot ()
{
Vector2 firePointPosition = new Vector2 (firePoint.position.x, firePoint.position.y);
Vector2 target = new Vector2 (firePoint.position.x, [firePoint.position.y + Range]);
RaycastHit2D hit = Physics2D.Raycast (firePoint, notToHit);
Debug.DrawLine (firePointPosition, target);
}
I just want it to draw a line (cause I'm still learning) from my firePoint object (at the mouth of my cannon) to a point +100 units on the Y axis (Range = 100).
I'm getting following c# errors:
1) Assets/Gun.cs(47,69): error CS1526: A new expression requires () or [] after type
2) Assets/Gun.cs(47,98): error CS8032: Internal compiler error during parsing, Run with -v for details
Can anyone point me in the right direction?
As Noctis already wrote the Vector2 target line is wrong. It should be like this
Vector2 target = new Vector2 ( firePoint.position.x, (firePoint.position.y + Range));
After that you say you have another compile error, but it is an error on line 48, so the Raycast call is wrong.
To call the Raycast you will have to do something like this:
RaycastHit2D hit = Physics2D.Raycast (Origin, Direction);
// So your code should be
RaycastHit2D hit = Physics2D.Raycast (firePoint, DIRECTION);
This means you will have to create another Vector2 which defines the direction of your "shoot line".
I attached a link which describe the call to Raycast
See the reference here
Please try to update your code and come back
Since i can see you only want to draw the line right now you should comment out you error proned code. So you code should look like this:
void Shoot ()
{
Vector2 firePointPosition = new Vector2 (firePoint.position.x, firePoint.position.y);
Vector2 target = new Vector2 (firePoint.position.x, (firePoint.position.y + Range));
// No need to do the ray casting right now
// RaycastHit2D hit = Physics2D.Raycast (firePoint, notToHit);
Debug.DrawLine (firePointPosition, target);
}
This line seems very fishy to me :
Vector2 target = new Vector2 ( firePoint.position.x
, [firePoint.position.y + Range]
);
you're passing something that looks like an array to the new function, this is why it's complaining I believe.
Did you try to say :
Vector2 target = new Vector2 ( firePoint.position.x
, (firePoint.position.y + Range)
);
To answer the firing question:
I assume you are using sprites and on a 2D environment since you are using Vector2. If that is the case you may want to either apply a force or directly change the "bullet" transform using the Vector2.right or even the Transform.forward, the latter will change depending on where your character is facing.
If you are going to instantiate the bullet prefab in the firePointPosition transform I would advice on just applying a force to the prefab the instantiation.
Something like:
public GameObject bulletPrefab; //Initialize it either by drag&drop from the editor or through code
private float bulletSpeed; // self explanatory
/* Rest of the code*/
GameObject bullet = Instantiate(bulletPrefab, firePointPosition, Quaternion.identity) as GameObject;
bullet.rigidbody.AddForce(Vector2.right * bulletSpeed);
// or
bullet.rigidbody.AddForce(transform.forward * bulletSpeed);

Categories