- Home /
Endless "Falling" Game - Background generation
Hello. This is my first question here. I've seen some other questions about this topic but none of them helped me with my specific issue.
I want to make an endless falling game where you fall in a long, endless, vertical cave. First of all I want to know if it's viable to make it so the character falls with a rigidbody, instead of the background going up. This is really important, because it's going to be an android game, so this matters a lot. Also, people say that you can break the physics if a gameobject goes too far from its origin.
Then, about the background generation, how would I do it? I have some programming skills and tried a lot of things, but I have some problems on implementing a seamless background that generates when the player reaches the previous one.
![alt text][1] [1]: /storage/temp/23187-unity_question_endless_faller.png
I made this to illustrate better.
I want to know the best practice in terms of performance and seamlessness when generating the background. Do I use an array? Or an object to instantiate the background? People say that it's a bad thing to keep instantiating/destroying objects, so what could be done to avoid it?
I hope I was clear enough and thanks in advance!
How I do it, is I don't have the player actually move. I set the textureoffset (with a seamless texture) with time. So the texture scrolls on a plane as if the player was moving... nothing is actually moving. Though, your obstacles would need to move Up.
Answer by fifthknotch · Mar 06, 2014 at 05:19 PM
I made an endless runner using one seamless texture that scrolled on the plane. The plane would extend farther than the camera could see and because it scroll through one seamless texture, It looked like the player was actually running. Using a rigidbody to actually make your player fall would start eating up processing power and is probably not what you want to do on android. Another way of achieving the "look" of falling is to have multiple planes all moving upwards. Instead of instantiating and destroy just change the plane's transform position once it reaches a certain height to a height below the screen and make it move up. You could have in the script something like: if (transform.position.y >= "your value goes here") { transform.position.y -= "size of the plane"; } Either of these methods work but they both require the player not falling.
I did this way but i'm having some problems. I made a script with a function that whenever the player hits a new plane, one other plane is chosen at random to be moved down (to the next "chunk" that will appear under the player). But I'm having some problems, whenever the player touches a plane, the plane he touches gets moved, ins$$anonymous$$d of a random one. I'm trying to work this out but if I solve this problem i'll be able to do this type of game the way you said. Thanks man!
It sounds like some variable are getting flipped around. If you post the relevant code, we might could help you with this. Otherwise, good luck!
Answer by Vitorcampea · Mar 06, 2014 at 05:56 PM
You will need 2 scripts, one for the background spawner and other for background
Background: (this will makin him move down at speed of 10 and destroy after the time you insert on inspecter)
public class BackgroundMove : MonoBehaviour {
public float speed = 10;
public float timeToDestroy;
public float currentTimeToDestroy;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
currentTimeToDestroy = currentTimeToDestroy + 1 * Time.deltaTime;
transform.Translate (0,-speed*Time.deltaTime,0);
if (currentTimeToDestroy >= timeToDestroy) {
Destroy(gameObject);
}
}
}
Background Spawner (this will spawn 1 background in each timespawn you insert on inspecter)
using UnityEngine;
using System.Collections;
public class BackSpawner : MonoBehaviour {
public GameObject background;
public float timeToSpawn;
public float currentTimeToSpawn;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
currentTimeToSpawn = currentTimeToSpawn+1 * Time.deltaTime;
if (currentTimeToSpawn >= timeToSpawn) {
Instantiate (background, transform.position, transform.rotation);
currentTimeToSpawn = 0;
}
}
}
this works and i tested it, good luck
This way probably works but it keeps destroying and instantiating new gameobjects, so I don't think it's a optimal way to do it. But you gave me some ideas, thanks man!
You can just use an objectpool to control the instantiate and destroy. So everything is Instantiated on Start(), and then made activated/deactivated through scripting by use of the Objectpool.
Oh yeah I forgot I could do that here!
This script is attached to the player.
void OnTriggerEnter2D(Collider2D hit)
{
if (hit.gameObject.tag == "touchSection");
{
int n = Random.Range(0, other.walls.Length);
while (n == other.newNum)
{
newNum = Random.Range(0, other.walls.Length);
}
other.$$anonymous$$ove(n);
}//if
}//OntriggerEnter
This one is attached to the object that moves the paths, or "chunks"
public class Path$$anonymous$$over : $$anonymous$$onoBehaviour {
public GameObject[] walls;
public Transform player;
public float distance;
public Vector3 pos;
public int movespeed;
public int oldNum;
public int newNum;
// Use this for initialization
void Start () {
pos = new Vector2(0, player.position.y - distance);
newNum = Random.Range (0,walls.Length);
}
// Update is called once per frame
void Update () {
pos = new Vector2(0, player.position.y - distance);
walls[0].transform.Translate(Vector2.up * Time.deltaTime * movespeed, Space.World);
walls[1].transform.Translate(Vector2.up * Time.deltaTime * movespeed, Space.World);
walls[2].transform.Translate(Vector2.up * Time.deltaTime * movespeed, Space.World);
walls[3].transform.Translate(Vector2.up * Time.deltaTime * movespeed, Space.World);
if(Input.GetAxis("Vertical") == 0)
{
movespeed = 8;
}
if(Input.GetAxis("Vertical") > 0)
{
movespeed = 4;
}
if(Input.GetAxis("Vertical") < 0)
{
}//if
}//update
public void $$anonymous$$ove(int range)
{
newNum = range;
while (oldNum == newNum)
{
newNum = Random.Range (0,walls.Length);
}
walls[newNum].transform.position = pos;
oldNum = newNum;
}//Spawn
}
Thanks in advance, man!
I see your problem, you are sending move to the wall you hit at line 10 it the first script. You need to send the message to the one of the other walls. It looks like you tried to name the other wall "n", but ins$$anonymous$$d of sending a message to "n", you send the message to "other" with the parameter "n".
Actually, I concealed that part. "other" is actually the other script:
public class CallFunction : $$anonymous$$onoBehaviour {
public Path$$anonymous$$over other;
Pathmover being the script that moves the walls (or "chunks" or "sections" or whatever you'd like to call it) I'm getting really confused about it, now. ):
I think the problem lies within this part:
void OnTriggerEnter2D(Collider2D hit)
{
if (hit.gameObject.tag == "touchSection");
{
int n = Random.Range(0, other.walls.Length);
while (n == other.newNum)
{
newNum = Random.Range(0, other.walls.Length);
}
other.$$anonymous$$ove(n);
}//if
}//OntriggerEnter
I think that whenever the character hits the trigger of the wall section, it runs the line other.$$anonymous$$ove(n); a lot of times, so that's why ALL of the walls go down whenever the charactr touches one of them.
Here's the web player link for you to test... Left and right to move, not that it matters right now :P https://dl.dropboxusercontent.com/u/29752052/Arquivos/ProcDown/ProcDown.html
Your answer
Follow this Question
Related Questions
How do I proceduraly generate an environment around a sphere? 5 Answers
How to make a race track similar to audiosurf? 0 Answers
My game keeps freezing 1 Answer
How to Make an Endless Runner Move from track to track smoothly 0 Answers
Texture render performance - one 1024px, vs two 512px - for modular models? 1 Answer