- Home /
Fall off left side of screen and spawn on right
Evening all!
I'm nearing the end of my doodle-jump style game (1st unity project!) and have come across what I hope is the final hurdle.
Currently I have a spaceship which moves left to right along the X axis when you tilt the phone, the ship goes off screen and continues on forever unless you tilt back in the opposite direction.
I would like the ship to re-appear on the opposite side of the screen when it falls off the edge, a bit like Asteroids..to complicate things further I'd need to allow for varying screen resolutions and maybe use a percentage of the screen width, is this possible? if so, how?
Here is my movement script...
void Update() {
rigidbody.velocity = new Vector3(0, 0, 0);
rigidbody.AddForce(new Vector3(0, 8000, 0), ForceMode.Force);
// rigidbody.velocity = new Vector3(0, rigidbody.velocity.y, 0);
transform.Translate(Input.GetAxis("Horizontal") * Time.deltaTime * speed, 0, 0); //pc controls (arrows)
Vector3 dir = Vector3.zero; //Android controls - accelorometer
dir.x = -Input.acceleration.y;
dir.y = 0;
dir.z = 0;
if (dir.sqrMagnitude > 1)
dir.Normalize();
dir *= Time.deltaTime;
transform.Translate(dir * speed);
}
Answer by AlucardJay · Jun 30, 2012 at 08:34 AM
EDIT :
To use Camera.main.ScreenToWorldPoint
, pass a Vector3 and specify a screen-pixel for X and Y, for Z you need to specify the distance between the camera and the spaceship. e.g. if the camera Z is -10 , and the ship Z is 0, then the distance is 10. so the command should read : leftConstraint = Camera.main.ScreenToWorldPoint(new Vector3(0.0f, 0.0f, 10.0f)).x;
Here's a working C# script :
using UnityEngine;
using System.Collections;
public class Screen_Bounds : MonoBehaviour
{
public float leftConstraint = 0.0f;
public float rightConstraint = 0.0f;
public float buffer = 1.0f; // set this so the spaceship disappears offscreen before re-appearing on other side
public float distanceZ = 10.0f;
void Awake()
{
// set Vector3 to ( camera left/right limits, spaceship Y, spaceship Z )
// this will find a world-space point that is relative to the screen
// using the camera's position from the origin (world-space Vector3(0,0,0)
//leftConstraint = Camera.main.ScreenToWorldPoint( new Vector3(0.0f, 0.0f, 0 - Camera.main.transform.position.z) ).x;
//rightConstraint = Camera.main.ScreenToWorldPoint( new Vector3(Screen.width, 0.0f, 0 - Camera.main.transform.position.z) ).x;
// using a specific distance
leftConstraint = Camera.main.ScreenToWorldPoint( new Vector3(0.0f, 0.0f, distanceZ) ).x;
rightConstraint = Camera.main.ScreenToWorldPoint( new Vector3(Screen.width, 0.0f, distanceZ) ).x;
}
void Update()
{
/*
if (shipX < leftConstraint - buffer) { // ship is past world-space view / off screen
shipX = rightConstraint + buffer; // move ship to opposite side
}
if (shipX > rightConstraint + buffer) {
shipX = leftConstraint - buffer;
}
*/
}
}
Original Answer :
You can find a position in world-space that the spaceship moves off screen, then move the spaceship to a position on the other side that is off-screen. Use Camera.main.ScreenToWorldPoint
http://docs.unity3d.com/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html
Here is a JS example (just saw it was C#, have added below). Also consider the Update functions as psuedoCode =]
var leftConstraint : float = 0.0;
var rightConstraint : float = 960.0;
var buffer : float = 1.0; // set this so the spaceship disappears offscreen before re-appearing on other side
function Start()
{
// set Vector3 to ( camera left/right limits, spaceship Y, spaceship Z )
// this will find a world-space point that is relative to the screen
leftConstraint = Camera.main.ScreenToWorldPoint(Vector3(Screen.width * 0.0, 0.0, 0.0)).x;
rightConstraint = Camera.main.ScreenToWorldPoint(Vector3(Screen.width * 1.0, 0.0, 0.0)).x;
}
function Update()
{
if (shipX < leftConstraint - buffer) { // ship is past world-space view / off screen
shipX = rightConstraint + buffer; // move ship to opposite side
}
if (shipX > rightConstraint + buffer) {
shipX = leftConstraint - buffer;
}
}
Converted : C# is not my native language, but try :
float leftConstraint = 0.0f;
float rightConstraint = 960.0f;
float buffer = 1.0f; // set this so the spaceship disappears offscreen before re-appearing on other side
void Start()
{
// set Vector3 to ( camera left/right limits, spaceship Y, spaceship Z )
// this will find a world-space point that is relative to the screen
leftConstraint = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width * 0.05f,0.0f,0.0f)).x; // Or set to (0,0,0)
rightConstraint = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width * 0.95f,0.0f,0.0f)).x; // Or set to (Screen.width,0,0)
}
void Update()
{
if (shipX < leftConstraint - buffer) { // ship is past world-space view / off screen
shipX = rightConstraint + buffer; // move ship to opposite side
}
if (shipX > rightConstraint + buffer) {
shipX = leftConstraint - buffer;
}
}
C-Blunt : Ok, so I've played about with various things including $$anonymous$$ $$anonymous$$ay's solution which looked good but something wasnt quite right.
I've simplified it now and it works well except it won't scale on screen size...
if( transform.position.x < -12 ) transform.position = new Vector3(12,transform.position.y, transform.position.z);
else if( transform.position.x > 12 ) transform.position = new Vector3(-12,transform.position.y, transform.position.z);
@C-Blunt please post comments here [add new comment]
something wasn't quite right ? What was happening? The 12 you are using should be the value stored in leftConstraint
. Need more info.
Am also puzzled by it won't scale on screen size . In world-space, the camera renders things the same for any resolution I assumed.
Apologies, I will re-post the code suggested, modified slightly to work with my game, it works to an extent, but the left & right constraints seem too close together as you only move a small distance to the left/right and are ported to the opposite side (slightly off centre, not other side of the screen.) The first part of the script seems to be the problem:
float leftConstraint = 0.0f; float rightConstraint = 960.0f; float buffer = 1.0f;
void Start() { // set Vector3 to ( camera left/right limits, spaceship Y, spaceship Z ) // this will find a world-space point that is relative to the screen leftConstraint = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width 0.05f,0.0f,0.0f)).x; rightConstraint = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width 0.95f,0.0f,0.0f)).x; }
~EDIT~ With a little further testing, I increased the buffer to 10.0f, this works fine on my Xperia phone, hopefully it will on tablets too!
Thanks!
I have been playing with this and worked out why your buffer is set so high. When you use ScreenToWorldPoint
have to set the Vector3 Z value to be the distance from the camera. Currently, the Z is set to 0.0f, so the left and right constraints are returning zero !
e.g. if the camera Z is -10 , and the ship Z is 0, then the distance is 10. so the command should read : leftConstraint = Camera.main.ScreenToWorldPoint(new Vector3(0.0f, 0.0f, 10.0f)).x;
I have edited the answer with a script that should work, and so you don't have to set the buffer so high !
You could also define a relative value for distanceZ, I think: distanceZ = $$anonymous$$athf.Abs (cam.transform.position.z + transform.position.z);
I'm currently developing an Asteroids Clone for Desktop, and implemented your code structure as following:
void Start () {
cam = Camera.main;
distanceZ = $$anonymous$$athf.Abs (cam.transform.position.z + transform.position.z);
leftConstraint = cam.ScreenToWorldPoint (new Vector3 (0.0f, 0.0f, distanceZ)).x;
rightConstraint = cam.ScreenToWorldPoint (new Vector3 (Screen.width, 0.0f, distanceZ)).x;
bottomConstraint = cam.ScreenToWorldPoint (new Vector3 (0.0f, 0.0f, distanceZ)).y;
topConstraint = cam.ScreenToWorldPoint (new Vector3 (0.0f, Screen.height, distanceZ)).y;
}
void FixedUpdate (){
if (transform.position.x < leftConstraint - buffer) {
transform.position = new Vector3 (rightConstraint + buffer, transform.position.y, transform.position.z);
}
if (transform.position.x > rightConstraint + buffer) {
transform.position = new Vector3 (leftConstraint - buffer, transform.position.y, transform.position.z);
}
if (transform.position.y < bottomConstraint - buffer) {
transform.position = new Vector3 (transform.position.x, topConstraint + buffer, transform.position.z);
}
if (transform.position.y > topConstraint + buffer) {
transform.position = new Vector3 (transform.position.x, bottomConstraint - buffer, transform.position.z);
}
}
Almost everything works just fine, except it doesn't translate from left to right, it just stops at the buffer limit, like Clamp. You have any idea what's going on?
Answer by charkins · Feb 18, 2016 at 08:53 AM
//Scales to screen
using UnityEngine;
using System.Collections;
public class TransportObjectOnScreenExit : MonoBehaviour {
float leftConstraint = Screen.width;
float rightConstraint = Screen.width;
float bottomConstraint = Screen.height;
float topConstraint = Screen.height;
float buffer = 1.0f;
Camera cam;
float distanceZ;
void Start() {
cam = Camera.main;
distanceZ = Mathf.Abs(cam.transform.position.z + transform.position.z);
leftConstraint = cam.ScreenToWorldPoint(new Vector3(0.0f, 0.0f, distanceZ)).x;
rightConstraint = cam.ScreenToWorldPoint(new Vector3(Screen.width, 0.0f, distanceZ)).x;
bottomConstraint = cam.ScreenToWorldPoint(new Vector3(0.0f, 0.0f, distanceZ)).y;
topConstraint = cam.ScreenToWorldPoint(new Vector3(0.0f, Screen.height, distanceZ)).y;
}
void FixedUpdate() {
if (transform.position.x < leftConstraint - buffer) {
transform.position = new Vector3(rightConstraint + buffer, transform.position.y, transform.position.z);
}
if (transform.position.x > rightConstraint + buffer) {
transform.position = new Vector3(leftConstraint - buffer, transform.position.y, transform.position.z);
}
if (transform.position.y < bottomConstraint - buffer) {
transform.position = new Vector3(transform.position.x, topConstraint + buffer, transform.position.z);
}
if (transform.position.y > topConstraint + buffer) {
transform.position = new Vector3(transform.position.x, bottomConstraint - buffer, transform.position.z);
}
}
}
Answer by Mizuho · Jun 29, 2012 at 09:13 PM
http://answers.unity3d.com/questions/43564/best-way-to-tell-which-objects-are-being-looked-at.html
Use a Raycast and shoot it at your object. If it misses, your object flew off the screen and you should calculate which side it flew off of (probably by calculating where it is relative to the central coordinate your camera is looking at).
Thanks for the reply, I have looked at using raycast and making and invisible wall or even using a collider on the wall but I don't think this would work on different screen resolutions. Is it possible for a raycast to detect the screen edge? Any help with a snippet of code would be great as im still a novice with c#. thanks!
Answer by C-Blunt · Jun 30, 2012 at 09:31 PM
Ok, so I've played about with various things including Jay Kay's solution which looked good but something wasnt quite right.
I've simplified it now and it works well except it won't scale on screen size...
if( transform.position.x < -12 ) transform.position = new Vector3(12,transform.position.y, transform.position.z); else if( transform.position.x > 12 ) transform.position = new Vector3(-12,transform.position.y, transform.position.z);