Keeping player within screenbounds with moving camera (Vertical Shooter)
I followed a tutorial for this (Linked below [4mins])and have implemented it into my player movement script. However the bounds to where the character can't leave is left behind by the camera as it moves upward my character hits the bounderies and cannot move forward.
Im very new, making my first game... How can I have the bounderies update with the camera's position?
YouTube Tutorial Link: https://youtu.be/ailbszpt_AI
I can't get his attention, but the youtuber told someone else "Add the cameras transform.position to ScreenBounds when calculating viewpos."
How do I do that?
Below is my player movement script...
using UnityEngine;
public class Player_Movement : MonoBehaviour {
public float maxSpeed = 30f;
public Camera MainCamera; //be sure to assign this in the inspector to your main camera
private Vector2 screenBounds;
private float objectWidth;
private float objectHeight;
// Start is called before the first frame update
void Start()
{
screenBounds = MainCamera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.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 Update()
{
// Moving the Ship
Vector3 pos = transform.position;
// MOVE the ship Horizontally.
Input.GetAxis("Horizontal");
pos.x += Input.GetAxis("Horizontal") * maxSpeed * Time.deltaTime;
transform.position = pos;
// MOVE the ship Vertically.
Input.GetAxis("Vertical");
pos.y += Input.GetAxis("Vertical") * maxSpeed * Time.deltaTime;
transform.position = pos;
}
void LateUpdate()
{
//Bounderies
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);
transform.position = viewPos;
}
}
Answer by exokide · Nov 08, 2019 at 11:30 AM
Short answer would be that the camera leaves you behind because you never change the screenBounds. There is more to this though, I have not watched this tutorial but the intended use appears to be a stationary camera and to move the rest of the world.
A more robust way of doing this with a moving camera in mind would be to begin by changing your screenBounds variable from "Vector2" to "Rect" The Rect type can store all the details of a rectangle which would be its position in 2D space (X and Y) and its size in 2D space (width and height).
Next you have to initialize screenBounds in your Start method replace your previous initialize code with:
float cameraHeight = MainCamera.orthographicSize * 2;
float cameraWidth = cameraHeight * MainCamera.aspect;
Vector2 cameraSize = new Vector2(cameraWidth, cameraHeight);
Vector2 cameraCenterPosition = MainCamera.transform.position;
Vector2 cameraBottomLeftPosition = cameraCenterPosition - (cameraSize / 2);
screenBounds = new Rect(cameraBottomLeftPosition , cameraSize);
The code is very verbose at an attempt to make it easier to take it what it does but the only thing carried forward is screenBounds which is made up of two Vector2's. Next we have to update screenBounds to keep up with changes in camera position for this we will just update it every frame. Add this line to the end of your Update method:
screenBounds.position = (Vector2)MainCamera.transform.position - (screenBounds.size / 2);
This is a shorthand version of half of what we do in the Start method. Last we need to modify the two Clamp calls in LateUpdate method replace them with:
viewPos.x = Mathf.Clamp(viewPos.x, screenBounds.x + objectWidth, screenBounds.x + screenBounds.width - objectWidth);
viewPos.y = Mathf.Clamp(viewPos.y, screenBounds.y + objectHeight, screenBounds.y + screenBounds.height - objectHeight);
That should do it here is a full trimmed down version of your original script with fixes applied
using UnityEngine;
public class Player_Movement : MonoBehaviour
{
public float maxSpeed = 30f;
public Camera MainCamera;
private Rect screenBounds;
private float objectWidth;
private float objectHeight;
void Start()
{
float cameraHeight = MainCamera.orthographicSize * 2;
float cameraWidth = cameraHeight * MainCamera.aspect;
Vector2 cameraSize = new Vector2(cameraWidth, cameraHeight);
Vector2 cameraCenterPosition = MainCamera.transform.position;
Vector2 cameraBottomLeftPosition = cameraCenterPosition - (cameraSize / 2);
screenBounds = new Rect(cameraBottomLeftPosition , cameraSize);
objectWidth = transform.GetComponent<SpriteRenderer>().bounds.extents.x;
objectHeight = transform.GetComponent<SpriteRenderer>().bounds.extents.y;
}
void Update()
{
Vector3 pos = transform.position;
pos.x += Input.GetAxis("Horizontal") * maxSpeed * Time.deltaTime;
pos.y += Input.GetAxis("Vertical") * maxSpeed * Time.deltaTime;
transform.position = pos;
screenBounds.position = (Vector2)MainCamera.transform.position - (screenBounds.size / 2);
}
void LateUpdate()
{
Vector3 viewPos = transform.position;
viewPos.x = Mathf.Clamp(viewPos.x, screenBounds.x + objectWidth, screenBounds.x + screenBounds.width - objectWidth);
viewPos.y = Mathf.Clamp(viewPos.y, screenBounds.y + objectHeight, screenBounds.y + screenBounds.height - objectHeight);
transform.position = viewPos;
}
}
Answer by Chaseriver1994 · Nov 11, 2019 at 03:01 PM
Thank you so much! For replying! I wonder what potential benefits there could be for both codes?
I also got back an answer from a youtube channel "Code Monkey" who was also awesome enough to respond. His channel is amazing check it out for superb tutorials.
YouTube Channel: Code Monkey
For my solution I just missed adding the "MainCamera.transform.position" to screenbounds at the end of the script.
Finished code below...
public float maxSpeed = 30f; public Camera MainCamera; //be sure to assign this in the inspector to your main camera private Vector2 screenBounds; private float objectWidth; private float objectHeight; // Start is called before the first frame update void Start() { screenBounds = MainCamera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, MainCamera.transform.position.z)); objectWidth = transform.GetComponent().bounds.extents.x; //extents = size of width / 2 objectHeight = transform.GetComponent().bounds.extents.y; //extents = size of height / 2 } void Update() { // Moving the Ship Vector3 pos = transform.position; // MOVE the ship Horizontally. Input.GetAxis("Horizontal"); pos.x += Input.GetAxis("Horizontal") maxSpeed Time.deltaTime; transform.position = pos; // MOVE the ship Vertically. Input.GetAxis("Vertical"); pos.y += Input.GetAxis("Vertical") maxSpeed Time.deltaTime; transform.position = pos; } void LateUpdate() { //Bounderies Vector3 viewPos = transform.position; viewPos.x = Mathf.Clamp(viewPos.x, MainCamera.transform.position.x + screenBounds.x -1 + objectWidth, MainCamera.transform.position.x + screenBounds.x - objectWidth); viewPos.y = Mathf.Clamp(viewPos.y, MainCamera.transform.position.y + screenBounds.y -1 + objectHeight, MainCamera.transform.position.y + screenBounds.y - objectHeight); transform.position = viewPos; }
Before giving you a more complicated answer I tried a few quick simple fixes similar to what you posted. When thrown through very quick tests I found issues when the camera goes into negative space, camera has a different than default size , etc. If both scripts work in your use cases there is no benefit of one over another. $$anonymous$$any ways to achieve a goal!
Your answer
Follow this Question
Related Questions
C# orthographic scripting error. Please help. 1 Answer
When playing builded version of game the cameras only captures part of scene. 0 Answers
Trail effect for non-moving object 2 Answers
CS1216 error 0 Answers
Screen Resolution 0 Answers