I’m setting up my title screen for my small game, and I’d like to ask for some help with that.
I have a title graphic, which is a GUITexture, and beneath that I have a 3D object which will later become my ‘play’ game button once I add the scripting.
I originally set up a backdrop behind all of this as a GUITexture with an x and y scale of 1 to fit the camera resolution perfectly, but then I lost my 3D object because the GUITextures are always rendered on top.
So, I created a sprite, and attempted the following code to scale accordingly, which kind of works in landscape mode only, but it doesn’t fit the screen fully, I have a large gap at the top, and it also doesn’t work in portrait resolutions : -
using UnityEngine;
using System.Collections;
public class ScaleSprite : MonoBehaviour {
// Use this for initialization
void Start () {
SpriteRenderer sr = GetComponent<SpriteRenderer>();
float worldScreenHeight = Camera.main.orthographicSize * 2;
float worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
transform.localScale = new Vector3(worldScreenWidth / sr.sprite.bounds.size.x, worldScreenHeight / sr.sprite.bounds.size.y, 1);
}
// Update is called once per frame
void Update () {
}
}
Anybody offer any advice as to why, or offer a better solution, one that would work in both portrait and landscape would be great, simple scale whatever sprite I assign it to, to ‘whatever’ resolution is chosen ?
Fixed part of my problem, I’d not set the camera to sit at exactly 0 on the x and y axis, now I don’t get the gap !
Currently my script works in the following resolutions ( I’m working with Android platform ) : -
16:10 Landscape -WORKS
3:2 Landscape - WORKS, but… doesn’t seem to visually scale any differently from 16:10, i.e. when switching from 16:10 to 3:2, image stays same size, suggesting stretching beyond the width of the screen instead of the screen width only
WXGA Landscape ( 1280x800 ) - WORKS
WSVGA Landscape ( 1024x600 ) - Gaps either side
FWVGA Landscape ( 854x480 ) - Gaps either side
WVGA Landscape ( 800x480 ) - Gaps either side
HVGA Landscape ( 480x320 ) - WORKS
Seems like I’m fairly close to getting what I require, I’ve also figured out what I need to change in my calculation should I target a Portrait orientation, but all I’m interested in at this stage is the Landscape mode.
So… Anyone can help with some code suggestions for the 3 landscape modes that have gaps still, or 4 if you include the 3:2 Landscape problem listed above ?
I hope I didn’t misunderstand the question. I’m not sure if you’re always trying to fill the screen but I’m assuming you are.
using UnityEngine;
using System.Collections;
public class ScaleToFillScreen : MonoBehaviour
{
private SpriteRenderer sr;
private Transform _transform;
public int pixelsToUnityUnits = 100;
public Camera cam;
public bool followCamera = true;
// Use this for initialization
void Start()
{
_transform = transform;
sr = GetComponent<SpriteRenderer>();
cam = (cam != null) ? cam : Camera.main;
}
// Update is called once per frame
void Update()
{
Sprite sprite = sr.sprite;
float aspectRatio = Screen.width / (float)Screen.height; // in respect to width
// Guesstimation
int orthoPixelsY = Mathf.CeilToInt(cam.orthographicSize * 2 * pixelsToUnityUnits);
int orthoPixelsX = Mathf.CeilToInt(orthoPixelsY * aspectRatio);
// orthoX and orthoY are obviously not the same as the screen resolution, but we can take advantage of the fact that they're scaled based
// on unity units and ignore calculating based on screen pixels
// find the ratio in scales along each respective axis' and assign as the new local scale
Vector3 newScale = new Vector3(orthoPixelsX / (float)sprite.rect.width, orthoPixelsY / (float)sprite.rect.height, 1f);
_transform.localScale = newScale;
if(followCamera)
{
Vector3 camPosition = cam.transform.position;
Vector3 newPosition = new Vector3(camPosition.x, camPosition.y, _transform.position.z);
_transform.position = newPosition;
}
}
}
Sorry if I was off the mark. I’m not sure if you want to always fill the screen as the Aspect Ratio will be ignored and stretch your image oddly.
Edit: Actually ignore the follow Camera bit. That was strictly something I thought of for 2D play. It wont work on a 3D camera that is moving around a lot.
Edit2: Renamed the script to ‘ScaleToFillScreen’ since that better explains the functionality of the script.
Thank you for reply, it is highly appreciated and I promise it will be studied intently.
The background image I have is a mixture of gradients, so stretching it out in any fashion will not be noticeable, the main logo for my game is a GUITexture, which I scale to fit the aspect ratio seperately in a different script. I have a 3D GameObject that is placed underneath my logo that will be my ‘PLAY’ button, but obviously this was previously hidden behind my original ‘background’ guitexture, by using a sprite, and your help with the script, my title screen will work correctly now and the ‘play’ button will be shown now !
The camera addition is actually very useful, I will comment it out for now, but I’m sure I will use this again in future !
Thanks again for all your efforts, I owe you a beer.
I didn’t realize what Orthosize actually meant until after reading into things, questioning it and looking at the unity units on the grid. It makes a lot of sense, but because of my uncertainty that unity units are always 1 unit per 100 pixels I added the pixelsToUnityUnitys value so it can be adjusted if there’s any possible chance one can adjust pixels per unity units.
Misterselmo : Apologies, missed your post there, I’ve not moved to 4.6 as yet, as I’ve just been sticking with the public releases, the 4.6 GUI stuff looks nice and a lot easier to work with than the current integration, looking forward to the 4.6 public release !
Sorry, but it’s wrong. GUITexture and GUIText components using depth camera, like other 3D objects.
OnGUI system no. Use a depth variable only affects the GUI elements draw in OnGUI function. And these, yes, are always rendered on top scene 3D objects.
Thanks for your clarification, I actually looked at this technique also when researching this, but it didn’t work for me when I initially tried it, your scene example is helpful.
Regards
EDIT, I’m curious, with both techniques, what would people recommend as best method on Android platform ?