Smooth camera causes zoom factor to change - android-camera

I have a game play scene in which the user can zoom in and out, for which I used smooth camera in the following manner:
public static final int CAMERA_WIDTH = 1024;
public static final int CAMERA_HEIGHT = 600;
public static final float MAXIMUM_VELOCITY_X = 400f;
public static final float MAXIMUM_VELOCITY_Y = 400f;
public static final float ZOOM_FACTOR_CHANGE = 1f;
mSmoothCamera = new SmoothCamera(0, 0,
Constants.CAMERA_WIDTH,
Constants.CAMERA_HEIGHT,
Constants.MAXIMUM_VELOCITY_X,
Constants.MAXIMUM_VELOCITY_Y,
Constants.ZOOM_FACTOR_CHANGE);
mSmoothCamera.setBounds(0f, 0f,
Constants.CAMERA_WIDTH,
Constants.CAMERA_HEIGHT);
But the above creates a problem for me. When the user performs zoom-in and leaves game play scene, then other scene behaviours do not look good. I have set zoom factor to 1 to fix this. But now it shows camera translation in other scenes. Because scene switching time it so short, the player can easily see camera translation, which is something I don't want. After the camera repositions, everything works perfect but how do I set camera position properly?
For example, my loading text moves from bottom to top or vice versa, based on camera movement. Please let me know if I can provide more details.

Please give more detail so that I can help you, or you can use the following method:
mSmoothCamera.setMaxVelocity() method and mSmoothCamera.setCenter()
And increase your MAXIMUM_VELOCITY_X and MAXIMUM_VELOCITY_Y value, e.g. to more than 800 or 1000. Example:
mSmoothCamera.setMaxVelocity(x, y)
where x = MAXIMUM_VELOCITY_X and y = MAXIMUM_VELOCITY_Y.
Following is optional:
mSmoothCamera.setCenter(as_per_your_requirement);
where as_per_your_requirement means the camera center.

I don`t know if this issue is still valid but I had also this issue, try use mCamera.setZoomFactorDirect(1.0f); in your menu scene constructor.
It`s works for me

Related

Unity 2D - Keep Player Object in Boundary of it's Parent Panel

In Unity i have a UI Panel which has a player object (an UI Image object).
I moving player object into planel with user inputs (keyboard or touch)
I can't keep player object in it's parent panel,
Please check below image, I want to keep player inside of Red Panel
Here is my Tried Code
public Camera MainCamera; //be sure to assign this in the inspector to your main camera
private Vector2 screenBounds;
private float objectWidth;
private float objectHeight;
private RectTransform pnlBackgroundTransform;
private void Start()
{
pnlBackgroundTransform = GameObject.Find("PnlBackground").GetComponent<RectTransform>();
screenBounds = MainCamera.ScreenToWorldPoint(new Vector3(pnlBackgroundTransform.rect.width , pnlBackgroundTransform.rect.height , MainCamera.transform.position.z));
objectWidth = transform.GetComponent<SpriteRenderer>().bounds.extents.x; //extents = size of width / 2
objectHeight = transform.GetComponent<SpriteRenderer>().bounds.extents.y; //extents = size of height / 2
}
void LateUpdate()
{
Vector3 viewPos = transform.position;
viewPos.x = Mathf.Clamp(viewPos.x, screenBounds.x * -1 + objectWidth, screenBounds.x - objectWidth);
viewPos.y = Mathf.Clamp(viewPos.y, screenBounds.y * -1 + objectHeight, screenBounds.y - objectHeight);
Debug.Log(screenBounds);
Debug.Log(viewPos);
transform.position = viewPos;
}
I'd say it's not very usual having the player implemented as a UI element, and instead you should be implementing it outside the UI/Canvas system.
The UI/Canvas system uses a set of rules of placing and scaling to deal with responsive design. You have at least 4 values (excluding rotation) to place something on the screen: anchor, pivot, position and scale.
For example: if you want to create a square you can either set it's size in absolute pixel values or relative values (to parent). If you're using absolute values, your UI Scale Mode, defined on the Canvas object, should affect the visual results.
This means the UI/Canvas is for elements that should adapt to the screen, such as buttons, dialogs, labels, etc. Taking advantage of device parameters to improve the UX.
Outside the UI/Canvas system, things are directly based on Linear Algebra: you have a 3D vector space (a "World") where everything exists with an absolute size and position. Then, your Camera stretches and twists the whole world to match what your current perspective. That means your object will always have the same size, regardless of screen size.
Now, assuming you have a very specific reason to implement your game into UI, there are a few ways you can do it. I'll assume you're using absolute values. Please note all the units used here are pixels, and the effect should be different for devices with different resolutions and sensible to the UI Scale Mode parameter. Also, please note I've set both anchors min and max to (0,0), the bottom left corner (default is screen center, (0.5,0.5)), in order to avoid negative coordinates.
The following script is attached to the player's UI Image.
public class UIMovementController : MonoBehaviour
{
public float speed = 5.0f;
new private RectTransform transform;
private Rect canvasRect;
private void Start()
{
transform = GetComponent<RectTransform>();
canvasRect = GetComponentInParent<Canvas>().pixelRect;
}
void Update()
{
// Keyboard Input (Arrows)
Vector2 move = new Vector2(0,0);
if (Input.GetKey(KeyCode.UpArrow)) { move.y += speed; }
if (Input.GetKey(KeyCode.DownArrow)) { move.y -= speed; }
if (Input.GetKey(KeyCode.LeftArrow)) { move.x -= speed; }
if (Input.GetKey(KeyCode.RightArrow)) { move.x += speed; }
transform.anchoredPosition += move;
// Position clamping
Vector2 clamped = transform.anchoredPosition;
clamped.x = Mathf.Clamp(clamped.x, transform.rect.width / 2, canvasRect.width - transform.rect.width / 2);
clamped.y = Mathf.Clamp(clamped.y, transform.rect.height / 2, canvasRect.height - transform.rect.height / 2);
transform.anchoredPosition = clamped;
}
}

Unity3d Linerenderer not visible

I am trying to draw a line between two UI GameObjects with Linerenderer. In scene mode everything work fine, but in game mode line is invisible. I tried to change Z position of objects but lines are still invisible. Can anyone help me? Thanks in advance
private LineRenderer lineRenderer;
private float counter;
private float dist;
private Vector3 aPos;
private Vector3 bPos;
public Transform origin;
public Transform destination;
public float lineDrawSpeed = 6f;
// Use this for initialization
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
aPos = new Vector3(origin.position.x, origin.position.y, origin.position.z); // Using these to move the lines back
bPos = new Vector3(destination.position.x, destination.position.y, destination.position.z);
lineRenderer.SetPosition(0, aPos);
lineRenderer.SetWidth(3f, 3f);
dist = Vector3.Distance(origin.position, destination.position);
}
// Update is called once per frame
void Update()
{
if (counter < dist)
{
counter += .1f / lineDrawSpeed;
float x = Mathf.Lerp(0, dist, counter);
Vector3 pointA = aPos;
Vector3 pointB = bPos;
Vector3 pointAloneLine = x * Vector3.Normalize(pointB - pointA) + pointA;
lineRenderer.SetPosition(1, pointAloneLine);
}
}
Unless I'm overlooking some logic error in the code you've posted, I think the problem might be with the material.
Generic debugging help for line renderers:
Try setting the color/material of the line renderer:
lineRenderer.sortingOrder = 1;
lineRenderer.material = new Material (Shader.Find ("Sprites/Default"));
lineRenderer.material.color = Color.red;
If that doesn't work, perhaps you need to specify the number of vertexes manually?
mineLaser.SetVertexCount (2);
Finally, if these both don't work, it might just be a logic error; try setting the transforms for the lineRenderer's position to be some predefined value and see if it shows up.
For this specific question:
Ah, so its on a canvas. Assuming you mean the UI canvas, I believe linerenderer is the wrong tool to use in this situation. Check out this question.
One of the answers there suggests to:
just use a panel filled with any color you want and use Height and Width to set the length and the Width of your line
This is impossible in "Screen Space - Overlay" Canvas mode. In that mode UI overlay draws on top of everything in Scene (including LineRenderer, that actually non UI element).
Try to use "Screen Space - Camera" option for your Canvas and "Use World Space" option for you Line Renderer.
I think you must have forgotten to set sorting layer for the line renderer. As this could only be the possible reason if the line is visible in the scene view and not in the game view.

how to get background to scroll with player height in unity?

I am making an endless jumper. I am trying to get the BG to scroll down based on the players height.
I have seen code that moves the code at a specific speed:
public float speed = .5f;
void Updated(){
Vector2 offset = new Vector2(0, Time.deltatime * speed);
GetComponent<Renderer>().material.mainTextureOffset = offset;
}
I want to move it with the height of the player.
public float PlayerHeight;
So now I need to set the height of the BG. I can't figure out how to do this part.
Transform background;
public float backgroundHeightY;
public GameObject BackGround;
from here I am stuck. I don't want it to move with the camera, but move at a certain rate based on the height of the player. Any help would be awesome.
It sounds like you have a background that has a fixed position relative to the camera, but you want the background to scroll "against" the player as they move up and down, giving a parallax effect?
public Transform player;
public float multiplier = 0.1f; //Tweak this
void Update(){
Vector2 offset = new Vector2(0, player.position.y * multiplier);
GetComponent<Renderer>().material.mainTextureOffset = offset;
}
I have it working well going up, but not down. Here is how it is working going up. I have adjusted the backgroundModifier to fit the timing I need.
//Changes the BG position
changeAmount = (playerHeightY - currentCameraHeight)/backgroundModifier;
Vector3 temp = new Vector3(0, changeAmount, 0);
BackGround.transform.position += temp;
Anyone have an idea on how to get the falling to work. I feel like I am making this harder than it needs to be.
Here is how I finally did this. I actually switched the camera from orthographic to perspective. It took a lot of tweaking to layout, but it ended up working perfectly well. So the code I have above I deleted.

How can i turn the camera to left and right in unity for a sphere?

updated CODE .. the problem is that i cant move the ball only if i hold the E button than i use WASD or arrows to move the ball...and when i hold Q the camera 2 activates and i can move the ball with WASD or arrows...but with the right axis for that angle...is like ballance that game... i want to not hold the E or Q just to change the camera and move the ball corecctly for that angle with the right axis for the ball but not holding the cameras button
using UnityEngine;
using System.Collections;
public class controlPlayer : MonoBehaviour {
public float viteza ; // this is speed
;
void Start(){
}
void Update()
{
if(Input.GetKey(KeyCode.Q) ) // if i hold Q the camera 2 activates and with WASD i can move the ball
{
float miscaOrizontal = Input.GetAxis("Horizontal");
float miscaVertical = Input.GetAxis("Vertical");
Vector3 miscare = new Vector3(miscaVertical,0.0f,(-miscaOrizontal)); //also here i chande the axis for the camera 2
rigidbody.AddForce(miscare * viteza * Time.deltaTime);
}
if(Input.GetKey(KeyCode.E) ) // here when i press E the camera 1 activates and alos i can move the ball if i keep pressing E
{ float miscaOrizontal2 = Input.GetAxis("Horizontal");
float miscaVertical2 = Input.GetAxis("Vertical");
Vector3 miscare2 = new Vector3(miscaOrizontal2,0.0f,miscaVertical2); // here are the controls for the ball for the camera ..i had to change the axis here..
rigidbody.AddForce(miscare2 * viteza * Time.deltaTime);
}
}
}
}
Alright, so if I'm understanding you correctly, you want the ball to move in relation to which direction the camera is currently facing. As well as you don't want to have to hold down "Q" or "E" while you move your ball with WASD controls.
So there are a few things that I'd like to mention here, so we'll take them one at a time. First off, you shouldn't have "AddForce" inside of an Update call. Update is called every frame whenever it can. It's great for input, but generally you want to call it in "FixedUpdate" instead. It provides a better response across many devices. If you leave it in update, you can get inaccurate physics results, and missed collisions. There's a lot out there on this subject, so if you want to know more about it, then just google for a little while.
As for the code side, you want to store a reference to what camera you're using to avoid having to hold these buttons down.
What I mean is:
private Camera referencedCamera = null;
private void Start()
{
referencedCamera = camera1;
}
private void Update()
{
if(Input.GetKey(KeyCode.Q)) referencedCamera = camera2;
else if(Input.GetKey(KeyCode.E)) refrencedCamera = camera1;
}
This way you can reference which camera is being used, rather than a key input. Something else to look into is the "State Design Pattern". Below is a video over the "State Design Pattern." That is a great video tutorial series that Derek Banas put up on design patterns, extremely recommend watching them, but the state pattern could potentially solve this problem for you as well. So that should take care of not having to hold the button down in order to make the move. More or less, the buttons will now allow you to just switch which camera is currently being used.
https://www.youtube.com/watch?v=MGEx35FjBuo
So now that that is solved, you want to transform the input that you currently have, and you want to put it in terms of hte camera that is currently being used. So to avoid rewriting a lot of the code over and over again, just know that these two code snippets should be pieced together into one. So "referencedCamera" should be already defined in the code I'm about to write:
private void FixedUpdate()
{
if(referencedCamera != null)
{
float miscaOrizontal = Input.GetAxis("Horizontal");
float miscaVertical = Input.GetAxis("Vertical");
Vector3 miscare = referencedCamera.transform.TransformDirection(
new Vector3(miscaVertical, 0.0f, -miscaOrizontal));
rigidbody.AddForce(miscare * viteza * Time.deltaTime);
}
}
So now with this, is it's the same code, but there is a call to the referenced cameras transform to take the vector 3 from the input and put it in relation to the camera instead, and add the new relational vector to the object.
I also want to recommend you looking into events rather than if checks in the update function, but that is beyond the scope of the question. Hope this helps and any questions, don't hesitate to ask.
EDIT
After further discussion, we came across something that should also be mentioned. If your camera that you are referencing is angled, the force will be applied in that angle, so keep that in mind. If it is pointed towards an object downward, then forward relative to the camera will apply a force downward, and not entirely in what you may consider the forward direction. Thought it was worth mentioning.

Unity 2D parallax background for all screen sizes

I come from the flash world and new to Unity and struggling with backgrounds in 2D for mobile. That is, struggling with understanding how to create a parallax background that will fit on all mobile devices. Actually doesn't even have to be parallax. I've read several post on the issue and tried several things but none of them work for me.
I've tried scripts that change the camera size, that scale the images etc. Outcome is never good as one scales the images and they don't look right and the other methods don't display critical parts of the background.
What have I missed with 2D backgrounds and how can I address it?
Thank-you
As you are new to Unity explaining each and everything may take brief answer.
Have a look on this script it will help you if it doesn't comment and ask.
Code :
using UnityEngine;
using System.Collections;
public class Done_BGScroller : MonoBehaviour
{
public float scrollSpeed;
public float tileSizeZ;
private Vector3 startPosition;
void Start ()
{
startPosition = transform.position;
}
void Update ()
{
float newPosition = Mathf.Repeat(Time.time * scrollSpeed, tileSizeZ);
transform.position = startPosition + Vector3.forward * newPosition;
}
}