Unity3D - How to rotate a camera like Google Earth? - unity3d

I'm creating a game in Unity3D that contains a planet in a scene. I want the camera to move around the planet and rotate in the vector direction of the mouse when the player is holding down the right click anywhere on the screen. I have code written out as seen below. The code works great, however the player is only able to rotate the camera around the planet if the mouse is on the planet and not off the planet. How do I change it so that the camera will rotate around the planet even if the mouse is not on the planet?
public class CameraHumanMovement : MonoBehaviour
{
[Header("Settings")]
public float planetRadius = 100f;
public float distance;
public GameObject planet;
public Transform camTransform;
public Transform holderTransform;
private Vector3? mouseStartPosition1;
private Vector3? currentMousePosition1;
public bool dog;
private void LateUpdate()
{
if (Input.GetMouseButtonDown(1))
mouseStartPosition = GetMouseHit();
if (mouseStartPosition != null)
DragPlanet();
if (Input.GetMouseButtonUp(1))
StaticPlanet();
}
private void DragPlanet()
{
currentMousePosition1 = GetMouseHit();
RotateCamera((Vector3)mouseStartPosition1, (Vector3)currentMousePosition1);
}
private void StaticPlanet()
{
mouseStartPosition1 = null;
currentMousePosition1 = null;
}
private void RotateCamera(Vector3 dragStartPosition, Vector3 dragEndPosition)
{
//normalised for odd edges
dragEndPosition = dragEndPosition.normalized * planetRadius;
dragStartPosition = dragStartPosition.normalized * planetRadius;
// Cross Product
Vector3 cross = Vector3.Cross(dragEndPosition, dragStartPosition);
// Angle for rotation
float angle = Vector3.SignedAngle(dragEndPosition, dragStartPosition, cross);
//Causes Rotation of angle around the vector from Cross product
holderTransform.RotateAround(planet.transform.position, cross, angle);
}
private static Vector3? GetMouseHit()
{
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
{
return hit.point;
}
return null;
}
}

A simple code could be like this :
public class CameraHumanMovement : MonoBehaviour
{
//Rotation speed exposed on the inspector
public float RotationSpeed = 10f;
private void Update()
{
//Whenever the left mouse button is pressed rotate this object that holds this script in the x and y axis.
//You can reference your planet and put this script in another object if you want and it will be "yourplanetobject.transform etc.."
if(Input.GetMouseButton(0))
{
float rotX = Input.GetAxis("Mouse X") * RotationSpeed * Time.deltaTime;
float rotY = Input.GetAxis("Mouse Y") * RotationSpeed * Time.deltaTime;
transform.Rotate(Vector3.up, -rotX);
transform.Rotate(Vector3.right, rotY);
}
}
}
Cheers!

Related

CHARACTER ROTATION depending on camera IN UNITY

I'm making a 3rd person controller in unity and i'm stuck: i can't figure out how to make the player follow my freelook cinemachine.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed;
public GameObject Hoverboard_script;
public GameObject cinemachine_Hoverboard;
public Transform main_cam_tf;
void Update()
{
Hoverboard_script.SetActive(false);
cinemachine_Hoverboard.SetActive(false);
PlayerMovement_void();
CamController_void();
}
void PlayerMovement_void()
{
float hor = Input.GetAxisRaw("Horizontal");
float ver = Input.GetAxisRaw("Vertical");
Vector3 playerMovement = new Vector3(hor, 0f, ver).normalized * speed * Time.deltaTime;
transform.Translate(playerMovement, Space.Self);
}
void CamController_void()
{
float MouseY = main_cam_tf.eulerAngles.y;
Debug.Log(MouseY);
Quaternion rotation = Quaternion.Euler(0f, MouseY, 0f);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 4f);
}
}
Right now if i rotate the camera, the player enters a non-stop loop where it rotate constantly. How can i solve? Thanks, cheers
If you want to rotate the player as the rotation value of Y of Camera then remove all the lines of codes in which they rotate your object. Instead use one of these:
1.
transform.rotation = Quaternion.AngleAxis(Camera.Main.transform.eulerAngles.y, Vector3.up);
transform.rotation = Quaternion.EulerAngles(transform.eulerAngles.x, Camera.Main.transform.eulerAngles.y, transform.eulerAngles.z);

Unity: 3D top-down rotate item around player

I'm trying to get an object to always be "in front" of the player, from a top down perspective. Here's screenshots demonstrating what I'm trying to do.
So as you can see, when the blue capsule (player) picks up the green capsule (item), the item correctly hovers in front of the player (indicated by the z-axis blue arrow), but when the player turns in any other direction, the item doesn't follow, and instead stays in exactly the same position relative to the player.
My player controller script looks as follows:
using UnityEngine;
public class PlayerController : MonoBehaviour {
public float movementSpeed = 10;
private Rigidbody body;
private Vector2 movement;
void Start() {
body = GetComponent<Rigidbody>();
}
void Update() {
movement.x = Input.GetAxis("Horizontal");
movement.y = Input.GetAxis("Vertical");
}
void FixedUpdate() {
body.velocity = new Vector3(movement.x * movementSpeed * Time.deltaTime, 0, movement.y * movementSpeed * Time.deltaTime);
// this is what updates the direction of the blue arrow in the direction of player movement
if(movement.x != 0 || movement.y != 0) {
body.rotation = Quaternion.LookRotation(body.velocity);
}
}
}
And here's my pickup script (where the item's position is supposed to be updated):
using UnityEngine;
public class Pickup : MonoBehaviour {
private GameObject item;
public float carryDistance = 1;
void OnCollisionEnter(Collision collision) {
if(collision.gameObject.CompareTag("Item")) {
item = collision.gameObject;
}
}
void Update() {
if(item) {
item.transform.position = transform.position + new Vector3(0, 0, carryDistance);
}
}
}
So to reiterate my question: How can I update the item's position such that it's always hovering next to the player on the side of the blue arrow?
You can achieve this by using players transform.forward
item.transform.position = transform.position + (transform.forward * carryDistance)
+ (Vector3.up * carryHeight);
Alternatively you can just add empty child gameobject to the player, position it in front of the player and use its transform position and rotation to position the picked up object.
public class Pickup : MonoBehaviour {
public Transform pickupPositionTransform;
private GameObject item;
public float carryDistance = 1;
void OnCollisionEnter(Collision collision) {
if(collision.gameObject.CompareTag("Item")) {
item = collision.gameObject;
}
}
void Update() {
if(item) {
item.transform.position = pickupPositionTransform.position;
item.transform.rotation = pickupPositionTransform.rotation;
}
}
}

try to move a object in unity 2d

The object is not moving down the slope i have also tried to reduce the friction to zero but not working and i am using a ball as my object
how to move an object in unity in 2d
Here is my code:
public class move : MonoBehaviour
{
public float moveSpeed = 3f;
Rigidbody2D rig;
float yat ;
void Start()
{
rig = GetComponent<Rigidbody2D>();
}
void Update()
{
float xat = Input.GetAxis("Horizontal");
yat = rig.velocity.y;
rig.velocity = new Vector2(xat*moveSpeed,yat);
}
}
My apologize i don't get it exactly what you try to do? But if you simply moving the object you can try "Transfrom.Translate" method.
By the way, using velocity method try this code in your own version :
float speed = 0.5f;
...
void Update () {
float inputHorizontal = Input.GetAxisRaw("Horizontal");
player.velocity = Vector2.right * inputHorizontal * speed;
}
Imo this should work, if you have any other query let me know.

Jump in using Rigidbody or Character controller

i have been recreating my jump code, i have it all done but i can't add force or anything else.
Here's my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class pBeh : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
public Rigidbody rb;
public float jumpSpeed = 5.2f;
private Vector3 movingDirection = Vector3.zero;
public CharacterController controller;
public float speed;
float turnSmoothVelocity;
public float turnSmoothTime;
public bool canJump = false;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * 10;
float vertical = Input.GetAxis("Vertical") * 10;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
if (canJump == true && Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Jumped");/*
transform.Translate(Vector3.up * 5.0f * Time.deltaTime);
rb.AddRelativeForce(Vector3.up * 8.0f);
rb.AddForce(Vector3.up * 8.0f)
i have tried a lot more, but it just doesn't work.
The sphere (Player) does nothing or shakes.
*/
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("SampleScene");
}
}
void FixedUpdate()
{
if ((controller.collisionFlags & CollisionFlags.Below) != 0)
{
//Debug.Log("ground");
canJump = true;
}
else
{
canJump = false;
}
}
As i said it works just fine i just can't find reason why i cannot jump.
I have all character controller right and rigidbody too. If you could help i would be happy.
Btw i am beginner so i copied movement to be same as camera. Thanks!
From what I know, rigidbody and character controller do not work together (on the same object) so you have to choose one or the other, if you are using rigidbody then a ground check or similiar stuff would not be necessary since rigidbody is using unity physicis system so a lot of the stuff would be already done for you to simulate physics but you should still read thru the document

Jittery movement of the camera when rotating AND moving - 2D top down Unity

I am making a 2d top down game where the player can rotate the camera around himself as he moves through the world.
Everything works fine when the player is moving around the world the camera follows him fine. if he standing still then the camera rotation also works very well. However as soon as I start to do both then there is a jittery in the camera that makes all other objects jitter besides the player.
Now in working with this problem I have found out that this could have to do with the fact that I use rigidbody2d.AddRelativeForce (so physics) to move the player and that his movements are checked in FixedUpdate.
https://forum.unity3d.com/threads/camera-jitter-problem.115224/ http://answers.unity3d.com/questions/381317/camera-rotation-jitterness-lookat.html
I have tried moving my camera rotation and the following scripts to LateUpdate, FixedUpdate, Update you name it. Nothing seems to work. I am sure that there is some sort of delay between movement of the camera and the rotation that is causing this. I am wondering if anyone has any feedback?
I have tried disabling Vsync, does not remove it entirely
I have tried interpolating and extrapolating the rigidbody and although there is a difference it does not remove it entirely. Ironically it seemd if I have it set to none, it works best.
Scripts:
To Follow character, script applied to a gameobject that has the camera as a child
public class FollowPlayer : MonoBehaviour {
public Transform lookAt;
public Spawner spawner;
private Transform trans;
public float cameraRot = 3;
private bool smooth = false;
private float smoothSpeed = 30f;
private Vector3 offset = new Vector3(0, 0, -6.5f);
//test
public bool changeUpdate;
private void Start()
{
trans = GetComponent<Transform>();
}
private void FixedUpdate()
{
CameraRotation();
}
private void LateUpdate()
{
following();
}
public void following()
{
Vector3 desiredPosition = lookAt.transform.position + offset;
if (smooth)
{
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
}
else
{
transform.position = desiredPosition;
}
}
void CameraRotation()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
}
public void SetTarget(string e)
{
lookAt = GameObject.Find(e).GetComponent<Transform>();
}
}
The character Controller, script applied to the Player, is called in FixedUpdate
private void HandleMovement()
{
if (Input.GetKey("w"))
{
rigid.AddRelativeForce(Vector2.up * speed);
}
if (Input.GetKey("s"))
{
rigid.AddRelativeForce(Vector2.down * speed);
}
if (Input.GetKey("a"))
{
if (facingRight)
{
Flip();
}
rigid.AddRelativeForce(Vector2.left * speed);
}
if (Input.GetKey("d"))
{
if (!facingRight)
{
Flip();
}
rigid.AddRelativeForce(new Vector2(1,0) * speed);
}
}
Try to use Coroutines. I modified some of my scripts to be more familiar to Your code, tried it, and I didn't see any jittery. I hope that will help You.
Camera Class:
public class CameraController : MonoBehaviour {
[SerializeField]
Transform CameraRotator, Player;
[SerializeField]
float rotationSpeed = 10f;
float rotation;
bool rotating = true;
void Start()
{
StartCoroutine(RotatingCamera());
}
IEnumerator RotatingCamera()
{
while (rotating)
{
rotation = Input.GetAxis("HorizontalRotation");
CameraRotator.Rotate(Vector3.up * Time.deltaTime * rotation * rotationSpeed);
CameraRotator.position = Player.position;
yield return new WaitForFixedUpdate();
}
}
private void OnDestroy()
{
StopAllCoroutines();
}
}
Player Class:
public class PlayerMovement : MonoBehaviour {
[SerializeField]
float movementSpeed = 500f;
Vector3 movementVector;
Vector3 forward;
Vector3 right;
[SerializeField]
Transform CameraRotator;
Rigidbody playerRigidbody;
float inputHorizontal, inputVertical;
void Awake()
{
playerRigidbody = GetComponent<Rigidbody>();
StartCoroutine(Moving());
}
IEnumerator Moving()
{
while (true)
{
inputHorizontal = Input.GetAxis("Horizontal");
inputVertical = Input.GetAxis("Vertical");
forward = CameraRotator.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
Vector3 right = new Vector3(forward.z, 0, -forward.x);
movementVector = inputHorizontal * right + inputVertical * forward;
movementVector = movementVector.normalized * movementSpeed * Time.deltaTime;
playerRigidbody.AddForce(movementVector);
yield return new WaitForFixedUpdate();
}
}
}
I fixed this problem finally:
First I made my cameraRotation() and follow() into 1 function and gave it a better clearer name:
public void UpdateCameraPosition()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
else if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
Vector3 desiredPosition = lookAt.transform.position + offset;
transform.position = desiredPosition;
}
I then called that function from the character controller straight after the handling of movement. Both calls (handleMovement & cameraPosition) in fixedUpdate.
void FixedUpdate()
{
HandleMovement();
cameraController.UpdateCameraPosition();
}
and the jittering was gone.
So it seems it was imply because there was a slight delay between the two calls as the previous posts I read had said. But I had failed to be able to properly Set them close enough together.
Hope this helps someone.