Unity2D - On build, the background is shorter than it should be - unity3d

While in editor, everything's working fine, but when I build the game to my phone, the background seems to be short on top and bottom side.
This is a screenshot from the phone build.
This is a screenshot from Unity.
I checked all sizes and they were all the same - 800x1280. I think the problem started to happen when I made the cloudy background infinitely move with a quad.
Checked everywhere, can't seem to pin-point the problem.

You should resize the background according to screen size. You can do that through code. If you are using Sprite Renderer, you can follow this link to do so. Here's the main codes needed to resize a sprite according to the above link.
void Awake() {
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
float cameraHeight = Camera.main.orthographicSize * 2;
Vector2 cameraSize = new Vector2(Camera.main.aspect * cameraHeight, cameraHeight);
Vector2 spriteSize = spriteRenderer.sprite.bounds.size;
Vector2 scale = transform.localScale;
if (cameraSize.x >= cameraSize.y) { // Landscape (or equal)
scale *= cameraSize.x / spriteSize.x;
} else { // Portrait
scale *= cameraSize.y / spriteSize.y;
}
}
Or if you are using a UI Panel under Canvas to draw the background, you can set the anchors on the edge points and set the Canvas's UI Scale Mode to Scale With Screen Size

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;
}
}

Dynamically added LineRenderer doesn't show in game view

I add some line dynamically and they appear in the scene view perfectly, but not in game view. The z indexes are properly set, I use different layer just for the lines. I tried changing the camera clipping planes values, culling mask is on everything.
void Update()
{
Vector2 mousePos;
if (Input.GetMouseButtonDown(0))
{
Vector3 closeToPoint = IsClickCloseToPoint();
if (closeToPoint.z != -10000f)
{
GameObject newObj = Instantiate(lineGenerator);
startMousePos = closeToPoint;
newLine = newObj.GetComponent<LineRenderer>();
newLine.transform.SetParent(parentObject.transform);
newLine.positionCount = 2;
}
}
if (Input.GetMouseButton(0))
{
if (newLine != null)
{
mousePos = Input.mousePosition;
newLine.SetPosition(0, new Vector3(startMousePos.x, startMousePos.y, -5f));
newLine.SetPosition(1, new Vector3(mousePos.x, mousePos.y, -5f));
distance = (mousePos - startMousePos).magnitude;
distanceText.text = distance.ToString("F2");
}
}
if (Input.GetMouseButtonUp(0))
{
if (newLine != null)
{
newLine = null;
}
}
}
You are drawing everything on a canvas. But LineRenderer is not a UI component and therefore is not shown on the canvas.
If you want to work with LineRenderer nontheless check this info in Unity Answers. The basic idea is to have the canvas set up as Screen Space and increase the width of the lines. Don't forget to assign the camera.
i think you need to put a material on the lineRenderer. What you see in the scene view is the "non material" texture that doesn't appear in game view :)
I hope that help :)
Raph
The problem was that the coordinates are different in the scene view and the game view, or at least you have to design to the game view, not the scene view. My lines were present in the game view, but they were out of the canvas. I used Camera.main.ScreenToWorldPoint(Vektor3) to convert every vektor.
I can't see the Inspector settings of your LinRenderer but I suspect that you have
Alignment set to Transform Z
Lines face the Z axis of the Transform Component.
And thos becomes completely invisible if your orthographic Camera looks exactly in Z direction onto it.
Try and change the Alignment to View.
Also note that literally nothing is rendered on top of a ScreenSpace Overlay Canvas. It is one of the last things to be rendered in a frame.

Not able to get real position of an object in a Canvas with "Screen Space Overlay"

I have a mobile game with a BAR on the top of the screen. The bar and it's game objects are in canvas with "Screen Space - Overlay" mode plus a Canvas Scaler with scale mode of "Scale with Screen Size" and match equals "Match width or height".
I am animating a game object to the position of an object inside of this and the object is going completely of the screen (really far way).
I am trying to get the position of the object using code below.
Even so, the position being returned is complete of the screen. Any idea what I am doing wrong?
public Vector3 getObjectPosition()
{
// Getting my CANVAS
Camera cam = Camera.main;
GameObject canvasOverlayObject = GameObject.Find("CanvasOverlay");
Canvas canvas = canvasOverlayObject.GetComponent<Canvas>();
//Manual scalling the CANVAS
float canvasScaleX = Screen.width / canvasOverlayObject.GetComponent<CanvasScaler>().referenceResolution.x;
float canvasScaleY = Screen.height / canvasOverlayObject.GetComponent<CanvasScaler>().referenceResolution.y;
return Camera.main.ScreenToWorldPoint(new Vector3(transform.position.x / canvas.scaleFactor, transform.position.y / canvas.scaleFactor, 0));
}
No scaling was needed even using the scaled canvas, just passed the gameobject.tranform.position as the parameter.
public Vector3 getPosition()
{
Camera cam = Camera.main;
GameObject canvasOverlayObject = GameObject.Find("CanvasOverlay");
Canvas canvas = canvasOverlayObject.GetComponent<Canvas>();
Vector3 rawPosition = Camera.main.ScreenToWorldPoint(gameObject.transform.position);
return rawPosition;
}

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.

Unity 2D Android - Restrict object to within the screen

I am working on a 2D Game similar to Space Shooter. I developed it for Web and PC and it works great. I am now porting it to Android and am having an issue with the Player code.
The player(a space ship) will be at the bottom of the screen and it moves left to right within the screen. I wrote a piece of code which limits the player within the screen and here is the code:
private float screenx = Screen.width -20;
playerPosScreen = Camera.main.WorldToScreenPoint(transform.position);
if(Input.GetKey(KeyCode.RightArrow) && playerPosScreen.x < screenx)
{
transform.Translate(Vector3.right * speed * Time.deltaTime * 0.4f);
}
if (Input.GetKey(KeyCode.LeftArrow) && playerPosScreen.x > 20)
{
transform.Translate(-Vector3.right * speed * Time.deltaTime * 0.4f);
}
I am aware that I still need to convert few of the static values in the above code and this is is not really a good way to code.
My question here is how do I do this in Android? I want the player to stay in the screen, i.e if the user moves the player by dragging him to extreme left, no matter how much ever he tries to drag, the player should stay at the left corner of the screen and the same applies to right. In simple terms I want to detect the left and right edges of the screen and limit my object within these edges.
My game will be in landscape mode.
Any help would be very much appreciated. Thanks in advance.
This sort of problem is generally solved in the following manor:
if(transform.position.x < screenx) {
transform.position.x = screenx;
}
Here, we are checking to see if the transformed player is out of the screen space. If it is, we set it to the minimum it can be - which I am assuming is screenx.
public Transform player;
public float distanceFromCamera=10;
public float offsetx=.05f;
public float offsety=.05f;
void Awake()
{
player.position=Camera.main.ViewportToWorldPoint(new Vector3(offsetx,offsety,distanceFromCamera));
}
this will be your bottom left screen boundry