How do I make the border of a map and the panning of that map the same? - unity3d

I am using a map bigger than the screen I viewing. Therefore I need to be able to pan around that map. I am having a problem with clamping the camera and the map. I want to be able to use the demension of the image as the width and height of the clamp. The problem is the units.
The image is 2144 x 1708
The camera transposition is in single digits (14 x 7) or something like that.
All of the code I am using is below.
private Vector3 mouseOrigin; // Position of cursor when mouse dragging starts
private bool isPanning; // Is the camera being panned?
public bool useBoundary = true;
public Vector2 boundaryMin;
public Vector2 boundaryMax;
public Image map;
private void Start()
{
Camera cam = Camera.main;
float mapRatio = map.rectTransform.rect.width / map.rectTransform.rect.height;
float mapScreenHeight = (1.5f * cam.orthographicSize);
float mapScreenWidth = (3f * mapScreenHeight) * cam.aspect;
boundaryMin = new Vector2(0, 1);
boundaryMax = new Vector2(map.rectTransform.rect.width, map.rectTransform.rect.height);
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
mouseOrigin = Input.mousePosition;
isPanning = true;
}
// Disable movements on button release
if (!Input.GetMouseButton(0))
isPanning = false;
if (isPanning)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
Vector3 move = new Vector3(pos.x * panSpeed, pos.y * panSpeed, 0);
transform.Translate(move, Space.Self);
BoundaryCheck();
}
}
private void BoundaryCheck()
{
if (!useBoundary)
return;
Vector3 newPos = transform.position;
newPos.x = Mathf.Clamp(newPos.x, boundaryMin.x, boundaryMax.x);
newPos.y = Mathf.Clamp(newPos.y, boundaryMin.y, boundaryMax.y);
transform.position = newPos;
}
}
Any help would be greatly appreciated.

You can do this using Unity UI - Scroll Rect.
Check out Unity UI - Scroll Rect - Introduction

In my opinion you should need to use below script for camera panning, zooming and rotating. You can off any undesirable function. Now according to your question you have to restrict the movement(according to your image border). simply you can restrict the camera movements on differet axis according to your limitations. You should place cubes into the borders of the map and use their positions as the limit of camera movement and panning etc.
using UnityEngine;
using System.Collections;
public class CamMovementManager : MonoBehaviour
{
#region Vars
public float turnSpeed = 1.0f; // Speed of camera turning when mouse moves in along an axis
public float panSpeed = 4.0f; // Speed of the camera when being panned
public float zoomSpeed = 4.0f; // Speed of the camera going back and forth
private Vector3 mouseOrigin; // Position of cursor when mouse dragging starts
private bool isPanning; // Is the camera being panned?
private bool isRotating; // Is the camera being rotated?
private bool isZooming; // Is the camera zooming?
private float pannPosLimit = 300f;
private int fovMin = 15;
private int fovMax = 90;
#endregion Vars
#region UnityEvents
void Update()
{
// Get the left mouse button
if (Input.GetMouseButtonDown(0))
{
// Get mouse origin
mouseOrigin = Input.mousePosition;
isRotating = true;
}
// Get the right mouse button
if (Input.GetMouseButtonDown(1))
{
// Get mouse origin
mouseOrigin = Input.mousePosition;
isPanning = true;
}
// Get the middle mouse button
if (Input.GetMouseButtonDown(2))
{
// Get mouse origin
//mouseOrigin = Input.mousePosition;
//isZooming = true;
}
//changing fov on mouse scroll to zoomIn/out
float fov = Camera.main.fieldOfView;
fov += Input.GetAxis("Mouse ScrollWheel") * 10f;
fov = Mathf.Clamp(fov, fovMin, fovMax);
Camera.main.fieldOfView = fov;//*/
// Disable movements on button release
if (!Input.GetMouseButton(0)) isRotating = false;
if (!Input.GetMouseButton(1)) isPanning = false;
if (!Input.GetMouseButton(2)) isZooming = false;
// Rotate camera along X and Y axis
if (isRotating)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
//Debug.Log("rotate pos : " + pos);
transform.RotateAround(transform.position, transform.right, -pos.y * turnSpeed);
transform.RotateAround(transform.position, Vector3.up, pos.x * turnSpeed);
}
// Move the camera on it's XY plane
if (isPanning)
{
if (Input.mousePosition.y > pannPosLimit)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
Vector3 move = new Vector3(pos.x * panSpeed, pos.y * panSpeed, 0);
transform.Translate(move, Space.Self);
}
}
// Move the camera linearly along Z axis
if (isZooming)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
Vector3 move = pos.y * zoomSpeed * transform.forward;
transform.Translate(move, Space.World);
}
}
#endregion
#region CustomMethods
public void CamRotating()
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
transform.RotateAround(transform.position, transform.right, -pos.y * turnSpeed);
transform.RotateAround(transform.position, Vector3.up, pos.x * turnSpeed);
}
public void CamPanning()
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
Vector3 move = new Vector3(pos.x * panSpeed, pos.y * panSpeed, 0);
transform.Translate(move, Space.Self);
}
public void CamZooming()
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
Vector3 move = pos.y * zoomSpeed * transform.forward;
transform.Translate(move, Space.World);
}
#endregion CustomMethods
}

Related

unity2d, trajectory prediction shaking

I'm making a mobile game that uses trajectory to find out the next path from my player. When the player is silent the trajectory works very well, but when the player is moving the trajectory sometimes moves on its own even though it returns to its proper position later, but this is very disturbing.
Here's the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerMovement : MonoBehaviour
{
public static PlayerMovement Instance;
Rigidbody2D rb;
Vector3 startPos;
Vector3 endPos;
[HideInInspector] public Vector3 initPos;
[HideInInspector] public Vector3 direction;
public static Vector3 anotherSpeed; // Only for trajectory
float speedMultiplier = 1.5f;
public GameObject trajectoryDot;
GameObject[] trajectoryDots;
public int numbersOfTrajectory;
float trajectoryDotsDistance = 0.001f;
public static float energy = 100f;
public Slider energyBar;
float slowDownFactor = 0.3f;
private void Start()
{
if (!Instance)
Instance = this;
rb = GetComponent<Rigidbody2D>();
trajectoryDots = new GameObject[numbersOfTrajectory];
}
void Update()
{
anotherSpeed = direction;
if (!Pause.isPaused)
{
// Get Start Position
if (Input.GetMouseButtonDown(0))
{
// Instansiate The Trajectory
for (int i = 0; i < numbersOfTrajectory; i++)
{
trajectoryDots[i] = Instantiate(trajectoryDot,gameObject.transform.position, gameObject.transform.rotation);
}
}
// Get Position When Dragging
if (Input.GetMouseButton(0))
{
EnableSlowMotion();
// Get Drag Position
endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition) + new Vector3(0, 0, 10);
startPos = gameObject.transform.position;
// Get The Speed
direction = endPos - startPos;
direction = direction.normalized;
direction = Vector3.Lerp(transform.position, direction, 500 * Time.deltaTime);
direction = direction * 18;
// Update The Trajectory Position
for (int i = 0; i < numbersOfTrajectory; i++)
{
trajectoryDots[i].transform.position = calculatePosition(i * trajectoryDotsDistance);
}
}
// Get Position When Realeasing
if (Input.GetMouseButtonUp(0))
{
DisableSlowMotion();
// enable Gravity
rb.gravityScale = 1f;
// Move The Player
rb.velocity = new Vector2(direction.x * speedMultiplier, direction.y * speedMultiplier);
// Destroy The Trajectory When Player Release
for (int i = 0; i < numbersOfTrajectory; i++)
{
Destroy(trajectoryDots[i]);
}
}
}
CameraZoom();
ControlsChecker();
}
// Calculate The Trajectory Prediction
Vector2 calculatePosition(float elapsedTime)
{
return new Vector2(startPos.x, startPos.y) +
new Vector2(anotherSpeed.x * speedMultiplier, anotherSpeed.y * speedMultiplier) * elapsedTime +
0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}
// Check Controls Is pull or push
void ControlsChecker()
{
if (PlayerPrefs.GetInt("Controls") == 1)
{
direction = direction;
anotherSpeed = anotherSpeed;
}
else
{
direction = -direction;
anotherSpeed = -anotherSpeed;
}
}
void EnableSlowMotion()
{
Time.timeScale = slowDownFactor;
Time.fixedDeltaTime = 0.02f * Time.timeScale;
}
void DisableSlowMotion()
{
Time.timeScale = 1f;
Time.fixedDeltaTime = 0.02F;
}
}
void CameraZoom()
{
if (Input.GetMouseButton(0))
{
vcam.m_Lens.OrthographicSize += 0.1f;
if (vcam.m_Lens.OrthographicSize >= maxZoom)
{
vcam.m_Lens.OrthographicSize = maxZoom;
}
}
else if (Input.GetMouseButtonUp(0))
{
zoomIn = true;
}
if (zoomIn)
{
vcam.m_Lens.OrthographicSize -= 0.2f;
if (vcam.m_Lens.OrthographicSize <= minZoom)
{
vcam.m_Lens.OrthographicSize = minZoom;
zoomIn = false;
}
}
}
so I get the player's movement direction from the calculation based on the point where I touch and the point when I release touch (dragging). Did I make a mistake in the code that caused my trajectory to vibrate often? I really need help here, thanks in advance.

Unity camera problem - Moving FPS/TPS camera to look at a target and resuming player control

I am having trouble with aligning my player controlled camera (I use the same class for FPS and TPS) to look at a target (when ResetCamera() is called by another script) and then getting the player to resume control. The main reason I am doing this is so I can switch between FPS and TPS cameras and remain looking at the same target.
I can look at the target fine, but ONLY if I stop setting the rotation based on yaw and pitch (from "Mouse X" and "Mouse Y" inputs) in LateUpdate() after I set the lookAtTarget in ResetCamera(), but that means the player can no longer look around.
However, I cannot figure out how to get the correct yaw and pitch values after this so the player can continue looking around from the new look at target. How could I do this so the player could continue looking around?
public class PlayerCamera : MonoBehaviour {
public float mouseSensitivity = 10f;
public Transform target;
public float dstFromTarget = 2f;
public Vector2 pitchConstraints = new Vector2(-20f, 85f);
public float rotSmoothTime = .12f;
Vector3 rotSmoothVel;
Vector3 currRot;
float yaw;
float pitch;
void LateUpdate() {
yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
pitch = Mathf.Clamp(pitch, pitchConstraints.x, pitchConstraints.y);
currRot = Vector3.SmoothDamp(currRot, new Vector3(pitch, yaw), ref rotSmoothVel, rotSmoothTime);
transform.eulerAngles = currRot;
transform.position = target.position - transform.forward * dstFromTarget;
}
public void ResetCamera(Transform lookAtTarget) {
transform.LookAt(lookAtTarget);
// below gets yaw and pitch values that move the camera to look at the
// wrong location
// yaw = transform.eulerAngles.x;
// pitch = transform.eulerAngles.y;
// pitch = Mathf.Clamp(pitch, pitchConstraints.x, pitchConstraints.y);
// currRot = new Vector3(pitch, yaw);
}
}
So, I figured out how to do what I wanted. Below is a script for a third or first person (just adjust the dstFromTarget variable to zero) camera that can be rotated to look at a target by another script with ResetCamera() and the player can resume moving around from that point.
public class PlayerCamera : MonoBehaviour {
public bool isFirstPerson = false;
public float mouseSensitivity = 10f;
public Transform target;
public float dstFromTarget = 2f;
public bool invertedPitch = false;
public float smoothTime = .12f;
public float minimumX = -85f;
public float maximumX = 85f;
// LateUpdate, so the Camera Target will definitely have been set
void LateUpdate () {
// first person updating is handled by Inverse kinematics stuff in my case
if (isFirstPerson) return;
UpdateStuff();
}
public void UpdateStuff() {
float yaw = Input.GetAxisRaw("Mouse X");
float pitch = -Input.GetAxisRaw("Mouse Y");
if (invertedPitch) {
pitch *= -1f;
}
Vector3 yRot = new Vector3(0f, yaw, 0f) * mouseSensitivity;
Vector3 xRot = new Vector3(pitch, 0f, 0f) * mouseSensitivity;
xRot = ClampRotationAroundXAxis(transform.rotation, xRot);
Transform newTrans = transform;
newTrans.Rotate(xRot);
newTrans.Rotate(yRot, Space.World);
transform.rotation = Quaternion.Slerp(transform.rotation, newTrans.rotation, smoothTime * Time.deltaTime);
transform.position = target.position - transform.forward * dstFromTarget;
}
public void ResetCamera(Transform lookAtTarget) {
transform.LookAt(lookAtTarget);
}
Vector3 ClampRotationAroundXAxis(Quaternion q, Vector3 xrot) {
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1.0f;
float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
if (angleX < minimumX && xrot.x < 0f) {
xrot = Vector3.zero;
}
if (angleX > maximumX && xrot.x > 0f) {
xrot = Vector3.zero;
}
return xrot;
}
}

How to Move an Object On Y Axis with Mouse in Unity

I want control the transform with mouse just for Y axis as it is moving on X axis by it self.
I use Vector2.MoveTowards to move it on X axis.
The transform must be moved by any touch and drag on the screen. So I wrote my codes in the Update function
My Codes :
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour
{
public Camera playerCamera;
public float speed = 12.0F;
private Vector3 moveDirection = Vector3.zero,Point,last;
void Start()
{
Point = transform.position;
last = transform.position;
if (playerCamera == null)
{
playerCamera = Camera.main;
}
playerCamera.transparencySortMode = TransparencySortMode.Orthographic;
}
void Update(){
if(Input.GetMouseButtonUp(0))
Point = last;
moveDirection.x = transform.position.x+speed;
moveDirection.y = transform.position.y;
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
last = ray.GetPoint (0);
transform.position = new Vector2 (transform.position.x, last.y - Point.y);
}
else
transform.position = Vector2.MoveTowards( transform.position,moveDirection,speed*Time.deltaTime);
//moveDirection.y -= 20.0f * Time.smoothDeltaTime;
//After we move, adjust the camera to follow the player
playerCamera.transform.position = new Vector3(transform.position.x, playerCamera.transform.position.y , playerCamera.transform.position.z);
}
}
How can I solve it?

Orthographic camera zoom with focus on a specific point

I have an orthographic camera and would like to implement a zoom feature to a specific point. I.e., imagine you have a picture and want to zoom to a specific part of the picture.
I know how to zoom in, the problem is to move the camera to a position that has the desired zone in focus.
How can I do so?
The camera's orthographicSize is the number of world space units in the top half of the viewport. If it's 0.5, then a 1 unit cube will exactly fill the viewport (vertically).
So to zoom in on your target region, center your camera on it (by setting (x,y) to the target's center) and set orthographicSize to half the region's height.
Here is an example to center and zoom to the extents of an object. (Zoom with LMB; 'R' to reset.)
public class OrthographicZoom : MonoBehaviour
{
private Vector3 defaultCenter;
private float defaultHeight; // height of orthographic viewport in world units
private void Start()
{
defaultCenter = camera.transform.position;
defaultHeight = 2f*camera.orthographicSize;
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Collider target = GetTarget();
if(target != null)
OrthoZoom(target.bounds.center, target.bounds.size.y); // Could directly set orthographicSize = bounds.extents.y
}
if (Input.GetKeyDown(KeyCode.R))
OrthoZoom(defaultCenter, defaultHeight);
}
private void OrthoZoom(Vector2 center, float regionHeight)
{
camera.transform.position = new Vector3(center.x, center.y, defaultCenter.z);
camera.orthographicSize = regionHeight/2f;
}
private Collider GetTarget()
{
var hit = new RaycastHit();
Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit);
return hit.collider;
}
}
hope you find this code example useful, should be a copy / paste.
Note: this script assume it's attached to the camera object, otherwise you should adjust the transform to the camera object reference.
private float lastZoomDistance = float.PositiveInfinity; // remember that this should be reset to infinite on touch end
private float maxZoomOut = 200;
private float maxZoomIn = 50;
private float zoomSpeed = 2;
void Update() {
if (Input.touchCount >= 2) {
Vector2 touch0, touch1;
float distance;
Vector2 pos = new Vector2(transform.position.x, transform.position.y);
touch0 = Input.GetTouch(0).position - pos;
touch1 = Input.GetTouch(1).position - pos;
zoomCenter = (touch0 + touch1) / 2;
distance = Vector2.Distance(touch0, touch1);
if(lastZoomDistance == float.PositiveInfinity) {
lastZoomDistance = distance;
} else {
if(distance > lastZoomDistance && camera.orthographicSize + zoomSpeed <= maxZoomOut) {
this.camera.orthographicSize = this.camera.orthographicSize + zoomSpeed;
// Assuming script is attached to camera - otherwise, change the transform.position to the camera object
transform.position = Vector3.Lerp(transform.position, zoomCenter, Time.deltaTime);
} else if(distance < lastZoomDistance && camera.orthographicSize - zoomSpeed >= maxZoomIn) {
this.camera.orthographicSize = this.camera.orthographicSize - zoomSpeed;
transform.position = Vector3.Lerp(transform.position, zoomCenter, Time.deltaTime);
}
}
lastZoomDistance = distance;
}
}

MouseOrbit Customization: Place camera on spot orbit

I have a MouseOrbit script based on the Standard Assets Script that I need to customize to place the camera in a specific spot in the orbit.
Heres the basics of the standard script that ships with Unity3d:
function Start () {
var angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
}
function onUpdate(){
x += Input.GetAxis("Mouse X") * xSpeed;
y -= Input.GetAxis("Mouse Y") * ySpeed;
var rotation = Quaternion.Euler(y, x,0);
var position = rotation * Vector3(0.0, 0.0, cameraDelta);
transform.rotation = rotation;
transform.position = position;
}
What I need to do is place the camera in a few spots around the target object at 0,0.
The first is directly behind the object. x:7,:y0,z:0.
Here's what I thought would work:
function TransformCamera(x,y,z){
//set position of camera
transform.position = new Vector3(x, y, z);
var angles = transform.eulerAngles;
y = angles.y;
x = angles.x;
z = angles.z;
var rotation = Quaternion.Euler(y, x, z);
var position = rotation * Vector3(0.0, 0.0, cameraDelta);
//adjusted_target;
transform.rotation = rotation;
transform.position = position;
}
This script is close... it transforms the camera and rotates it to look at the object, but it doesn't place the camera in the correct location 7,0,0.
Thanks!
Try this modified script. i hope this will solve your problem.
using UnityEngine;
using System.Collections;
public class OrbitCamera : MonoBehaviour
{
//The target of the camera. The camera will always point to this object.
public Transform _target;
//The default distance of the camera from the target.
private float _distance ;
//Control the speed of zooming and dezooming.
public float _zoomStep = 1.0f;
//The speed of the camera. Control how fast the camera will rotate.
public float _xSpeed = 1f;
public float _ySpeed = 1f;
//The position of the cursor on the screen. Used to rotate the camera.
private float _x = 0.0f;
private float _y = 0.0f;
//Distance vector.
private Vector3 _distanceVector;
/**
* Move the camera to its initial position.
*/
void Start ()
{
_distanceVector = new Vector3(0.0f,0.0f,-this.transform.position.z);
_distance = this.transform.position.z;
Vector2 angles = this.transform.localEulerAngles;
_x = angles.x;
_y = angles.y;
this.Rotate(_x, _y);
}
/**
* Rotate the camera or zoom depending on the input of the player.
*/
void LateUpdate()
{
if ( _target )
{
this.RotateControls();
this.Zoom();
}
}
/**
* Rotate the camera when the first button of the mouse is pressed.
*
*/
void RotateControls()
{
if ( Input.GetButton("Fire1") )
{
_x += Input.GetAxis("Mouse X") * _xSpeed;
_y += -Input.GetAxis("Mouse Y")* _ySpeed;
this.Rotate(_x,_y);
}
}
/**
* Transform the cursor mouvement in rotation and in a new position
* for the camera.
*/
void Rotate( float x, float y )
{
//Transform angle in degree in quaternion form used by Unity for rotation.
Quaternion rotation = Quaternion.Euler(y,x,0.0f);
//The new position is the target position + the distance vector of the camera
//rotated at the specified angle.
Vector3 position = rotation * _distanceVector + _target.position;
//Update the rotation and position of the camera.
transform.rotation = rotation;
transform.position = position;
}
/**
* Zoom or dezoom depending on the input of the mouse wheel.
*/
void Zoom()
{
if ( Input.GetAxis("Mouse ScrollWheel") < 0.0f )
{
this.ZoomOut();
}
else if ( Input.GetAxis("Mouse ScrollWheel") > 0.0f )
{
this.ZoomIn();
}
}
/**
* Reduce the distance from the camera to the target and
* update the position of the camera (with the Rotate function).
*/
void ZoomIn()
{
_distance -= _zoomStep;
_distanceVector = new Vector3(0.0f,0.0f,-_distance);
this.Rotate(_x,_y);
}
/**
* Increase the distance from the camera to the target and
* update the position of the camera (with the Rotate function).
*/
void ZoomOut()
{
_distance += _zoomStep;
_distanceVector = new Vector3(0.0f,0.0f,-_distance);
this.Rotate(_x,_y);
}
} //End class