Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Making a function that speeds up my flappy bird tutorial every 25 pipes

Discussion in 'Scripting' started by kriktsgrdn4evr, Feb 22, 2023.

  1. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12

    So I followed this tutorial to dip my toes back into unity after 5 years of being away. Everything works as it should and the game is "functional" but now I'm trying to tweak a few things. I want to call the "logic" script (which tallies the score every time the player goes through the middle pipe of a new pipe) so that every 25th time the "pipe spawn" script incriments its speed faster and the difficulty gets tougher. I'm just not sure how to go about this. I'm also having a hard time with which code I need to fix so that whenever the player goes 12 to -12 on the y axis the game over screen happens as well, let alone what that coding would look like. Any help would be super appreciated.
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,572
    Sorry, but that's not how to ask for help with your concrete problems. You followed a tutorial, that's great. However you haven't shown any of your code or where exactly you're stuck. We don't know how your game is actually made. Do you expect us to watch and follow that tutorial ourselfs to get the info what your code may look like? That's not gonna happen :)

    Maybe you're lucky and someone has actually watched that tutorial previously and can give you some advice. Though as I said, that's not how you should ask questions here.

    Tutorials are meant to teach you how it works. Most seem to use tutorials like free templates and that's it. Tutorials usually serve 2 purposes:
    • Someone actually explains most of the concepts of the game as it goes along.
    • You get a working project at the end that you can study yourself to better understand the individual parts
    The main point of a tutorial is to learn how it works, not to get free content.
     
    kriktsgrdn4evr and Yoreki like this.
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    At a high level, without looking at the code:
    • Count the pipes you passed. Triggers, or since they are uniform spaced, calculate it by coords.
    • Divide the counter by 25 and round it up or down to the next full integer to get a speed value
    • Use this value to adjust the scroll / flight speed in some way. Likely by multiplying by it and a scale value.
    I have no idea what you mean with the 12 to -12 part, probably talking about going out of bounds, but for that ill refer to what Bunny said: im not gonna watch the video. You should at least be able to post the relevant files, or explain what you mean conceptually in your own words. If you cant then you should start with something more simple, and actually follow the tutorial properly to understand what is responsible for what.
    @Kurt-Dekker has a blurb about doing tutorials properly which he loves to post :p
     
  4. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    Not trying to get free content from this, more or less trying to do exactly what you just said the tutorial was for. I learned a lot from the tutorial as a starting knowledge, I came here to learn more. The logical next step would be to learn how to do what I stated in my original post (making the difficulty through speed increment as the player progresses). As I have no idea how to do that, that is what I'm mainly asking.

    I also don't expect anyone to take time out of their day to watch the tutorial I watched and followed. I posted that just as context and a way to show "this is what I studied". I didn't know that I was supposed to put my coding in the thread (as I said I haven't touched Unity in 5 years at least, and I rarely ever used forums back then) but thank you for helping me with protocol, I will make sure to post screenshots of my codes and explain what I think I'm supposed to do with them from this building blocks. Hopefully that will lead to more concrete solutions, sorry for wasting your time.
     
    Yoreki likes this.
  5. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Not screenshots tho, we have code tags (there is a sticky on this subforum) for that. Screenshots only allow looking at the code, but not to quickly work with it. Code tags add syntax highlighting, line numbers and so on, and obviously allow us to quickly copy it to post solutions or try to reproduce an error.
     
    Bunny83 likes this.
  6. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    So this is the elements and prefabs in this level:

    - the Bird
    - the Pipes Prefab
    - the Bird Script
    - the Logic Script
    - the Pipe Middle Script
    - the Pipe Move Script
    - and the Pipe Spawn Script


    The bird is affected by the gravity which is at 2.5 and with this bird script
    Flappy Bird_Bird Script.png

    it gets the input of the spacebar as its "flapStrength" and causes it to bounce up with its velocity. The script also calls a reference to the logic script to aid with the game over state if it collides with the pipes collision
    Flappy Bird_Logic Script.png

    The Logic script calculates the player score and increases it by one every time the player passes through the "middle pipe" between the two pipes in prefab.
    Flappy Bird_Pipe Middle Script.png

    the Middle Pipe connects with the Logic Script through its Tag and also adds the score by 1

    Flappy Bird_Pipe Move Script.png

    The Pipe Move script creates the movement speed of the prefab as well as deletes the pipes that go to a certain point off screen so that it doesn't crash the game. (The tutorial said there were more effective ways to do this but never went over them)

    Flappy Bird_Pipe Spawn Script.png

    Finally the Pipe Spawn script creates a Spawn Rate and a Timer to spawn the pipes within a changeable variable that will effect the timer. The lower the number the faster the spawn rate because of the timer, the higher the number the farther space between pipes. It also randomizes the height of the pipes between a lowest and highest point, thus making them come in different patterns that the player has to go through.

    What I WANT to do, is affect the spawn rate using the middle pipe script (I assume) to effect the pipe move script or the Pipe Spawn script (which ever will get the job done) so that ever 25 pipes that are passed the spawn rate increases gradually as the player progresses.

    As for the 12 to -12 on the y axis I was speaking on before, that was indeed the out of bounds as you surmised. I am not sure how to code in through the game over state, that that is also a game over, because as of right now if you just let the bird fall and don't input anything at the start of the level the player will fall forever as the pipes scroll across the screen.

    I hope this was clearer and rectified the confusion from my original post. I wasn't asking for you guys to magically know the answer when I hadn't even shown the code, and I definitely didn't expect anyone to watch the video, that seems to have been a failure to communicate on my account, I showed it merely as a "this is what I followed" not a "watch this" sort of way. Again, any help would be useful.
     
  7. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    I JUST saw this... crap... okay hold on
     
    mopthrow, Yoreki and Bunny83 like this.
  8. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    Bird Code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class BirdScript : MonoBehaviour
    6. {
    7.     public Rigidbody2D myRigidbody;
    8.     public float flapStrength;
    9.     public LogicScript logic;
    10.     public bool birdIsAlive = true;
    11.  
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.         logic = GameObject.FindGameObjectWithTag("Logic").GetComponent<LogicScript>();
    16.     }
    17.  
    18.     // Update is called once per frame
    19.     void Update()
    20.     {
    21.        if (Input.GetKeyDown(KeyCode.Space) == true && birdIsAlive == true)
    22.         {
    23.             myRigidbody.velocity = Vector2.up * flapStrength;
    24.         }
    25.      
    26.      
    27.     }
    28.  
    29.     private void OnCollisionEnter2D(Collision2D collision)
    30.     {
    31.         logic.gameOver();
    32.         birdIsAlive = false;
    33.     }
    34. }
    Pipe Middle Code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PipeMiddleScript : MonoBehaviour
    6. {
    7.  
    8.     public LogicScript logic;
    9.  
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         logic = GameObject.FindGameObjectWithTag("Logic").GetComponent<LogicScript>();
    15.     }
    16.  
    17.     // Update is called once per frame
    18.     void Update()
    19.     {
    20.      
    21.     }
    22.  
    23.  
    24.     private void OnTriggerEnter2D(Collider2D collision)
    25.     {
    26.         if (collision.gameObject.layer == 3)
    27.         {
    28.             logic.addScore(1);
    29.         }
    30.    
    31.     }
    32. }
     
  9. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    Pipe Move Code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PipeMoveScript : MonoBehaviour
    6. {
    7.     public float moveSpeed = 5;
    8.     public float deadZone = -45;
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.  
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         transform.position = transform.position + (Vector3.left * moveSpeed) * Time.deltaTime;
    20.  
    21.  
    22.         if (transform.position.x < deadZone)
    23.         {
    24.             Debug.Log("Pipe Deleted");
    25.             Destroy(gameObject);
    26.         }
    27.     }
    28. }
    29.  
    30. Pipe Spawn Code:
    31.  
    32. [code=CSharp]using System.Collections;
    33. using System.Collections.Generic;
    34. using UnityEngine;
    35.  
    36. public class PipeSpawnScript : MonoBehaviour
    37. {
    38.     public GameObject pipe;
    39.     public float spawnRate = 2;
    40.     private float timer = 0;
    41.     public float heightOffset = 10;
    42.  
    43.     // Start is called before the first frame update
    44.     void Start()
    45.     {
    46.         spawnPipe();
    47.  
    48.     }
    49.  
    50.     // Update is called once per frame
    51.     void Update()
    52.     {
    53.        if (timer < spawnRate)
    54.         {
    55.             timer += Time.deltaTime;
    56.         } else
    57.         {
    58.             spawnPipe();
    59.             timer = 0;
    60.         }
    61.  
    62.  
    63.  
    64.     }
    65.  
    66.     void spawnPipe()
    67.     {
    68.         float lowestPoint = transform.position.y - heightOffset;
    69.         float highestPoint = transform.position.y + heightOffset;
    70.  
    71.         Instantiate(pipe, new Vector3(transform.position.x, Random.Range(lowestPoint, highestPoint), 0), transform.rotation);
    72.     }
    73. }
    [/code]


    Logic Code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class LogicScript : MonoBehaviour
    8. {
    9.     public int playerScore;
    10.     public Text scoreText;
    11.     public GameObject gameOverScreen;
    12.  
    13.     [ContextMenu("Increase Score")]
    14.     public void addScore(int scoreToAdd)
    15.     {
    16.         playerScore =  playerScore + scoreToAdd;
    17.         scoreText.text = playerScore.ToString();
    18.     }
    19.  
    20.  
    21.     public void restartGame()
    22.     {
    23.         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    24.     }
    25.  
    26.  
    27.     public void gameOver()
    28.     {
    29.         gameOverScreen.SetActive(true);
    30.     }
    31. }
     
  10. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Your LogicScript already tracks the score, which is the number of pipes passed, which you need for your 25 pipes speed mechanic. So add another variable to that script, called speedLevel. Whenever you calculate your score in addScore, also calculate speedLevel, which is basically just your new score divided by the desired pipe count (25) and rounded down. You need the speedLevel in the PipeMoveScript, so you need to either add a reference to the LogicScript (similar to PipeMiddleScript) or make the speedLevel variable static in order to easily access it. Now you can use the speedLevel in your calculations for the pipe movement. Directly multiplying it in there would likely be a bit heavy, so you want to scale it by some value, something like (1 + speedLevel * scaleValue), with a scaleValue somewhere in the 0.1 region or so. This would result in a 10% increase in base speed, for every 25 pipes passed.

    As for your out of bounds check, simply check your vertical coordinate inside the Bird Update() function and if you are where you shouldnt be, call gameOver(), as is done on collisions. You could also solve this by making the pipe colliders large enough so you cant miss them (on minimum speed) when going out of bounds. That way you could go out of bounds but would directly lose.
    Also, instead of directly going game over when out of bounds, you could try to Clamp the rigidbody coordinate to the desired region, so people could flap all they want but wouldnt go out of bounds. The gameover then happens naturally by hitting the next pipe. But that's a design decision.
     
    kriktsgrdn4evr likes this.
  11. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12

    Would the speedLevel variable be a float or int? and how do I check my vertical coordinate? this is one of the few times the overlap between Unreal coding and Unity is cross wiring so I'm not sure I know what the vertical coding is in Unity yet. Is it anything like:

    Transform.GetAxis("Vertical")?
     
  12. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    As you already know that Transforms are a thing, you'd be getting your answer a lot quicker by checking the documentation for these simple questions: https://docs.unity3d.com/ScriptReference/Transform.html
    We got a .position struct, which is a Vector3. As you are just reading the position that's fine, but be aware that when you are working with Rigidbodies, you are not supposed to set the transform.position directly and instead use the functions provided by the Rigidbody for that. Just in case you are going for the clamping approach instead of the gameover screen.

    Depends. You said you wanted it to (presumably abruptly) increase in speed every 25 pillars. Thus we want the speedValue to stay at 0 until the 24th pillar and directly jump to 1 at the 25th. Since we dont need any values inbetween, an integer would be the obvious choice. I said to round down anyways, in which case a float would behave pretty much the same - tho technically, working with an integer you dont even need to explicitely round down, as it'll strip the decimal places when casting from the float which is the result of the division.

    If instead you said to increase the speed steadily with every passed pillar, you could simply take the score itself to scale the speed with, and chose a smaller scaleValue to account for the larger number (so roughly 25x smaller scaleValue for same effect).
     
    kriktsgrdn4evr likes this.
  13. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    I realized that when I asked about the int or float I was still thinking of programming in terms of Unreal Engine and not Unity. So I did this and a bunch of errors came up, but this is how I understood what you said:

    Logic Script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class LogicScript : MonoBehaviour
    8. {
    9.     public int playerScore;
    10.     public Text scoreText;
    11.     public GameObject gameOverScreen;
    12.     public int speedLevel = 25f;
    13.  
    14.    
    15.  
    16.     [ContextMenu("Increase Score")]
    17.     public void addScore(int scoreToAdd)
    18.     {
    19.         playerScore =  playerScore + scoreToAdd / speedLevel;
    20.         scoreText.text = playerScore.ToString();
    21.     }
    22.  
    23.  
    24.     public void restartGame()
    25.     {
    26.         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    27.     }
    28.  
    29.  
    30.     public void gameOver()
    31.     {
    32.         gameOverScreen.SetActive(true);
    33.     }
    34. }

    Pipe Move Script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PipeMoveScript : MonoBehaviour
    6. {
    7.     public float moveSpeed = 5;
    8.     public float deadZone = -45;
    9.     public float scaleValue = 0.1;
    10.  
    11.     public LogicScript logic;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         logic = GameObject.FindGameObjectWithTag("Logic").GetComponent<LogicScript>();
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         transform.position = transform.position + (Vector3.left * moveSpeed) * Time.deltaTime (1 + speedLevel * scaleValue);
    23.  
    24.  
    25.         if (transform.position.x < deadZone)
    26.         {
    27.             Debug.Log("Pipe Deleted");
    28.             Destroy(gameObject);
    29.         }
    30.     }
    31. }

    clearly I misunderstood and missed a few steps from what I read and what I thought you meant
     
  14. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    There will be an error in the PipeMoveScript, since you just wrote speedLevel. There is no speedLevel inside of that script, that's why you referenced the logic script.. but then forgot to use it. It would be: logic.speedLevel.

    The value of speedLevel is rather useless tho, and would just cause your entire game to permanently run at 2.5x speed, since you never calculate it based on the pipe count. Instead you decrease the score you add. As i told you, you want to calculate speedValue whenever you adjust the score, so inside addScore. You yourself said that you want speed to increase whenever you pass 25 pipes, and that's exactly what the value of speedLevel should be: a 25th of your score.

    I'm not saying this to sound rude, but your issues have nothing to do with Unity vs Unreal. These are very basic problems with the fundamentals of object oriented programming as well as understanding the idea behind what you are trying to implement. I would highly suggest starting with something more easy. Generally, a course that teaches C# / OOP and Unity maybe. Personally i found Sebastian Lagues YT Series on that very beginner friendly:



    If might also be a great idea to start with logical thinking and problem solving skills in general:
    https://adriann.github.io/programming_problems.html
    (The first console input/output ones arent a great match for working in Unity, but the rest is purely algorithmic)
     
    Last edited: Feb 23, 2023
    kriktsgrdn4evr and mopthrow like this.
  15. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    343
    Just to add a few things from your scripts in post #13 that might save some headaches, it looks like you're having some problems with floats, ints and doubles.

    In your PipeMoveScript class on line 9, change 0.1 to 0.1f. If you don't include the f it thinks you're trying to assign a double instead of a float. It won't like that because you declared a float.

    In your LogicScript class on line 12, you declare an integer but try to assign a float value. Change 25f to 25. The f is for floats only and is not for ints.

    As a side note line 22 in PipeMoveScript looks like you missed a multiplication symbol after Time.deltaTime.

    Definitely do some more beginner-ish tutorials as @Yoreki suggests. It looks like you're more advanced than a beginner in some ways, but missing some critical information in others.

    Also consider not using the word 'Script' when naming your scripts. It's already obvious that it's a script and it's redundant to say so in the name.

    Good luck!
     
    Chubzdoomer and Yoreki like this.
  16. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    Thanks I'll look into it. I didn't take it as being rude, I know I have a lot to learn. I can grasp certain things but also can't understand basics I feel. I'm sure these videos might help along with the problem solving link you gave, thanks
     
    mopthrow and Yoreki like this.
  17. kriktsgrdn4evr

    kriktsgrdn4evr

    Joined:
    Dec 5, 2019
    Posts:
    12
    I didn't even realize "f" after a number was for float xD thanks. Yeah I'm definitely missing some critical information but thanks I'll definitely take your advice with the "Script" and I'm taking @Yoreki advice and trying his tutorials, hopefully it helps. Thanks for the input
     
    mopthrow and Yoreki like this.