Hello, noob here. I’m working on an infinite runner and I’m currently using a scrolling background with a static character, however I would like to increase the speed of the background scroll rate AND the spawn-able ground block movement by a certain factor every time player score is increased by 20, so: 20, 40, 60… I’m not sure where to start. Any help would be appreciated, thanks!
Do you have the background scrolling right now? What do you mean by spawn-able ground block moment? You mean the obstacles and enemies?
Yes the background scrolls right now and my character stays in one location with a run animation and can jump and duck(which is all I want right now). I did mean obstacles, sorry. So basically the game will randomly spawn blocks that the character jumps over or ducks under and increments score by 1(similar to flappy bird). Every 20 points I want to increase the speed of the obstacles and background so it gets progressively more difficult
I’m brand new to C# and Unity, so this is definitely a challenge for me. I’ve coded a bit with Java but that’s it. I’m assuming I have to write some type of script that checks:
if (player.getScore()%20){
backgroundSpeed *= factor;
}
Cool, so if you’re scrolling now, you must be scrolling by some rate, something like…
scrollingBackground.transform.position = new Vector3 (scrollingBackground.transform.position.x + (Speed * Time.smoothDeltaTime), scrollingBackground.transform.position.y, 0);
… right?
Can you just increase Speed as needed?
For the obstacles, what you’ll probably want to do is “cycle” them. Let say you have 5 object types in total, and you want to have at most 2 of them on screen for the player to avoid and anticipate. You can initially create them all off screen, then scroll them separately towards the player. Each using a movement approach similar to the above, something like…
obstacle.transform.position = new Vector3 (obstacle.transform.position.x + (Speed * Time.smoothDeltaTime), obstacle.transform.position.y, 0);
… you could manage an array of obstacles transforms as well as your two active obstacles…
Transform[] myObstacles = new Transform[5];
int indexOfActive1;
int indexOfActive2;
… then at Start you can randomly choose (or hard code) which obstacles come at the player…
indexOfActive1 = Random.Rand (0, myObstacles.length);
… in Update you move your obstacles as per above, with a check to see when it’s x Value goes beyond the screen. You can figure out screen width by using Screen.CurrentResolution and then converting that to world coordinates using ScreenToWorld, or you can just move an object to the left or right when in the editor while you have the camera selected and see when it is beyond the “frame” of the camera and use that value.
When the object is off the screen, you’ll want to reset it to the start position (also off the screen) and pick a new object the move towards the player.
That is basically how I wrote this game Microsoft Apps, you can do way more as you get a good basis.
Hope that helps.
Thank you so much! That was very helpful and informative. I guess my only other question is when you say: “Can you just increase Speed as needed?”. How would I implement the idea of increasing the speed every 20 points?
No problem. We all start somewhere :).
First you want to know when the player got a point, one way to do that (there are many) is to check when an obstacles is “behind” the player…
private int _points = 0;
private float _speed = 6;
... snipped ...
Update ()
{
if (player.transform.position.x > myObstacles[indexOfActive1].transform.position.x)
{
_points++;
}
if (_points % 20 == 0)
{
_speed *= 0.2f
}
}
You could also maintain two values, totalScore and pointsSinceLastSpeedUp, and then each time pointsSinceLastSpeedUp gets past 20, you can increase speed and add that to totalScore.
Awesome!!! Is it just convention to name private variables with an underscore as a prefix? "_points" ?
also, would _points have to be public if I access it from the BackgroundScroller script so I can adjust that speed as well? Thanks!
using the underscore prefix is something I do, not sure about others.
I would make _points accessible via an accessor, rather than just making it public…
public float Speed
{
get { return _speed; }
}
private PlayerScript player;
private float speed = 5;
private float factor = 1.5f;
Transform[] myObstacles = new Transform[2];
int indexOfActive1;
public void Start(){
player = FindObjectOfType(typeof(PlayerScript));
indexOfActive1 = Random.Rand (0, myObstacles.length);
}
public void Update(){
block = myObstacles[indexOfActive1];
block.transform.position = new Vector3 (block.transform.position.x + (speed * Time.smoothDeltaTime, block.transform.position.y, 0);
if (block.tranform.position.x < LEFT_SCREEN_BOUND){
block.transform.position = Vector3(defaultX, defaultY, defaultZ);
indexOfActive1 = Random.Rand (0, myObstacles.length);
}
if(player.Score % 20 == 0){
speed =* factor;
}
}
public float Speed
{
get {return speed};
}
I’m not at my computer with Unity, I know this isn’t right, but am I on the right track? How do I assign a random block movement, and how do I use the Transformation array?
Think you are on your way… my parenthesis were wrong in the samples I gave you, fixed above now, I think :).
You are assigning the random block movement via the “block.transform.position = …” code. And the transform array is being used in your if (block.transform.position.x …) code.
Another question about this, how do you use the score variable in another script? Currently I have the score incremented and declared in a separate script and it has an accessor, but how do I access that score from another script? I want to be able to go into the background scroll and obstacle scroll scripts and use the score variable so I can implement:
if (_points % 20 == 0)
{
_speed *= 0.2f
}
Would using PlayerPrefs be a feasible option?
You could use PlayerPrefs as a “global bucket” of sorts, but you have a few other options. Note that constantly reading from PlayerPrefs is like doing a disk read and is not something you want to do in an inner loop.
Some options…
1, You can “wire” them together in the editor by exposing public parameters. These show up in the editor and you can drag and drop an item into a public variable slot. Let’s say you have three scripts ScoreScript, BackgroundScrollScript, and ObstacleScript. You want BackgroundScrollScript and ObstacleScript to have access to ScoreScript. Define a public parameter for ScoreScript in BackgroundScrollScript and ObstacleScript…
public ScoreScript ScoreScriptCode;
… then in the editor select the GameObjects that has the BackgroundScrollScript and ObstacleScript attached to them. With them selected drag and drop the GameObject that has the ScoreScript attached to it. This will cause the editor to look through the dropped GameObject’s component and match the ScoreScript to the public ScoreScriptCode param.
2, If your obstacles are created at runtime using prefabs, which you should probably do, you will need to lookup your ScoreScript at runtime. I simply create a public static class called GLB (global) and expose a public static ScoreScript ScoreScriptCode and then on Start() of the ScoreScript I init the ScoreScriptCode param…
void Start()
{
...
GLB.ScoreScriptCode = this;
....
}
… you might want to change ScoreScript’s Start() to Awake() so that it is definitely init’d before BackgroundScrollScript and ObstacleScript are. All Awake() functions (for enabled Objects) are called before Start() is called.
3, You can use FindWithTag (Unity - Scripting API: GameObject.FindWithTag) if you tag the GameObject with ScoreScript as a component within the BackgroundScrollScript and ObstacleScript. I find that doing this on Start or Awake doesn’t always work. So instead I put a condition in my Update loop that skips out of Update until ScoreScript is found, something like…
private ScoreScript _scoreScript;
...
void Update ()
{
if (_scoreScript == null)
{
_scoreScript = GameObject.FindWithTag ("ScoreKeeper);
return;
}
... other Update code ...
}