Questions arising from first-person controller code in Unity - c#

I am creating a first person controller in Unity. Very basic stuff, camera is a child of Player capsule. Codes work, but I need help explaining what's going on.
*camera is child of Player in hierarchy
These are my questions:
In PlayerMovement, why are we translating in the Z-axis to achieve vertical movement when Unity is in Y-Up axis?
In CamRotation, I have no idea what is going on in Update(). Why are we applying horizontal movement to our Player, but then vertical movement to our Camera? Why is it not applied on the same GameObject?
What is mouseMove trying to achieve? Why do we use var?
I think we are getting a value of how much mouse has been moved, but what then does applying Vector2.Scale do to it?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public float speed = 5.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float mvX = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
float mvZ = Input.GetAxis("Vertical") * Time.deltaTime * speed;
transform.Translate(mvX, 0, mvZ);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamRotation : MonoBehaviour {
public float horizontal_speed = 3.0F;
public float vertical_speed = 2.0F;
GameObject character; // refers to the parent object the camera is attached to (our Player capsule)
// initialization
void Start()
{
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
var mouseMove = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
mouseMove = Vector2.Scale(mouseMove, new Vector2(horizontal_speed, vertical_speed));
character.transform.Rotate(0, mouseMove.x, 0); // to rotate our character horizontally
transform.Rotate(-mouseMove.y, 0, 0); // to rotate the camera vertically
}
}

XY is the plane for 2D Unity games. For 3D, you have Z-axis for height, and XY plane for positioning.
Note that different components from mouseMove are being applied (.x for character and .y for the camera). This means that the movement from the character is not equal to the movement from the camera; one should be faster/slower than the other.
var is a predefined C# keyword that lets the compiler figure out an appropriate type. In this case, it's the same as if you had written Vector2 as in Vector2 mouseMove = new Vector2(...);.
You are scaling the value from mouseMove, by multiplying its components by predefined values in your code. That's just it.
EDIT
You apply .x to your character because, as you commented after the line of code, you want to move it horizontally. As for the camera, .y is being applied because you want to move it vertically.
The negative value could be because the axis is inverted, so you make it negative so the camera has a natural movement. It's the same principle some games have in the setting, where they allow you to invert Y-axis.

Related

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!

gameObject rotates when camera rotates

I'm working on a UI menu for a game, and I dragged in a GameObject to serve as a representation of what will be placed down if you select it. When I attach a script for its rotation and run the game, it tilts downward with the tilt of the camera, even though there is no script linking the camera and the object.
Canvas is in ScreenSpace - Camera mode.
Rotation Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BuildList : MonoBehaviour {
//Floats
public float speed = 10f;
void Update ()
{
transform.eulerAngles = new Vector3 (-90f, transform.eulerAngles.y, transform.eulerAngles.z + (speed * Time.deltaTime));
}
}
The x-rotation in the inspector is the one that is rotating. When I rotate the camera downwards, the value the x-rotation in the inspector gets is -155, while the x-rotation of this object should be fixed at -90.
This may or not solve your problem, but I have a tip:
Don't ever use transform.eulerAngles for iterative update. It could cause Gimbal Lock. Use Rotate if possible.
I suggest replace the code with this:
void Update ()
{
// Note: the axis to rotate may different than what you expect. experiment with it
transform.Rotate(Vector3.forward * (speed * Time.deltaTime), Space.World);
}
And set the object rotation at (-90,0,0) before the game begin.
Thanks for willnode pushing me in the right direction, I found code in unity Documentation and modified it so it only rotates the z-axis of the object.
https://docs.unity3d.com/ScriptReference/Transform.Rotate.html
transform.Rotate(0, 0, Time.deltaTime * speed);

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 does the z change when I move this cube? [c#][Unity]

I am really new to unity so I wanted to make a simple 2d project where you can move a cube. So I made a script to move the cube but when I play the game the Z changes along with the X so it will fall of the map.
Video:
https://www.youtube.com/watch?v=M9oHSc6dN2A&feature=youtu.be
The script I'm using:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
private Vector2 input;
public float movementSpeed = 50f;
private float horizontal;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
horizontal = Input.GetAxis ("Horizontal");
rigidbody.AddForce ((Vector2.right * movementSpeed) * horizontal);
}
}
I am using unity 4
Your rigidbody has Use Gravity checked. Romove that and it should function the way you want. [Wrong axis]
Edit:
A Rigidbody has a constraint property. Freeze z position there.

something wrong with rotation controls in 2d top down shooter in unity3d

I am trying to get my character to face the mouse by rotating on its y axis. It rotates a little, but it do not face the mouse. The Camera's position is directly above the player, and its in orthographic view I see many other examples of top down shooters and there almost exactly like mine so i don't know whats the problem please help thank you.
using UnityEngine;
using System.Collections;
public class playermovementscript : MonoBehaviour {
public float movementspeed = 5f;
public float bulletspeed = 10f;
public GameObject bullet;
public GameObject shooter;
public Vector3 target;
public Camera camera;
// Use this for initialization
void Start () {
//refrence to main camera
Camera camera;
}
// Update is called once per frame
void Update () {
//call movement function in every frame
movement ();
// cheek for input of f in every frame if true execute shoot function
if (Input.GetKeyDown (KeyCode.F)) {
shoot();
}
}
void movement(){
// makes refrence to gameobjects rigidbody and makes its velocity varible to equal values of axis x and y
gameObject.GetComponent<Rigidbody>().velocity = new Vector3(Input.GetAxisRaw("Horizontal")*movementspeed,0,Input.GetAxisRaw("Vertical")*movementspeed);
// makes vector 3 type target equall to mouse position on pixial cordinates converted in to real world coordniates
target = camera.ViewportToWorldPoint (new Vector3(Input.mousePosition.x,Input.mousePosition.y,camera.transform.position.y - transform.position.y));
//target.x -= transform.position.x;
//target.z -= transform.position.z;
// states the vector 3 values of target
Debug.Log (target);
// makes object local z face target and iniziates up axis
transform.LookAt (target,Vector3.up);
}
Going to make an attempt to explain what's going on...
target = camera.ViewportToWorldPoint (new Vector3(Input.mousePosition.x,Input.mousePosition.y,camera.transform.position.y - transform.position.y));
The above code is trying to convert a mouse position which is in Screen Space (which measures the position from (0,0) to the width/height of the screen in pixels) to a Viewport Space (which measure the same screen but with a different measure, it measures the positions from (0,0) to (1,1)).
In Unity
Screen Space Measurement: Origin (0,0) to the max width/height
Viewport Measurement: Origin (0,0) to (1,1)
Reference: http://docs.unity3d.com/ScriptReference/Camera.html
If you desire to still use "ViewportToWorldPoint" then you could do a "ScreenToViewportPoint" then follow it with a "ViewPortToWorldPoint".
Otherwise, you could look into using "ScreenToWorldPoint" from the start.

Categories