I am trying to get the starting paddle (I am creating pong) to be at the left most of the screen at all times. I am having trouble coming up with a good formula for doing this. My camera size is 5, it is centered at (0,0). The paddle should be at approximately -6.5 for the x-coordinate. Here, in the script for the paddle, is how I am trying to do this
//renderer is the SpriteRenderer
xPos = -Camera.main.orthographicSize -
(renderer.sprite.textureRect.width/ renderer.sprite.pixelsPerUnit);
However this results in this (the left paddle is here the code is being applied):
So, the right paddle is essential being placed at the very left - the width of the image. However, some of the paddle image is cut off. I can't seem to figure out why and I have checked everywhere. Any help would be extremely appreciated and noticed.
I think your problem is related to the calculation of the width of the screen.
Unity uses Camera.main.orthographicSize to calculate the screen's height and then calculates the width depending on the screen proportions. Try to calcule the width in this way:
width= Camera.main.orthographicSize * Camera.main.aspect;
Related
guys! We are developing a 2D game for desktop and mobile. It is grid-based although we decided not to use tilemaps and, instead, create our own grid by code, because we need to program different actions and interactions for each tile. The game UI is on a canvas and that part resizes as we expected. Also, everything already works quite well "functionality-wise" on both, mobile and desktop. The problem is that, as we made the main grid and objects as sprites, it works great on any 16:9 screen, but some of the screen space gets cut when it runs on any wider screen.
How can we resize the whole sprite scene depending on screen size? I guess it has more to do with the camera than with the actual objects but we don´t have a clear clue. We already looked into "pixel-perfect camera" and, although we haven´t dug too deeply into it, it looks like it´s aimed more towards preserving artwork at full resolution and not so much at what we need.
This one is from the PC where we are developing the game and where it looks as it should:
And this one is from a PC with a wider screen (16:10) where the scene gets cropped from the sides (In the previous picture I marked in orange/yellow the columns that are lost in this one)
I guess there should be a way to stretch all sprites to fit the screen, but I think the best way to go would be to get empty horizontal or vertical bars, on top and bottom or to the sides, in order to preserve the exact proportions, and that would be good enough. But how to do it?
Thanks in advance.
Solved! Starting with the great ideas ephb gave me, I finally decided to get a reference percentage between the screen width and height. So, for 1920x1080, which is the resolution I know the game looks correct in, I did a rule of three and got that 1080 is 56.25% of the screen width, and, that in that case, the camera size should be 5.
Knowing those two elements, now I can check the height proportion for the user´s device and, using another rule of three, calculate the correct camera size, like this:
Camera cam;
void Awake()
{
cam = Camera.main;
cam.orthographicSize = GetHeightProportion() * 5 / 56.25f; //1920x1080 reference ---
}
float GetHeightProportion()
{
return ((float)Screen.height * 100) / (float)Screen.width;
}
I think you are looking to resize fore any aspect ration not screen resolution. You use the aspect ratio dropdown of the game window to see how it looks without running it on different computers.
The default setting is that the vertical field of view of your camera stays the same. Since the 16:10 display is taller this results in your image appearing zoomed with the sides being cut off.
Since you are using sprites and you basically have to recreate what the canvas scaler does but in world space.
You could move your camera, change its FOV if it a perspective camera, change its size if it is an orthographic camera or scale your scene. I will describe the first steps.
Get Screen width and height and calculate the aspect ratio.
Compare against your target aspect ratio. (I assume it is 16/9)
Use this multiplier to scale your scene / move your camera / change it's field of view
I'm working on an RTS game with some pretty extensive UI, so I moved the main camera's output to a quad which only makes up about half the screen, and I'm blitting some UI effects over the rest. My current way of interacting with the game uses unity's Input.mousePosition. When I moved the camera's feed to the quad, obviously those pixel coordinates were distorted, so I fixed them like this:
mapMousePos = (Input.mousePosition * mscaleCorr - mapCorrection * mscaleCorr);
mapCorrection being the pixel offset of the smaller feed, and mscaleCorr being a magic number that got through trial and error — a temporary fix.
Point is, now I'm realizing that running this game at a different resolution will almost certainly break these magic numbers.
What I want mapMousePos to be is what Input.mousePosition was before I moved the gameplay to the small quad - going from (0,0) in the bottom left of the quad to the screen (width, height) in the top right of the quad. This is just so it works with screenToWorld point really nicely on my gameplay camera.
I have the camera-feed quad parented to a full-screen quad, and tried using their relative positions to apply the necessary transformations, but it didn't work, I'm guessing because it's a pixel problem.
I've dug around the docs for a solution using Camera's builtin worldToScreenPoint function, without any luck. I'm sure I'll bump into a fix eventually, but would greatly appreciate any pointers.
Here's what I've come up with; it's stupid, but it works.
I've placed objects at the bottom left and top right of the quad, stored in code as bL and tR.
Then I convert the mousePosition to a worldPosition using ScreenToWorldPoint(), remap it by subtracting the bottom left position, and get it as a percentage across the screen by dividing it by the delta to the top right. Multiply the percentage by the pixel dimensions of the gameplay camera, and voila.
In code, this:
Vector3 wPos = finalcam.ScreenToWorldPoint(Input.mousePosition);
wPos -= bL.transform.position;
mapMousePos = new Vector2(Mathf.Abs(wPos.x), Mathf.Abs(wPos.y));
mapMousePos = new Vector2(
mapMousePos.x / (tR.transform.position.x -bL.transform.position.x),
mapMousePos.y / (tR.transform.position.y - bL.transform.position.y));
mapMousePos = new Vector2(mapMousePos.x * Camera.main.pixelWidth, mapMousePos.y * Camera.main.pixelHeight);
Again, it's dumb, but it seems to work. I'm leaving this up in case anybody knows a cleaner method.
I'm developing a little game where I generate rooms of different size and would like this randomly generated room to be always visible on the screen without caring about it's size. The camera is on a top view angle (rotation = 90,0,0).
I tried to create a relationship between it's size and the Y axis position of the camera to make it always visible but it wasn't successful. There is the solution where the object is kept on the bottom left corner of the screen but if the object is too big only a part of it is visible by the camera. I really have no more idea ^^
Thank you for your help !
I guess you are using an Orthographic camera. For the Orthographic Camera, the size is the number of unity units from the center of the camera to the top/bottom of the screen. The width is then based on the aspect ratio. So, if you know how big the objects are that should be easy!
You can get or set the main camera size with Camera.main.orthographicSize
then get/set the aspect ratio (width/height) with Camera.main.aspect
and you can reset it after with Camera.main.ResetAspect();
I have a game like Pong, except you control both paddles and try to keep the ball in bounds. I want the paddle to always be 1/3 of the height of the screen for all resolutions. So if the Height = 900, then the paddle should be 300 high. For some reason, I can't seem to find a way that works for all resolutions anywhere. I feel I need to accomplish this through a script. Here is an image of the components for my paddle.
I need a generic formula so the paddle height is always 1/3 of the screen height.
Thanks in advanced for any help!
Get the canvas height and assign the paddle sizeDelta to have y size equal to the canvas height divided by 3.
This is the script, assumed you attach it to the paddle:
public Canvas myCanvas;
void Start() {
float canvasHeight = myCanvas.pixelRect.height;
GetComponent<RectTransform>().sizeDelta = new Vector2(GetComponent<RectTransform>().sizeDelta.x, canvasHeight/3f);
}
I have some code that I wrote that works, but I feel it could be better and wanted to get some feedback.
The goal I had is to have a Sprite Scale up and back down in a timely fashion when a button is pushed so that it gives the illusion of jumping in a "Top Down" view of the game. Like the character is jumping off the screen. I already know how to draw scaled images I'm more interested in the logic of the timing aspect.
This works, just not sure it's the best. Thought maybe there was some equation, a math friend told me maybe a linear equation or like a parabola or second order equation. Not being great with math.
Anyway.
Class Properties
private double _jumpingStartedAt;
private double _totalJumpTimeInSeconds = 0.7;
private double _totalJumpFrames = 14;
private double _timeSinceLastScale;
private double _jumpingHalfWayAt;
When button is pushed for the first time I start the "Jump Logic". This runs once per jump. My thought was that I'd mark the "start" time and determine the "halfway" time by the totalJumpTimeInSeconds.
_jumpingStartedAt = gameTime.TotalGameTime.TotalSeconds;
_jumpingHalfWayAt = _jumpingStartedAt + MillisecondsBetweenFrame() * (_totalJumpFrames / 2);
And then this is run on each Update() until my "jump" is complete or isJumping = false. The logic here is that I would scale up every 1 "frame" until half way point then scale back down.
_timeSinceLastScale += gameTime.ElapsedGameTime.TotalSeconds;
if (_timeSinceLastScale > MillisecondsBetweenFrame() && gameTime.TotalGameTime.TotalSeconds < _jumpingHalfWayAt)
{
Scale += 0.2f;
_timeSinceLastScale = 0;
}
else if (gameTime.TotalGameTime.TotalSeconds > _jumpingHalfWayAt)
{
Scale -= 0.2f;
if (Scale < 1.0) Scale = 1; //probably don't need this was worried if it went passed 0
if (Scale == 1.0) _isJumping = false;
}
private double SecondsBetweenFrame()
{
return _totalJumpTimeInSeconds / this._totalJumpFrames;
}
Now this works, but seems a little convoluted to me.
Stretching image when jumping - side view
Yeah, it's pretty complicated, what you created.
I assume your sprite is also moving up and down when jumping. That you have some sort of Vector2 velocity, which you change by dv = gravityAcceleration * dt in every update, and so you change Vector2 position by dp = velocity * dt. If so, I would rather use my velocity.Y value to calculate how the sprite should stretch. I think it's more natural. And your code will become much more simple.
Here's an image to describe better what I mean:
However, you can probably face the other problem here: just at the beginning of the jump your sprite will suddenly get high velocity, when still being near the ground, which can cause it to cross through the floor for a moment. To prevent that you can artificially move your sprite upwards by the smallest needed value for the time of jump. The problem is described by the image below:
As you can very well see, the first stretched ball moved upwards a little bit, but not enough. You have to calculate difference between sizes before and after stretching and then move your sprite up by that distance.
If you do it like that, your Update should shorten to just a few lines. I believe you can do simple calculations on your own.
Easier approach
...Unless you'd rather like your sprite behave like you want. Then you could modify scale according to your Y position:
if (KeyboardState.IsKeyDown(Keys.Space))
{
isJumping = true;
jumpStartPosition = Position;
}
if (!isJumping) Scale = 1f;
else
{
Scale = StretchFactor * (Position.Y - jumpStartPosition.Y);
}
where:
- isJumping is a bool,
- jumpStartPosition is a Vector2,
- Position is a Vector2 property of your sprite,
- StretchFactor is a float property of your sprite telling how much does it stretch.
And you also need to have end-of-jump condition - for example when the sprite's Position.Y becomes smaller than the jumpStartPosition.Y. But generally this solution (as well as yours) has one disadvantage - there will be problems, if you will want to start jump from one height, and end it on another:
so I would rather recommend my first solution. There you can make stop-jump condition by collision check.
Stretching image when jumping - top-down view
Bummer. Since originally it wasn't specified that it is a top-down game, like those first GTA's, I really misunderstood the question, so the answer doesn't fit much. So the answer goes now.
If you wan't it to be realistic, you should use some basic principles of perspective. As we look at the character jumping from the top, it goes closer to us, so it's image grows. Why's that? Look at the pic below.
There are two things, that are needed for perspective to work: the center of perspective and the screen. The center of perspective is the point, where all "rays" are crossing. "Ray" is a line from the any point in the world to the center of our eye. Now the screen is the plane, where image of 3d world is being created. The points of the real world are being cast into screen along their rays. Of course your game is pseudo-3d, but it shouldn't matter in that case.
When z grows, sprite comes closer to the center of perspective. If you imagine ray from the center of perspective to the edge of the sprite, the angle of ray changes, as it's distance to the center of perspective becomes lesser. And the change of angle makes the point's image on the screen moving. That's why image grows, or becomes smaller.
Now we can wonder: ok, how now put this into numbers? Look at the picture below:
I deliberately translated whole world by -C so the z coord of the center of perspective could become 0. That makes calculations simplier. What are we trying to find, is the x' - coord of the point on the screen. Let the Z* = |z - C|. If we look at this picture it becomes clear, that we can find what we need by pretty simple proportion:
Using the same method you can calculate y'. If your character is always at the center of the screen, all that you need will be x'/x = y'/y = S, i.e. your scale. That's because x in this scenario is, in fact, the half-width of the sprite, and y is the half-height. However, if your character will be able to move freely around the screen, you may want to scale & translate it, so it would be more natural:
The white square is the on-the-ground sprite, the gray square is the jumping sprite. In this case you will have to know l (left), r (right), t (top) and b (bottom) coords of the sprite's boundaries (top-bottom means Y-axis, not Z-axis). Then using the same proportion you can get l', r', t' and b' - boundaries of the sprite's image on screen. From this data you should be able to calculate both scale and translation.
Note: L is the parameter of our calculation which you have to choose yourself. Assuming, that the screen has constant width Ws and height Hs, L strictly corresponds with FOV (field of view). You can acquire it also using proportions. So L = (cos(FOV/2) * Ws)/2. I would recommend FOV = 60 deg. If you will make FOV too big, you may face the fisheye problem.