I am creating a game with Unity and I have a math problem.
I have a sphere with a radius of 10 and center of (0, 0, 0).
I want the camera to move around that sphere, but I can't find anywhere a way to do what I want to.
I move the camera in the X axis and the Y axis (and therefore get a point outside of the sphere) and I want to set it's Z axis so the camera would be back on the sphere, I am using this equation: r^2 = x^2 + y^2 + z^2 => z^2 = r^2 - x^2 - y^2
But it doesn't work… Please help me
EDIT
This is my code (in c#):
private void OnMouseDrag()
{
var newX = mainCameraTransform.position.x + Input.GetAxis("Mouse X");
var newY = mainCameraTransform.position.y + Input.GetAxis("Mouse Y");
var maxDistance = 10.0f;
newX = Mathf.Clamp(newX, -maxDistance * 0.85f, maxDistance * 0.85f);
newY = Mathf.Clamp(newY, 1.0f * 0.85f, maxDistance * 0.85f);
var newZ = Mathf.Sqrt(Mathf.Abs(maxDistance * maxDistance - newX * newX - newY * newY));
mainCameraTransform.position = new Vector3(newX, newY, newZ);
mainCameraTransform.LookAt(Vector3.zero);
}
As you can see I used Clamp to keep the X and Y less then the radius but it didn't help…
This isn't tested, but it should be pretty close
private void OnMouseDrag(){
Vector3 newPos = mainCameraTransform.position;
newPos += mainCameraTransform.up * Input.GetAxis("Mouse Y");
newPos += mainCameraTransform.right * Input.GetAxis("Mouse X");
newPos = newPos.normalized * 10f;
mainCameraTransform.position = newPos;
mainCameraTransform.LookAt(Vector3.zero, mainCameraTransform.up);
}
You have to limit 2D coordinates by circle border
len = Mathf.Sqrt(newX * newX + newY * newY);
//perhaps you have Len or Hypot function in your Math library
if len > maxDistance then
newX = maxDistance * newX / len
newY = maxDistance * newY / len;
Drag and drop this script on the camera to orbit it around a target using the right mouse button
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OrbitAroundObject : MonoBehaviour {
public Transform target;
public float distance = 10.0f;
public float xSpeed = 120.0f;
public float ySpeed = 120.0f;
public float yMinLimit = -20f;
public float yMaxLimit = 80f;
public float distanceMin = .5f;
public float distanceMax = 15f;
public float smoothTime = 2f;
public float zoomSpeed = 1;
float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;
float velocityX = 0.0f;
float velocityY = 0.0f;
// Use this for initialization
void Start() {
Vector3 angles = transform.eulerAngles;
rotationYAxis = angles.y;
rotationXAxis = angles.x;
// Make the rigid body not change rotation
if (GetComponent<Rigidbody>()) {
GetComponent<Rigidbody>().freezeRotation = true;
}
}
void LateUpdate() {
if (target) {
if (Input.GetMouseButton(1)) {
velocityX += xSpeed * Input.GetAxis("Mouse X") * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}
//distance -= (Input.mouseScrollDelta.y*Time.deltaTime);
distance = Mathf.Lerp(distance, distance-(Input.mouseScrollDelta.y*zoomSpeed) , Time.deltaTime * smoothTime);
distance = Mathf.Clamp(distance, distanceMin, distanceMax);
rotationYAxis += velocityX;
rotationXAxis -= velocityY;
rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);
//Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
Quaternion toRotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Quaternion rotation = toRotation;
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + target.position;
transform.rotation = rotation;
transform.position = position;
velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}
}
public static float ClampAngle(float angle, float min, float max) {
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
}
Related
Hello I was trying to do movement script in Unity. Also I wanted to add jump, but everytime when I jump it moves up for like 0.025 on Y direction and stops the player in air*(if I am on 0 and I jump it moves on 0.02545 then 0.0543 etc...)* and I can spam Space to move player up. I added gravity but it looks it doesn't work.. I don't know how to fix it. I hope someone can help me with my problem...
Here is the function what I am using...
Vector3 moveDirection = Vector3.zero;
public float walkingSpeed = 10.0f;
public bool canJump = true;
public float jumpSpeed = 8.0f;
public float gravity = 10.0f;
CharacterController characterController;
void Movement()
{
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 right = transform.TransformDirection(Vector3.right);
float moveX = walkingSpeed * Input.GetAxis("Vertical");
float moveY = walkingSpeed * Input.GetAxis("Horizontal");
float MovementY = moveDirection.y;
moveDirection = (forward * moveX) + (right * moveY);
if (Input.GetButtonDown("Jump") && canJump)
{
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}
Because you are resetting moveDirection every frame (when you call moveDirection = (forward * moveX) + (right * moveY) you aren't letting the gravity accumulate. You should instead save the vertical speed separately and add it every frame.
Something like the following:
Vector3 moveDirection = Vector3.zero;
public float walkingSpeed = 10.0f;
public bool canJump = true;
public float jumpSpeed = 8.0f;
public float gravity = 10.0f;
CharacterController characterController;
private float verticalSpeed;
void Movement()
{
float moveX = walkingSpeed * Input.GetAxis("Vertical");
float moveY = walkingSpeed * Input.GetAxis("Horizontal");
verticalSpeed -= gravity * Time.deltaTime;
if (Input.GetButtonDown("Jump") && canJump)
{
verticalSpeed = jumpSpeed;
}
characterController.Move((moveX * transform.forward + moveY * transform.right + verticalSpeed * transform.up)
* Time.deltaTime);
}
transform.forward is equivalent to transform.TransformDirection(Vector3.forward)
I use the attached c# script to control the camera.
Mouse scroll (pulley/roller/wheel): Zooming in and out of the main character
Up Arrow (or W key) and Down Arrow (or X key): Raise and Lower the camera
Right arrow (or D key) and Left arrow (or A key): Rotate the camera around the main character
I try to get the camera to follow the back of the main character, and add it the offset that player defined by using mouse and arrows.
This line correctly moves the camera according to the input from the mouse and arrows:
transform.position = target.position + offset * currentZoom;
This line correctly moves the camera so that it will follow the back of the main character:
transform.position = target.position - target.forward + Vector3.up;
But each of them works correctly only if the other is canceled. If I try to merge them into one line, like:
transform.position = target.position - target.forward + Vector3.up + offset * currentZoom;
then the camera doesn't move properly:
Using the left and right arrows moves the camera around the main
character in ellipse/oval shape instead of in a circle
When the character moves, the offsset set by the right and left
arrows isn't saved but the camera returns to being exactly behind
the back of the main character
What do I need to do to combine the two lines so that camera does move properly?
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform target;
public Vector3 offset = new Vector3(10f, 6f, 0f);
public float RotationX = .5f;
public float rightLeftSpeed = 5f;
public float currentZoom = .13f;
public float minZoom = .1f;
public float maxZoom = 1f;
public float speedZoom = .1f;
public float currentHeight = 6f;
public float minHeight = 0f;
public float maxHeight = 10f;
public float speedHeight = 1f;
void Update()
{
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * speedZoom;
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
currentHeight += Input.GetAxis("Vertical") * speedHeight * Time.deltaTime;
currentHeight = Mathf.Clamp(currentHeight, minHeight, maxHeight);
offset.y = currentHeight;
offset = Quaternion.AngleAxis(-Input.GetAxis("Horizontal") * rightLeftSpeed, Vector3.up) * offset;
}
void LateUpdate()
{
transform.position = target.position + offset * currentZoom;
transform.position = target.position - target.forward + Vector3.up;
transform.LookAt(target.position + Vector3.up * RotationX);
}
}
I tested your code and adjusted it til it worked like you were trying to have it work. Instead of using offset, I used an angle. Then after setting the position, I rotate around the object by that angle. I set the height as part of setting the position. Lastly, I multiplied the target.forward by currentZoom to make it the distance the camera is from the object. I also adjusted the default values since these changes would make it really close otherwise. I'm pretty sure there are ways to simplify this a bit, but this works!
public class CameraController : MonoBehaviour {
public Transform target;
public float angle;
public float RotationX = .5f;
public float rightLeftSpeed = 5f;
public float currentZoom = 5f;
public float minZoom = 2f;
public float maxZoom = 8f;
public float speedZoom = .5f;
public float currentHeight = 6f;
public float minHeight = 3f;
public float maxHeight = 7f;
public float speedHeight = 1f;
void Update() {
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * speedZoom * Time.deltaTime * 60f;
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
currentHeight += Input.GetAxis("Vertical") * speedHeight * Time.deltaTime * 60f;
currentHeight = Mathf.Clamp(currentHeight, minHeight, maxHeight);
angle -= Input.GetAxis("Horizontal") * rightLeftSpeed * Time.deltaTime * 60f;
}
void LateUpdate() {
var newPosition = target.position - (target.forward * currentZoom) + Vector3.up;
newPosition.y = target.position.y + currentHeight;
transform.position = newPosition;
transform.RotateAround(target.position, Vector3.up, angle);
transform.LookAt(target.position + Vector3.up * RotationX);
}
}
I made runtime gizmo in project
but gizmo move correct drag is not correct
I have to move the mouse dragging part to the xyz axis,
but I only move in the xy axis
i attempt innerproduct but failed
public int HowToMove;
private Vector3 mOffset;
private float mZCoord;
void OnMouseDrag()
{
float distance = Vector3.Distance(transform.root.position,
Camera.main.transform.position);
switch (HowToMove)
{
case 0:
float deltaX = Input.GetAxis("Mouse X") * (Time.deltaTime * 10 * distance);
mOffset = Camera.main.transform.right * deltaX;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
case 1:
float deltaY = Input.GetAxis("Mouse Y") * (Time.deltaTime * 10 * distance);
mOffset = Vector3.up * deltaY;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
case 2:
float deltaZ = Input.GetAxis("Mouse Y") * (Time.deltaTime * 10 * distance);
mOffset = Vector3.forward* deltaZ;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
}
There was a problem that did not drag correctly through xyz gizmo.
For example, when I turned the camera 180 degrees, I clicked xyz red (x axis) and moved up and down.
So I switched to the new code.
public class GizmoMove : MonoBehaviour
{
public int HowToMove; //x y z 축 다르게 인스펙터창에서 설정이 되어있습니다.
private Vector3 mOffset;
private float mZCoord;
void OnMouseDrag()
{
Vector2 ve2 = CameraControls.originPos;
switch (HowToMove)
{
case 0:
Vector2 XAxis = (new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")));
float deltaX = Vector2.Dot(XAxis, ve2);
mOffset = Vector3.left * deltaX * 0.3f;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
case 1:
Vector2 YAxis = (new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")));
float deltaY = Vector2.Dot(YAxis, ve2);
mOffset = Vector3.up * deltaY * 0.3f;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
case 2:
Vector2 ZAxis = (new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")));
float deltaZ = Vector2.Dot(ZAxis, ve2);
mOffset = Vector3.forward * deltaZ * 0.3f;
CameraControls.selectionObj.transform.position += mOffset;
transform.root.position = (CameraControls.selectionObj.transform.position);
break;
}
}
}
I have created new Unity project, have added a cube into the center and now want to make player to be able to rotate camera around this cube by swipes and/or mouse drags.
Please, name simple steps to implement this or keywords to find an answer or where to read about it?
public Transform Target;
public float distance = 2.0f;
public float xSpeed = 20.0f;
public float ySpeed = 20.0f;
public float yMinLimit = -90f;
public float yMaxLimit = 90f;
public float distanceMin = 10f;
public float distanceMax = 10f;
public float smoothTime = 2f;
float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;
float velocityX = 0.0f;
float velocityY = 0.0f;
void Update()
{
if (Input.GetMouseButton(0))
{
velocityX += xSpeed * Input.GetAxis("Mouse X") * distance * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}
rotationYAxis += velocityX;
rotationXAxis -= velocityY;
rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);
Quaternion rotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + Target.position;
transform.rotation = rotation;
transform.position = position;
velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
Taken from https://answers.unity.com/questions/1257281/how-to-rotate-camera-orbit-around-a-game-object-on.html
If you only want to rotate around a specific axis, for example around Y, you could basicly just do this
this.transform.RotateAround(Target.transform.position, Vector3.up, Input.GetAxis("Mouse X")*20.0f);
Create a new C# Script called "CameraRotate", open it and paste this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraRotate : MonoBehaviour {
public Transform cube;
public float sensitivityX;
public float sensitivityY;
GameObject pivot;
void Start () {
pivot = new GameObject ("pivot");
pivot.transform.position = cube.position;
transform.SetParent (pivot.transform);
}
void Update () {
pivot.transform.eulerAngles += new Vector3 (Input.GetAxis ("Mouse Y") * -sensitivityX * Time.deltaTime, Input.GetAxis ("Mouse X") * sensitivityY * Time.deltaTime, 0);
}
}
Assign this script to your camera, then in Inspector Tab, with the camera selected, assign your Cube (drag) into the "cube" slot, and assign a value to the sensitivity fields (i used something about 500), press play and test.
What does this script do?
It creates a new GameObject at the center of the Cube to be a reference of rotation, it's called pivot. So it sets the Camera as a child of the pivot, and rotates the pivot according with your mouse axis.
I wrote this way:
float mouseX = -Input.GetAxis("Mouse X");
float mouseY = -Input.GetAxis("Mouse Y");
float magnitude = transform.position.magnitude;
Vector3 mouseSwipe = new Vector3(mouseX, mouseY, 0);
Vector3 startPoint = new Vector3((float)camera.pixelWidth / 2, (float)camera.pixelHeight / 2, magnitude - 1);
Vector3 startPointWorld = camera.ScreenToViewportPoint(startPoint);
Vector3 endPointWord = camera.ScreenToViewportPoint(startPoint + mouseSwipe);
Vector3 mouseSwipeWord = endPointWord - startPointWorld;
float dragLat = mouseSwipeWord.y;
float dragLng = mouseSwipeWord.x;
Vector3 oldPosition = transform.position / magnitude;
float lat = Mathf.Asin(oldPosition.y);
float rsmall = Mathf.Acos(oldPosition.y);
float lng = Mathf.Atan2(oldPosition.z / rsmall, oldPosition.x / rsmall);
lat += dragLat * 10 * 2 * Mathf.PI;
if( lat*180/Mathf.PI > 80 )
{
lat = 80 * Mathf.PI / 180;
}
else if( lat*180/Mathf.PI < -80)
{
lat = -80 * Mathf.PI / 180;
}
lng += dragLng * 10 * 2 * Mathf.PI * 2;
float y = Mathf.Sin(lat);
rsmall = Mathf.Cos(lat);
float x = rsmall * Mathf.Cos(lng);
float z = rsmall * Mathf.Sin(lng);
Vector3 newPosition = new Vector3(x, y, z);
newPosition *= magnitude;
transform.position = newPosition;
LookAtTarget();
The goal was to simulate mouse is rotation object by drag.
I'm trying to write a very simple 3d model viewer that allows the user to click and drag on the x and y axes to rotate an object. The problem I am facing with my included code sample is that, when I rotate something, say, about the y axis, and then try to rotate about the x axis, I find that the object is rotated about the object's x axis instead of the x-axis from the perspective of the camera.
I'm effectively trying to simulate rotating something along the z-axis, albeit through two motions.
public Transform obj;
private Vector3 screenPoint;
private Vector3 offset;
//public float minX = 270.0f;
//public float maxX = 360.0f;
//public float minY = -90.0f;
//public float maxY = 90.0f;
public float sensX = 100.0f;
public float sensY = 100.0f;
float rotationY = 0.0f;
float rotationX = 0.0f;
float posX = 0.0f;
float posY = 0.0f;
void Update() {
if (Input.GetMouseButton(0)) {
rotationX += Input.GetAxis("Mouse X") * sensX * Time.deltaTime;
//rotationX = Mathf.Clamp(rotationX, minX, maxX);
rotationY += Input.GetAxis("Mouse Y") * sensY * Time.deltaTime;
//rotationY = Mathf.Clamp(rotationY, minY, maxY);
Quaternion q = Quaternion.Euler(rotationY, -rotationX, 0);
transform.rotation = q;
}
if (Input.GetMouseButton(1)) {
posX += Input.GetAxis("Mouse X") * 25.0f * Time.deltaTime;
posY += Input.GetAxis("Mouse Y") * 25.0f * Time.deltaTime;
transform.position = new Vector3(posX, posY, 0);
}
}
If you are looking to rotate around the z-axis, you could try the transform.RotateAround function. This will allow you to specify a point (as a Vector3), a rotation axis (again as a Vector3), and a degree to which to rotate. This function can modify both the position and the rotation elements of your transform.