diff --git a/404.html b/404.html index 9de6b35..4ffbc16 100644 --- a/404.html +++ b/404.html @@ -912,6 +912,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/ball-path-prediction/index.html b/botmaking/ball-path-prediction/index.html index 9c94171..ce198a6 100644 --- a/botmaking/ball-path-prediction/index.html +++ b/botmaking/ball-path-prediction/index.html @@ -966,6 +966,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/bot-customization/index.html b/botmaking/bot-customization/index.html index d6e3cdc..8da7afd 100644 --- a/botmaking/bot-customization/index.html +++ b/botmaking/bot-customization/index.html @@ -1025,6 +1025,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/config-file-documenation/index.html b/botmaking/config-file-documenation/index.html index 7817e03..8a9a909 100644 --- a/botmaking/config-file-documenation/index.html +++ b/botmaking/config-file-documenation/index.html @@ -1004,6 +1004,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/dropshot/index.html b/botmaking/dropshot/index.html index 6231a9f..5e91a35 100644 --- a/botmaking/dropshot/index.html +++ b/botmaking/dropshot/index.html @@ -1007,6 +1007,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/hoops/index.html b/botmaking/hoops/index.html index a82aa8c..6b7ab69 100644 --- a/botmaking/hoops/index.html +++ b/botmaking/hoops/index.html @@ -994,6 +994,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/input-and-output-data/index.html b/botmaking/input-and-output-data/index.html index 5d6f96a..090525e 100644 --- a/botmaking/input-and-output-data/index.html +++ b/botmaking/input-and-output-data/index.html @@ -933,6 +933,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/jumping-physics/index.html b/botmaking/jumping-physics/index.html index 36f34cc..8cb81c3 100644 --- a/botmaking/jumping-physics/index.html +++ b/botmaking/jumping-physics/index.html @@ -1024,6 +1024,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/machine-learning-faq/index.html b/botmaking/machine-learning-faq/index.html index 758e765..13a1036 100644 --- a/botmaking/machine-learning-faq/index.html +++ b/botmaking/machine-learning-faq/index.html @@ -926,6 +926,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/manipulating-game-state/index.html b/botmaking/manipulating-game-state/index.html index ecd70ce..b54c100 100644 --- a/botmaking/manipulating-game-state/index.html +++ b/botmaking/manipulating-game-state/index.html @@ -986,6 +986,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/matchcomms/index.html b/botmaking/matchcomms/index.html index 29c9ad5..222214e 100644 --- a/botmaking/matchcomms/index.html +++ b/botmaking/matchcomms/index.html @@ -1000,6 +1000,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/quickchat/index.html b/botmaking/quickchat/index.html index 5a882d9..aaa39b2 100644 --- a/botmaking/quickchat/index.html +++ b/botmaking/quickchat/index.html @@ -973,6 +973,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/rendering/index.html b/botmaking/rendering/index.html index 55975bc..1cbc9bb 100644 --- a/botmaking/rendering/index.html +++ b/botmaking/rendering/index.html @@ -977,6 +977,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/scripts/index.html b/botmaking/scripts/index.html index 48c56b2..aa9b50d 100644 --- a/botmaking/scripts/index.html +++ b/botmaking/scripts/index.html @@ -926,6 +926,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/shooting-the-ball-towards-or-away-from-a-target/index.html b/botmaking/shooting-the-ball-towards-or-away-from-a-target/index.html index 327ff67..a9272a6 100644 --- a/botmaking/shooting-the-ball-towards-or-away-from-a-target/index.html +++ b/botmaking/shooting-the-ball-towards-or-away-from-a-target/index.html @@ -1014,6 +1014,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/team-match-communication-protocol/index.html b/botmaking/team-match-communication-protocol/index.html index 5fdc3a1..1031c95 100644 --- a/botmaking/team-match-communication-protocol/index.html +++ b/botmaking/team-match-communication-protocol/index.html @@ -984,6 +984,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/tick-rate/index.html b/botmaking/tick-rate/index.html index e9eb85c..9d13d08 100644 --- a/botmaking/tick-rate/index.html +++ b/botmaking/tick-rate/index.html @@ -1000,6 +1000,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/botmaking/useful-game-values/index.html b/botmaking/useful-game-values/index.html index e22a934..de4b918 100644 --- a/botmaking/useful-game-values/index.html +++ b/botmaking/useful-game-values/index.html @@ -1018,6 +1018,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/community/air-show/index.html b/community/air-show/index.html index 37ba168..59bd947 100644 --- a/community/air-show/index.html +++ b/community/air-show/index.html @@ -1021,6 +1021,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/community/community-guidelines/index.html b/community/community-guidelines/index.html index 2e31a97..78c69cb 100644 --- a/community/community-guidelines/index.html +++ b/community/community-guidelines/index.html @@ -1053,6 +1053,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/community/rlbot-pack/index.html b/community/rlbot-pack/index.html index cd20360..42eccd7 100644 --- a/community/rlbot-pack/index.html +++ b/community/rlbot-pack/index.html @@ -983,6 +983,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/community/rocket-league-story-mode/index.html b/community/rocket-league-story-mode/index.html index 69573ad..e978e6f 100644 --- a/community/rocket-league-story-mode/index.html +++ b/community/rocket-league-story-mode/index.html @@ -987,6 +987,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/community/tips-for-running-tournaments/index.html b/community/tips-for-running-tournaments/index.html index 0d5bfb3..a64f84e 100644 --- a/community/tips-for-running-tournaments/index.html +++ b/community/tips-for-running-tournaments/index.html @@ -1122,6 +1122,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/framework/architecture/index.html b/framework/architecture/index.html index 3d80d8d..87e1eb3 100644 --- a/framework/architecture/index.html +++ b/framework/architecture/index.html @@ -889,6 +889,13 @@ Diagram Source Code + + +
  • + + RLBot v5 + +
  • @@ -1000,6 +1007,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + @@ -1296,6 +1323,13 @@ Diagram Source Code + + +
  • + + RLBot v5 + +
  • @@ -1368,6 +1402,9 @@

    Diagram Source Code

    DLL->RLBot.exe: send controls parallel off +

    RLBot v5

    +

    + diff --git a/framework/console-commands/index.html b/framework/console-commands/index.html index 7ebd757..aee18f0 100644 --- a/framework/console-commands/index.html +++ b/framework/console-commands/index.html @@ -980,6 +980,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + @@ -1289,11 +1309,24 @@

    Known Console Commands

    All of these are confirmed to work as intended. Please add more as you find them!

    Research for More Console Commands

    Try some of these!

    diff --git a/framework/operating-system-support/index.html b/framework/operating-system-support/index.html index c89094f..a53b477 100644 --- a/framework/operating-system-support/index.html +++ b/framework/operating-system-support/index.html @@ -902,6 +902,19 @@ Linux + +
  • @@ -917,6 +930,13 @@ Instructions +
  • + +
  • + + RLBot v5 on Mac + +
  • @@ -993,6 +1013,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + @@ -1262,6 +1302,19 @@ Linux + +
  • @@ -1277,6 +1330,13 @@ Instructions +
  • + +
  • + + RLBot v5 on Mac + +
  • @@ -1304,8 +1364,13 @@

    Operating system support

    Windows

    RLBot was originally made for Windows, so Windows has the best support. Users are encouraged to watch this video to get started quickly with RLBotGUI!

    Linux

    -

    RLBot only runs on linux with the old native linux version of rocket league. This version is only available on steam. There is a (probably outdated) install script here.

    -

    If you only have the epic version of the game or you want to run the proton version, you're unfortunately out of luck. This is due to libRLBotInterface.so being broken on linux. A rewrite of RLBot (v5) is being worked on and will support linux.

    +

    RLBot v4 only runs on Linux with the old native Linux version of Rocket League. This version is only available on Steam. There is a (probably outdated) install script here.

    +

    If you only have the Epic version of the game or you want to run the Proton version, you're unfortunately out of luck. This is due to libRLBotInterface.so being broken on Linux.

    +

    RLBot v5 on Linux

    +

    RLBot's next major version, RLBot v5, is aiming to properly support Linux. +RLBot v5 currently supports either Rocket League running under Proton on Steam or +Rocket League installed from the Epic Games Store via Legendary.

    +

    This version is currently in development, but you can inquire about the progress in the RLBot Discord. While support has been added for Linux, very few bots have been ported to run in RLBot v5.

    Mac

    Mac support is currently unknown and may not work. If you want to try, see the instructions below.

    Instructions

    @@ -1313,11 +1378,14 @@

    Instructions

  • Make sure you have Python 3.11 and pip
  • Run these commands
  • -
    python3 -m pip install --user --upgrade pip
    -python3 -m pip install --user gevent eel
    -python3 -m pip install --user --upgrade rlbot rlbot_gui
    -python3 -c "from rlbot_gui import gui; gui.start()"
    +
    python3 -m pip install --user --upgrade pip
    +python3 -m pip install --user gevent eel
    +python3 -m pip install --user --upgrade rlbot rlbot_gui
    +python3 -c "from rlbot_gui import gui; gui.start()"
     
    +

    RLBot v5 on Mac

    +

    Native MacOS support has been dropped. It's recommended to run both Rocket League +and RLBot under a virtual machine running Windows or Linux.

    diff --git a/framework/psyonix-api-notes/index.html b/framework/psyonix-api-notes/index.html index 9e2cd72..c389af4 100644 --- a/framework/psyonix-api-notes/index.html +++ b/framework/psyonix-api-notes/index.html @@ -918,8 +918,8 @@
  • - - What you can expect from this new version of RLBot + + What you can expect from this new version of RLBot (v4)
  • @@ -1007,6 +1007,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + @@ -1272,8 +1292,8 @@
  • - - What you can expect from this new version of RLBot + + What you can expect from this new version of RLBot (v4)
  • @@ -1333,7 +1353,7 @@

    Psyonix api notes

    Details

    Check out this diagram to get some intuition for this migration. Everything on the left staying the same or as close to the same as possible, so your bots are expected to keep working with no changes required!

    -

    What you can expect from this new version of RLBot

    +

    What you can expect from this new version of RLBot (v4)

    We're aiming for a backwards compatibility with this first bot API release, so expect your bots to play almost exactly like they used to!

    • The renderer now has occlusion, so 3D lines disappear behind objects correctly!
    • diff --git a/framework/sockets-specification/index.html b/framework/sockets-specification/index.html index 7f15c77..b066af9 100644 --- a/framework/sockets-specification/index.html +++ b/framework/sockets-specification/index.html @@ -942,6 +942,19 @@ Data Types + +
    • @@ -956,13 +969,6 @@ Sending Data -
    • - -
    • - - Future plans - -
    • @@ -1021,6 +1027,26 @@ + + + + + +
    • + + + + + RLBot v5 (Beta) Overview + + + + +
    • + + + +
    @@ -1290,6 +1316,19 @@ Data Types + +
  • @@ -1304,13 +1343,6 @@ Sending Data -
  • - -
  • - - Future plans - -
  • @@ -1387,6 +1419,83 @@

    Data Types

  • +

    RLBot v5

    +
      +
    1. None
        +
      • Aka the disconnect request.
      • +
      +
    2. +
    3. GameTickPacket
        +
      • Received by sessions at a high rate according to tick rate +(except "desired tick rate" is always 120hz in v5)
      • +
      +
    4. +
    5. FieldInfo
        +
      • Received by a session after it sends ConnectionSettings.
      • +
      +
    6. +
    7. StartCommand
        +
      • Starts a new match after reading the given config file.
      • +
      +
    8. +
    9. MatchSettings
        +
      • Received by a session after it sends ConnectionSettings.
      • +
      • Can be sent by sessions to start a new match.
      • +
      +
    10. +
    11. PlayerInput
        +
      • Sent by sessions to control their cars.
      • +
      +
    12. +
    13. DesiredGameState
        +
      • Sent by sessions to change the game state.
      • +
      • Ignored if state setting was disabled in the match settings.
      • +
      +
    14. +
    15. RenderGroup
        +
      • Sent by sessions to render lines & text in the game.
      • +
      • Ignored if render setting was disabled in the match settings.
      • +
      +
    16. +
    17. RemoveRenderGroup
        +
      • Sent by sessions to remove a render group.
      • +
      • Ignored if render setting was disabled in the match settings.
      • +
      +
    18. +
    19. MatchComm
        +
      • A copy is received by sessions when another session sends the message.
      • +
      • Messages may not be received if the message was filtered due to team_only being requested in the message.
      • +
      • Only received if enabled in ConnectionSettings.
      • +
      +
    20. +
    21. BallPrediction
        +
      • Received by sessions right before every GameTickPacket if enabled in ConnectionSettings.
      • +
      +
    22. +
    23. ConnectionSettings
        +
      • Sessions send this immediately after connecting.
      • +
      • Tells the server what kind of data it wants to receive.
      • +
      +
    24. +
    25. StopCommand
        +
      • Ends the current match, and optionally tells RLBotServer.exe to shut itself down.
      • +
      +
    26. +
    27. SetLoadout
        +
      • Sent by sessions to change the loadout of their cars.
      • +
      • Will always work if a loadout was not specified in match settings and when sent before InitComplete.
      • +
      • Ignored if state setting was disabled in the match settings, and a loadout was set in match settings.
      • +
      +
    28. +
    29. InitComplete
        +
      • Indicates that the session has finished all initialization and is ready to start receiving +game messages without delay.
      • +
      • The match will not start until all sessions have sent this message.
      • +
      • SpawnId will be used to set the name of the session in RLBot's performance monitor and when +filtering messages. Hiveminds should simply send the first spawn id they received from the framework.
      • +
      +
    30. +

    Connecting

    Prerequisites (handled automatically by RLBotGUI / the RLBot framework):

      @@ -1403,10 +1512,6 @@

      Connecting

      Sending Data

      Send data to the same TCP socket, using the same format (two bytes for type, two bytes for size). You can send match settings (starts a new match), player input, desired game state, render group, and quick chat.

      Consult google.github.io/flatbuffers to learn how to construct the byte array for your payload in the language of your choice.

      -

      Future plans

      -
        -
      • Allow clients to connect on a different port and exchange data in json format instead of flatbuffers.
      • -

      Client Libraries

      Python

        diff --git a/framework/supported-programming-languages/index.html b/framework/supported-programming-languages/index.html index 97f58c3..a4e3514 100644 --- a/framework/supported-programming-languages/index.html +++ b/framework/supported-programming-languages/index.html @@ -12,7 +12,7 @@ - + @@ -1076,6 +1076,26 @@ + + + + + +
      • + + + + + RLBot v5 (Beta) Overview + + + + +
      • + + + +
      diff --git a/framework/v5/index.html b/framework/v5/index.html new file mode 100644 index 0000000..9111c2e --- /dev/null +++ b/framework/v5/index.html @@ -0,0 +1,1690 @@ + + + + + + + + + + + + + + + + + + + + + + + RLBot v5 (Beta) Overview - RLBot Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + + Skip to content + + +
      +
      + +
      + + + + + + +
      + + +
      + +
      + + + + + + +
      +
      + + + +
      +
      +
      + + + + + +
      +
      +
      + + + +
      +
      +
      + + + +
      +
      +
      + + + +
      +
      + + + + +

      RLBot v5 (Beta) Overview

      +

      RLBot v5 is the next major update to the RLBot framework bringing a host of reliability improvements and some new features to the table.

      +

      RLBot v5 is now in beta. +In this beta period we will fix bugs, incorporate feedback, and potentially make minor breaking changes. +However, RLBot v5 should now be feature-complete and people can start adopting it. +Note that the various language interfaces are currently in development and may be unstable. +There is also no GUI and distribution method yet. +You can find the newest version of RLBotServer.exe on github.com/RLBot/core/releases. +See Virx' Video on how to get started in RLBot v5 beta with Python.

      +

      Any updates to RLBot v5 beta and language interfaces will be announced in the RLBot Discord #annoucements channel.

      + +

      In the remainder of this document we will cover:

      +
        +
      • Our reasoning for creating v5 and an overview of its architecture,
      • +
      • A list of features completed/reworked/todo/removed in v5 (beta),
      • +
      • A guide on how to transition from v4 to v5,
      • +
      • Links to v5 language interfaces and more.
      • +
      +

      Why v5?

      +

      RLBot v4 has been the most userfriendly and stable version of RLBot yet. +It was made in 2018 when RLBot was still using DLL injection. +Later, in 2019, the collaboration with Psyonix and the official API were revealed. +Since then, there have only been minor changes and new features, which proves how well-designed v4 was. +In fact, v5 is not that different from v4. +It is primarily a rewrite and an opportunity fix the flaws of v4 that have been revealed over the years. +So here are the main reasons we made v5:

      +
        +
      • The closed-sourced part of v4 is doing more than just communication with the Psyonix API. + This has long prevented the community from fixing certain bugs themselves. + Therefore we are extracting part of the closed-source part into the opens-source part of RLBot such that only the communication is closed-source.
      • +
      • The closed-sourced part of v4 is written in C++. + By rewritting the backend of RLBot in C# we hope that more people feel comfortable contributing to it.
      • +
      • No more DLLs. You may not be aware, but most bots still uses a DLL to communicate directly to the RLBot backend. + In v5, the transition to web sockets is finally complete and this allows the bot inferfaces to be improved (e.g. Python type hints are not a hack anymore).
      • +
      • All languages can start matches in v4, technically, but the logic for launching of Rocket League and bots was only implemented in Python (and partially Rust). + This discourage us from writing match starters (GUI, autoleague, etc) in other languages than Python (even CleoPetra in Java uses a Python process to start matches). + Therefore we move this logic to the backend for v5 such that more languages can benefit from it.
      • +
      • The Psyonix API made a few extra features availble to us, but we never integrated them in v4. They are integerated in v5.
      • +
      • Python is very slow. The rewrite in C# has made this clear.
      • +
      • The .cfg file format has no standard.
      • +
      +

      So while the changes to the functionality and interface are minor, the architecture and the framework's interal code is very different. +We hope these changes will make it enjoyable to work with and contribute to RLBot moving forward.

      +

      Features of v5

      +

      Legend: ✅=done, 🟨=todo, ✨=new, 🛠=reworked/changed, ⛔=removed

      +
        +
      • ✅🛠 First-class Windows & Linux support
          +
        • No current plans for MacOS, as there's no way to run Rocket League without a full VM
        • +
        +
      • +
      • ✅🛠 All bots connect to core directly via the sockets flatbuffer spec
          +
        • As a consequence, adding new language support is much easier - if your language can write/read +a TCP socket, it's possible! Bonus points if your language is one of the 14 that are currently supported +by FlatBuffers
        • +
        +
      • +
      • ✅🛠 Any language can still start/stop/manage a match, but the logic for launching Rocket League and bots are now in RLBotServer.
      • +
      • ✅🛠 All configs files now use the standard toml format. + Example: necto/bot.toml
      • +
      • ✅ Hiveminds
      • +
      • ✅ Scripts
      • +
      • ✅🛠 The bot configuration's python_file has been replaced with run_command and run_command_linux
          +
        • 🟨 On Linux, if run_command_linux isn't specified, v5 will attempt to run run_command under Wine
        • +
        +
      • +
      • ✅✨ Multi-ball support for when there's more/less than 1 ball in a game
      • +
      • ✅✨ New mutator options
          +
        • A Knockout match can be started
        • +
        • Start with one, two, four, or six balls
        • +
        • Max 7 goals
        • +
        • Beach ball, anniversary ball, spooky cube, or the haunted dropshot ball
        • +
        • Curve ball or beach ball curve
        • +
        • Medium ball size
        • +
        • Reverse gravity
        • +
        • Tactical rumble (fyi we still can't read rumble items)
        • +
        • Boost strength 5x
        • +
        • Max time 11 minutes
        • +
        +
      • +
      • ✅✨ Freeplay matches. Useful if you want to use the Rocket League's freeplay-exclusive features
      • +
      • ✅ Rendering
          +
        • 🟨 Rendering can be toggled for individual bots
        • +
        • â›” Keyboard shortcuts to toggle rendering. We plan to have buttons in the GUI instead!
        • +
        • ✅✨ New RenderAnchors. Attach your rendering to the location and rotation of a car or ball +plus both an absolute and local offset. No re-rendering is required and it is smooth. +Example: video posted on Discord
        • +
        +
      • +
      • ✅ Game state manipulation (aka state setting)
      • +
      • ✅ Updated ball prediction algorithm for better accuracy in all game modes that use a ball
      • +
      • ✅✨ Support for Psyonix Beginner bots
      • +
      • ✅✨ More customizable Psyonix bots
      • +
      • ✅✨ Override a bot name/loadout (without editing the bot configuration)
          +
        • Use cases include: Spawning specific Psyonix bots or give Nexto your in-game name to troll friends
        • +
        +
      • +
      • ✅🛠 Generated loadouts are now created by your bot instead of a separated loadout generator script
      • +
      • 🟨✨ Hot-swap your bot's loadout. Respawn your bot's car with a different loadout on command without + restarting the match or interfering with the other bots
          +
        • Only enabled when state setting is also enabled
        • +
        +
      • +
      • ✅✨ New data in GameTickPacket for every player:
          +
        • Last known player input
        • +
        • If the player was the last player to be spectated in the match
        • +
        • Player accolades. A list of small awards/events by the player, e.g. EpicSave, Demolition, PoolShot, LowFive, etc. +See full list here)
        • +
        +
      • +
      • ✅🛠 Match comms and quick chat have been combined into just MatchComms with an optional quick chat + message such that both bots and humans can understand what is meant
          +
        • â›” Quick chat messages are no longer restricted to a set of hardcoded options
        • +
        • ✅🛠 The team_only filtering finally works. No more spying on enemy chats
        • +
        +
      • +
      • ✅🛠 RLBot waits for all processes to fully boot before letting the match start
      • +
      • ✅ Performance metrics (i.e. missed responses by bots)
          +
        • â›” Keyboard shortcuts to toggle the performance graph. We plan to have buttons in the GUI instead! +Currently, the performance percentages will be shown anytime either RLBot itself or a bot is running below 100%.
        • +
        +
      • +
      • â›” Non-standard Tick Rates (standard is 120hz)
          +
        • All bots are now expected to run at 120hz. If you need more time to process inputs, it's advisable to +engineer your bot around this by, for example, using an extra asynchronous thread running complex algorithms.
        • +
        +
      • +
      • â›” DropshotTileInfo
          +
        • This functionality was lost with the introduction of the Psyonix API and is removed v5. But it might return.
        • +
        +
      • +
      +

      On top of all that, the framework is also simply significantly faster.

      +

      Breaking Changes / Migration

      +

      Many things will feel familiar in v5, but there's several breaking changes that have been made:

      +
        +
      • RLBot.exe has been renamed to RLBotServer.exe.
          +
        • Instead of the entire binary being closed-source, as much of the code as possible is now open-source +in RLBot/core.
        • +
        • Anyone can build RLBotServer.exe after making changes to the code due to Bridge.dll - this binary is +closed-source due to legal restrictions around the Psyonix API, but this knew binary was built to be as minimal +as possible while adhering to those restrictions.
        • +
        +
      • +
      • All bots are now expected to run at 120hz. If you need more time to process inputs, it's advisable to + engineer your bot around this by, for example, using an extra asynchronous thread running complex algorithms.
      • +
      • +

        Config files have changed

        +
          +
        • Instead of the arbitrary cfg file format, we now use toml files. This is a standardized format that +is easier to read and write and has better support over different languages. Many IDEs also support syntax +highlighting for toml files.
        • +
        • Bots config files must end in bot.toml. This includes hiveminds. Example valid file names include:
            +
          • bot.toml
          • +
          • super_bot.bot.toml
          • +
          • super_ultra.bot.toml
          • +
          +
        • +
        • Script config files must end in script.toml. Example valid file names include:
            +
          • script.toml
          • +
          • super_script.script.toml
          • +
          • super_ultra.script.toml
          • +
          +
        • +
        • Other config files have no defined naming convention.
        • +
        • +

          Bot/Script/Hivemind config file format:

          +
            +
          • [Locations] has been renamed to [settings]
          • +
          • hivemind must be set to true instead of [settings] if the bot is a hivemind
          • +
          • python_file, requirements_file, supports_standalone, and use_virtual_environment have been replaced +with a different concept: run_command and run_command_linux are ran in a shell to start the bot.
              +
            • Note: Bots submitted to the v5 botpack (TODO) will be expected to be packagable in a self-contained +executable that is built from source by an automated deployment pipeline. This includes Python bots.
            • +
            +
          • +
          • New optional value location - will set the working directory to something other than the directory that + the config file is currently located in.
          • +
          • maximum_tick_rate_preference has been removed, every bot is expected to run at 120hz
          • +
          • supports_early_start has been removed, as all bots are booted as soon as possible. Bots no longer know +their index when booting, but they do know their name & team.
          • +
          • looks_config and loadout_generator have been replaced with loadout_config
              +
            • If loadout_config is not set, then your bot can send a SetLoadout message during boot-up. This is a +direct replacement for the old loadout generator script.
            • +
            +
          • +
          • [Details] has been renamed to [details]
          • +
          • github has been renamed to source_link
          • +
          • Example of a bot config file in v4 and v5:
          • +
          +

          v4:

          +
          [Locations]
          +name = Necto
          +logo_file = ./necto_logo.png
          +looks_config = ./appearance.cfg
          +python_file = ./bot.py
          +requirements_file = ./requirements.txt
          +maximum_tick_rate_preference = 120
          +
          +[Details]
          +developer = Rolv, Soren, and several contributors
          +description = Necto is the official RLGym community bot, trained using PPO with workers run by people all around the world.
          +fun_fact = Necto uses an attention mechanism, commonly used for text understanding, to support any number of players
          +github = https://github.com/Rolv-Arild/Necto
          +language = rlgym
          +tags = 1v1, teamplay
          +
          +

          v5:

          +
          [settings]
          +name = "Necto"
          +logo_file = "necto_logo.png"
          +loadout_config = "loadout.toml"
          +run_command = ".\\venv\\Scripts\\python bot.py"
          +run_command_linux = "./venv/bin/python bot.py"
          +
          +[details]
          +developer = "Rolv, Soren, and several contributors"
          +description = "Necto is the official RLGym community bot, trained using PPO with workers run by people all around the world."
          +fun_fact = "Necto uses an attention mechanism, commonly used for text understanding, to support any number of players"
          +source_link = "https://github.com/Rolv-Arild/Necto"
          +language = "rlgym"
          +tags = ["1v1", "teamplay"]
          +
          +
        • +
        +
      • +
      • +

        All processes (bot, script & hivemind) are now similar to v4's concept of a StandaloneBot

        +
          +
        • This means that the only way to interface with RLBotServer.exe is by communicating via FlatBuffers over +a TCP socket. By default, the server listens to 0.0.0.0:23234. The port can be changed by passing in the +desired port as the first argument when starting the binary, for example RLBotServer.exe 54315.
        • +
        • In Python specifically, there is no longer a BaseAgent class. Instead, you must implement the Bot class.
        • +
        • Must read the environment variable RLBOT_SERVER_PORT to know what port they can connect to the server on.
        • +
        • Must read the environment variable RLBOT_SPAWN_IDS. It will be a single integer for bots and scripts, but for + hiveminds it will be a comma separated list of integers.
        • +
        +
      • +
      • Various changes have been made to the GameTickPacket
          +
        • Removed num_cars/num_pads as the list of cars/pads is now only as long as the actual number of cars/pads
        • +
        • Renamed cars to players
        • +
        • Replaced ball with balls which is now a list of balls in the game
        • +
        • Note: This list can have a length of zero in a normal match. It's recommended to check the length of + the list before assuming there's a ball in the game.
        • +
        • +

          In PlayerInfo:

          +
            +
          • Replaced is_demolished with demolished_timeout: demolished_timeout is a float representing the time + until the player respawns after being demolished. It is zero if the player is not demolished.
          • +
          • Added dodge_timeout: A float representing the time the player has left before they can no longer dodge. + -1 if the player cannot dodge (e.g. because they're on the ground or the dodge time window expired).
          • +
          • Replaced has_wheel_contact with a new concept, AirState. AirState is defined as:
          • +
          +
          enum AirState: ubyte {
          +  /// All wheels are on the ground
          +  OnGround,
          +  /// When the bot is jumping,
          +  /// then InAir right after
          +  Jumping,
          +  /// When the bot is double jumping,
          +  /// then InAir right after
          +  DoubleJumping,
          +  /// When the bot is dodging,
          +  /// then InAir right after
          +  Dodging,
          +  InAir,
          +}
          +
          +
            +
          • Removed jumped and double_jumped
          • +
          +
        • +
        +
      • +
      +

      The above list may be incomplete.

      + +

      Below we list where to find the implementation of RLBot v5, the language interfaces, and related documentation. +This wiki will also be updated as things stabilize.

      +

      RLBot v5 framework:

      + +

      Language interfaces (unstable):

      + + + + + + + +
      +
      + + +
      + +
      + + + +
      +
      +
      +
      + + + + + + + + + + \ No newline at end of file diff --git a/img/architecture/v5_diagram.drawio b/img/architecture/v5_diagram.drawio new file mode 100644 index 0000000..c15f424 --- /dev/null +++ b/img/architecture/v5_diagram.drawio @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/architecture/v5_diagram.png b/img/architecture/v5_diagram.png new file mode 100644 index 0000000..055e372 Binary files /dev/null and b/img/architecture/v5_diagram.png differ diff --git a/index.html b/index.html index b8ea1aa..028aca2 100644 --- a/index.html +++ b/index.html @@ -987,6 +987,26 @@ + + + + + +
    • + + + + + RLBot v5 (Beta) Overview + + + + +
    • + + + +
    diff --git a/miscellaneous/extracting-map-meshes/index.html b/miscellaneous/extracting-map-meshes/index.html index 80b6419..ae88906 100644 --- a/miscellaneous/extracting-map-meshes/index.html +++ b/miscellaneous/extracting-map-meshes/index.html @@ -9,7 +9,7 @@ - + @@ -921,6 +921,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + @@ -1491,9 +1511,8 @@

    Converting the object to binary da

    image

    If you want an example of using collision data and compiling them into a mesh to run collision queries on, check out the rl_ball_sym Rust project:

    diff --git a/miscellaneous/lan-setup/index.html b/miscellaneous/lan-setup/index.html index f048477..d4055bc 100644 --- a/miscellaneous/lan-setup/index.html +++ b/miscellaneous/lan-setup/index.html @@ -921,6 +921,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/miscellaneous/missing-pages/index.html b/miscellaneous/missing-pages/index.html index e6b2e48..1f6081c 100644 --- a/miscellaneous/missing-pages/index.html +++ b/miscellaneous/missing-pages/index.html @@ -916,6 +916,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/miscellaneous/rlbot-specific-game-settings/index.html b/miscellaneous/rlbot-specific-game-settings/index.html index f2d03b6..e77fdc2 100644 --- a/miscellaneous/rlbot-specific-game-settings/index.html +++ b/miscellaneous/rlbot-specific-game-settings/index.html @@ -921,6 +921,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/miscellaneous/workshop-custom-maps/index.html b/miscellaneous/workshop-custom-maps/index.html index 0eff5e1..497484d 100644 --- a/miscellaneous/workshop-custom-maps/index.html +++ b/miscellaneous/workshop-custom-maps/index.html @@ -921,6 +921,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/search/search_index.json b/search/search_index.json index b1acff6..e5d3fd7 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"RLBot","text":"

    Welcome to the RLBot wiki!

    "},{"location":"#getting-started","title":"Getting Started","text":"
    • Download RLBot
    • Botmaking Setup Guides
    "},{"location":"#video-tutorials","title":"Video tutorials","text":"
    • Setup/Python/GoslingUtils Tutorials by GooseFairy
    • C#/RedUtils tutorial by CodeRed
    • Java tutorial by Eastvillage
    • Python/VirxERLU Tutorials by VirxEC
    • Python video tutorials from Learn Code By Gaming
    • Language agnostic tutorial explaining useful concepts by b2studios
    "},{"location":"#language-specific-wikis","title":"Language-specific wikis","text":"
    • Officially supported languages
    • Other community supported languages
    • Machine Learning FAQ
    • RLGym
    "},{"location":"#text-tutorials","title":"Text tutorials","text":"
    • Shooting the ball towards or away from a target
    • Dodges (C#)
    • State systems (C#)
    "},{"location":"#commonly-used-resources","title":"Commonly Used Resources","text":"
    • GameTickPacket, FieldInfo, and Controllers
    • Useful Game Values (Field Size, Boost Pad Locations, and more)
    • Quickchats
    • Rendering
    • Dropshot and Related Information
    • Appearance Customization
    • Ball Prediction
    • The RLBotPack
    • Team Match Communication Protocol (TMCP)
    • Troubleshooting
    "},{"location":"#physics","title":"Physics","text":"
    • RocketSim by Zealan
    • Ball Physics by @Chip
    • Ball Collision by @Chip
    • Ground Car Control by @Chip
    • Aerial Car Control by @Chip
    • Inverse Aerial Car Control by @Chip
    • Aerial ball intercept/hit by @Chip
    • How Car and Ball Interact by @Chip
    • How to Analyze Drivable Paths by @Chip
    • The Physics Of Jumping by Impossibum
    • Extracting Map Meshes by Virx
    "},{"location":"#unofficial-but-helpful-code-repositories","title":"Unofficial but Helpful Code Repositories","text":"
    • Utilities by @Chip
    • GoslingUtils by GooseFairy
    • VirxERLU (aka GoslingUtils 2.0) by VirxEC
    • Source code to East's Java Tutorial
    • RedUtils by CodeRed
    "},{"location":"botmaking/ball-path-prediction/","title":"Ball path prediction","text":"

    When writing a bot, it's very useful to know where the ball will be a few seconds in the future. This is very challenging because the ball responds to gravity, drag, friction, spin, and bounces off of curvy walls. Fortunately, chip has your back. He did a meticulous study of the ball physics and built an extremely accurate model: https://samuelpmish.github.io/notes/RocketLeague/ball_bouncing/

    Note: this is just an estimate of what the ball will be doing in the future, it is not exact! It is recommended that you routinely update your predictions to have the most accurate estimates.

    The fruit of that labor is now available to your bot with a simple function! Just call the function and you get 6 seconds' worth of ball positions, each advancing 1/60 of a second into the future.

    "},{"location":"botmaking/ball-path-prediction/#language-specific-examples","title":"Language-specific examples","text":"

    (support for more languages coming soon):

    • Python
    • Java
    • C#
    "},{"location":"botmaking/bot-customization/","title":"Bot customization","text":""},{"location":"botmaking/bot-customization/#gui-customization","title":"GUI Customization","text":"

    The easiest way to customize your bot appearance is via RLBotGUI. To bring up the appearance editor, click on the bot info icon and then click Edit Appearance.

    Video guide

    You can use any item in the game, including painted items. The editor should have the latest items, but we have to manually update them. So if some recently added items are missing, please remind us on our discord. You can also click the bottom left buttons to preview your loadout in-game instantly!

    Tip: When previewing in-game and trying multiple loadouts, sometimes the camera will lose track of your car when it respawns. You can avoid this by cycling the camera with your mouse buttons instead of using the number keys. With this technique it should be possible to get into a camera mode like hard-attach and have it be stable as you look at different wheels, blue car vs orange car, etc.

    "},{"location":"botmaking/bot-customization/#manual-customization","title":"Manual Customization","text":"

    In your bot's config file you can set your bot's display name. You can have a name of max 31 characters. If your name is too long or there is duplicates that is handled in the framework.

    Example (bot.cfg file):

    [Locations]\n# Path to loadout config. Can use relative path from here.\nlooks_config = ./appearance.cfg\n\n# Path to python file. Can use relative path from here.\npython_file = ./python_example.py\n\n# Path to a file that can dynamically generate your bot's appearance. Optional.\nloadout_generator = example_loadout_generator.py\n\n# Name of the bot in-game\nname = PythonExampleBot\n\n# Optional: Location of a logo file to to show in RLBotGUI and tournament overlays. 400x300px preferred.\nlogo_file = ./logo.png\n

    The field looks_config should point to an appearance file. An appearance.cfg file could look like this:

    [Bot Loadout]\nteam_color_id = 27\ncustom_color_id = 75\ncar_id = 23\ndecal_id = 307\nwheels_id = 1656\nboost_id = 0\nantenna_id = 287\nhat_id = 0\npaint_finish_id = 1978\ncustom_finish_id = 1978\nengine_audio_id = 0\ntrails_id = 0\ngoal_explosion_id = 1971\nprimary_color_lookup = [50, 0, 200]\nsecondary_color_lookup = [100, 100, 250]\n\n[Bot Loadout Orange]\n# Same as above, except it applies to the orange car\n
    "},{"location":"botmaking/bot-customization/#item-ids","title":"Item IDs","text":"

    The GUI appearance editor uses a csv file generated by BakkesMod using the dumpitems command. You can see the most recently generated file here: https://github.com/RLBot/RLBotGUI/blob/master/rlbot_gui/gui/csv/items.csv

    To see the items, you might want to browse at: https://rocket-league.com/items/

    "},{"location":"botmaking/bot-customization/#colors","title":"Colors","text":"

    There are two ways to specify your colors:

    1. Use team_color_id and custom_color_id to index into the swatches (see images below).
    2. Use primary_color_lookup and secondary_color_lookup to choose a swatch closest to the RGB value you provide.

    In either case, you're limited to the same set of colors that can be selected in-game.

    NOTE: The shade of the colors may not be correspond exactly with following pictures.

    team_color_id are the primary color of the car. The top left color is index 0 increasing as you go right:

    custom_color_id is the secondary color, also called accent. These are identical for both teams:

    "},{"location":"botmaking/bot-customization/#painted-items","title":"Painted Items","text":"

    You can use a number based on this list:

    • 0 - None
    • 1 - Crimson
    • 2 - Lime
    • 3 - Black
    • 4 - Sky Blue
    • 5 - Cobalt
    • 6 - Burnt Sienna
    • 7 - Forest Green
    • 8 - Purple
    • 9 - Pink
    • 10 - Orange
    • 11 - Grey
    • 12 - Titanium White
    • 13 - Saffron

    These are set in your appearance cfg file. Example:

    [Bot Paint Blue]\ncar_paint_id = 12\ndecal_paint_id = 0\nwheels_paint_id = 7 \nboost_paint_id = 7\nantenna_paint_id = 0\nhat_paint_id = 0\ntrails_paint_id = 2\ngoal_explosion_paint_id = 0\n\n[Bot Paint Orange]\n...\n
    "},{"location":"botmaking/bot-customization/#loadout-generator","title":"Loadout Generator","text":"

    This is completely optional!

    Recently we added the ability to generate your bot's loadout with a python script. This lets you choose different loadouts based on player index, randomize parts of your loadout, etc. The script is executed at the beginning of every match.

    To use this feature, put a line like loadout_generator = loadout_generator_example.py in your bot cfg file, in the [Locations] section. Then create a python file like this:

    import random\nfrom pathlib import Path\n\nfrom rlbot.agents.base_loadout_generator import BaseLoadoutGenerator\nfrom rlbot.matchconfig.loadout_config import LoadoutConfig\n\n\nclass SampleLoadoutGenerator(BaseLoadoutGenerator):\n    def generate_loadout(self, player_index: int, team: int) -> LoadoutConfig:\n\n        # You could start with a loadout based on a cfg file in the same directory as this generator\n        loadout = self.load_cfg_file(Path('appearance.cfg'), team)\n\n        # Or you could start from scratch like this\n        # loadout = LoadoutConfig()\n\n        if player_index == 0:\n            loadout.antenna_id = 287  # use a Psyonix flag if you're the first player\n\n        loadout.team_color_id = player_index  # Different primary color depending on player index\n        loadout.paint_config.wheels_paint_id = random.choice([1, 2, 4, 5])  # Random wheel color\n\n        return loadout\n
    "},{"location":"botmaking/bot-customization/#bot-logos","title":"Bot Logos","text":"

    Either put a file called logo.png in the same folder as your bot cfg, OR specify logo_file = ... in your bot cfg in the same section as python_file. Dimensions of 400x300 px are preferred. It will appear in RLBotGUI, and maybe on stream!

    "},{"location":"botmaking/bot-customization/#need-inspiration","title":"Need inspiration?","text":"

    reddit.com/r/RLFashionAdvice

    "},{"location":"botmaking/config-file-documenation/","title":"Bot Config File","text":""},{"location":"botmaking/config-file-documenation/#sections","title":"Sections","text":""},{"location":"botmaking/config-file-documenation/#locations","title":"Locations","text":"

    This section is poorly named at this point, but oh well. It includes:

    • looks_config: The location of your bot's appearance config, relative to the cfg file.
    • python_file: The location of your bot's python file, relative to the cfg file.
    • logo_file: Optional. The location of an image that will represent your bot in RLBotGUI, tournament overlays, etc.
    • name: The name of your bot in-game.
    • supports_early_start: Optional. Indicates whether your bot can handle the early start system. Read below for details.
    • requirements_file: Optional. The location of a requirements.txt for your bot. If specified, RLBotGUI will use it to warn people if there's a missing dependency, and they'll have the option to install your requirements.txt file.
    • use_virtual_environment: Optional, defaults to False. Installs your bot's requirements from the requirements.txt file into a python venv so they're isolated from potentially conflicting requirements from other bots. See pr #535
    • loadout_generator: Optional. Location of a script that can influence your bot's appearance on startup for randomization / index-dependent changes. See loadout generator
    • requires_tkinter: Optional. Set it to true if your bot needs tkinter, and if the user is running a GUI which lacks tkinter, they will be warned.
    "},{"location":"botmaking/config-file-documenation/#bot-parameters","title":"Bot Parameters","text":"

    This is mainly for bot makers to add arbitrary config values useful to them. Generally the framework doesn't care what you put here, except in the case of Scratch bots.

    "},{"location":"botmaking/config-file-documenation/#details","title":"Details","text":"

    This section is for metadata about your bot which can be displayed to people in RLBotGUI, tournament overlays, etc. Common details included:

    • developer: The name of the developer(s) of the bot.
    • description: Textual description of the bot, its playstyle, how to use it, etc.
    • fun_fact: A short fun fact about the bot. Sometimes displayed on stream during tournaments.
    • github: A github link
    • language: Which language/technology the bots was made with
    • tags: A comma separated list of tags. Primarily used by the RLBotGUI to put the bot in the correct tabs. Common tags include: 1v1, teamplay, goalie, hoops, dropshot, snow-day, rumble, spike-rush, heatseeker, memebot
    "},{"location":"botmaking/config-file-documenation/#early-start-system","title":"Early Start System","text":"

    If a bot adds supports_early_start = True then it will be started up before the Rocket League match loads, which gives it lots of extra time. To live happily in this situation the bot MUST be able to deal with weird game tick packets, e.g.:

    • Could have unexpected bots / unexpected teams
    • The bot's index might be higher than the packet's num_cars
    • The packet may transition suddenly to a different set of cars, different game type, etc
    "},{"location":"botmaking/config-file-documenation/#match-config-file-rlbotcfg","title":"Match Config File (rlbot.cfg)","text":"

    This configuration controls which bots are in the game, what arena to play on, what mutators to use, etc. Example config

    "},{"location":"botmaking/config-file-documenation/#sections_1","title":"Sections","text":"
    • RLBot Configuration: Contains miscellaneous overall configurations
    • Team Configuration: Configurations at the team level
    • Match Configuration: Configurations for a specific match
    • Mutator Configuration: Mutators for a specific match
    • Participant Configuration: What participants are playing
    • Scripts: What scripts should be ran
    "},{"location":"botmaking/config-file-documenation/#rlbot-configuration","title":"RLBot Configuration","text":"
    • extensions_path: A path to the extension file used later on for extra game controlling needs
    • launcher_preference: 'steam' or 'epic'. For people who have the game on both, determines which launcher is preferred for opening Rocket League.
    "},{"location":"botmaking/config-file-documenation/#team-configuration","title":"Team Configuration","text":"

    NOTE: None of these take an effect currently

    • Team Blue Color: Changes Blue team color, use 0 to use default color
    • Team Blue Name: Changes the Team name to use instead of 'Blue'
    • Team Orange Color: Changes Blue team color, use 0 to use default color
    • Team Orange Name: Changes the Team name to use instead of 'Orange'
    "},{"location":"botmaking/config-file-documenation/#match-configuration","title":"Match Configuration","text":"
    • num_participants: The total number of cars that will be spawned into the match.
    • game_mode: 'Soccer', 'Hoops', 'Dropshot', 'Hockey', 'Rumble'
    • game_map, e.g. \"Mannfield\". All possible values
    • skip_replays: If True, replays are automatically skipped after a goal. However, also prevents match replays from being saved.
    • start_without_countdown: If True, skips kickoff countdown
    • existing_match_behavior: 'Restart If Different', 'Restart', 'Continue And Spawn'
    • enable_lockstep: If True, the framework will wait for outputs from all bots before advancing to the next frame.
    • enable_rendering: If True, bots' debug rendering is turned on at the start of a match (toggle it with page up/down).
    • enable_state_setting: If True, bots are allowed to manipulate the game state (useful during development).
    • auto_save_replay: If True, the match replay is automatically saved.
    "},{"location":"botmaking/config-file-documenation/#mutator-configuration","title":"Mutator Configuration","text":"

    All of these default to the \"normal\" value (the first in the list) if you don't specify them.

    • Match Length: Changes the length of the match. '5 Minutes', '10 Minutes', '20 Minutes', 'Unlimited'
    • Max Score: Changes the number of goals needed to win. 'Unlimited', '1 Goal', '3 Goals', '5 Goals'
    • Game Speed: 'Default', 'Slo-Mo', 'Time Warp'
    • Overtime: 'Unlimited', '+5 Max, First Score', '+5 Max, Random Team'
    • Ball Max Speed: 'Default', 'Slow', 'Fast', 'Super Fast'
    • Ball Type: 'Default', 'Cube', 'Puck' or 'Basketball'
    • Ball Weight: 'Default', 'Super Light', 'Light' or 'Heavy'
    • Ball Size: 'Default', 'Small', 'Large', 'Gigantic'
    • Ball Bounciness: 'Default', 'Low', 'High', 'Super High'
    • Boost Amount: 'Default', 'Unlimited', 'Recharge (Slow)', 'Recharge (Fast)' or 'No Boost'
    • Rumble: 'None', 'Default', 'Slow', 'Civilized', 'Destruction Derby', 'Spring Loaded', 'Spikes Only' or 'Spike Rush'
    • Boost Strength: '1x', '1.5x', '2x', '10x'
    • Gravity: 'Default', 'Low', 'High' or 'Super High'
    • Demolish: 'Default', 'Disabled', 'Friendly Fire', 'On Contact' or 'On Contact (FF)'
    • Respawn Time: '3 Seconds', '2 Seconds', '1 Second', 'Disable Goal Reset'
    "},{"location":"botmaking/config-file-documenation/#participant-configuration","title":"Participant Configuration","text":"
    • participant_config_NUMBER: The path to a participant configuration
    • participant_team_NUMBER: what team the bot is on
    • participant_type_NUMBER: the type of the bot Accepted values are \"human\", \"rlbot\", \"psyonix\", \"party_member_bot\", and \"controller_passthrough\", You can have up to 4 local humans and they must be activated in game or it will crash. If no player is specified you will be spawned in as spectator!
    • human - not controlled by the framework (but must appear before bot entries)
    • rlbot - controlled by the framework
    • psyonix - default bots (skill level can be changed with participant_bot_skill
    • party_member_bot - controlled by an rlbot but the game detects it as a human
    • controller_passthrough - controlled by a human but runs through the framework
    • participant_bot_skill_NUMBER: 0.0 is Rookie, 0.5 is pro, 1.0 is all-star
    • participant_loadout_config_NUMBER: the path to the loadout. This overrides the agent config if not None

    Example contents:

    participant_config_0 = my_folder/my_bot.cfg\nparticipant_config_1 = my_folder/other_bot.cfg\n\nparticipant_team_0 = 0\nparticipant_team_1 = 1\n\nparticipant_type_0 = rlbot\nparticipant_type_1 = rlbot\n\nparticipant_bot_skill_0 = 1.0\nparticipant_bot_skill_1 = 1.0\n
    "},{"location":"botmaking/config-file-documenation/#scripts","title":"Scripts","text":"

    This field is optional, by default no scripts will be ran.

    • script_config_NUMBER: The path to the script configuration

    Example contents:

    script_config_0 = src/test/python/agents/script/sample_script.cfg\nscript_config_1 = src/test/python/agents/script/sample_script.cfg\n
    "},{"location":"botmaking/dropshot/","title":"Dropshot","text":"

    As of August 19. 2018 the RLBot framework officially supports Dropshot with access to locations and states of floor tiles. This page contains information and useful values related to the Dropshot game mode.

    To make RLBot start a Dropshot game you have to set the following values in rlbot.cfg:

    game_mode = Dropshot\ngame_map = DropShot_Core707\n
    "},{"location":"botmaking/dropshot/#tiles","title":"Tiles","text":"

    There are 140 tiles in total. Locations and owning team can be found in the agent's FieldInfo as GoalInfo objects. In Python self.get_field_info().goals will be a list of the floor tiles with following attributes:

    GoalInfo: {\n  'team_num': int,\n  'location': Vector3,\n  'direction': Vector3,\n}\n

    Example: To access the location of tile 0 in Python, write: self.get_field_info().goals[0].location

    A list of all locations can be found here.

    To access the state of tile 0 in Python, write: packet.dropshot_tiles[0].tile_state. This is an integer which corresponds to:

    • 0: Unknown
    • 1: Filled
    • 2: Damaged
    • 3: Open

    The tiles will be sorted the same way in FieldInfo and GameTickPacket so indices match.

    The tiles are hexagonal in shape. The distance between centres is 768 uu (except for the middle where the distance from blue tiles to orange tiles is 256 uu. A neutral strip about 128 uu wide covers the tiles partially). The image below shows the relative dimensions of a Dropshot tile.

    "},{"location":"botmaking/dropshot/#arena","title":"Arena","text":"

    The tiles are layed out in rows of 7,8,9,10,11,12,13 |middle| 13,12,11,10,9,8,7. Where tile 0 is in the blue corner (back left if you are on blue team) and tile 139 is in an orange corner (back left if you are on the orange team).

    The overall layout of the arena and tile indices can be seen below.

    The arena is a regular hexagon except its rounded corners. Here are some dimensions:

    • Center: (0, 0)
    • Floor level: 3.2 uu
    • Center to wall: 4555 uu
    • Center to corner: 5026 uu
    • Center to corner (without rounding walls): 5259.66 uu
    • Wall length: about 5026 uu
    • Arena height: 1986 uu

    Note that the tiles on the boundaries are not complete - the rounded base of the walls overlaps the tiles to varying degrees (approximately 30-40% of the tile is overlapped, and the tile centrepoints are always visible).

    You may notice that tiles' locations are at z=0, but floor level is z=3.2. This is because the tiles have a thickness.

    "},{"location":"botmaking/dropshot/#within-arena-script","title":"Within arena script","text":"

    Here's a small script to check if a point is within the arena:

    def is_within_arena(point):\n    HEIGHT = 1986\n    TO_WALL = 4555\n    TO_CORNER = 5260  # 4555 / math.sin(60)\n\n    if point.z < 0 or HEIGHT < point.z:\n        return False\n\n    ax = abs(point.x)\n    ay = abs(point.y)\n\n    if TO_CORNER < ax or TO_WALL < ay:\n        return False\n\n    return TO_WALL * TO_CORNER - TO_WALL * ax - 0.5 * TO_CORNER * ay >= 0;\n
    "},{"location":"botmaking/dropshot/#ball","title":"Ball","text":"

    Ball radius: 102.24 uu

    The GameTickPacket contains Dropshot info about the ball. It can be found in the DropshotBallInfo object at packet.game_ball.drop_shot_info which contains the variables: absorbed_force, damage_index, and force_accum_recent.

    The ball has three phases. The current phase is the variable damage_index where:

    • 0: Normal
    • 1: Charged
    • 2: Super Charged

    The ball gains charge as it is hit by cars. When a car exerts a force on the ball, the ball charges up equal to the magnitude of the force (energy). The ball enters the next phase when it reaches a certain threshold:

    • Charged: 2500 energy
    • Super Charged: 11000 energy

    The current amount of energy (force absorded) is the absorbed_force variable.

    However, a hit does not always charge the ball. To make the ball charge up, the impact must be at least 500 energy, otherwise the ball will not charge at all. Furthermore, when the ball gets hit, it will temporarily accept less energy. The variable force_accum_recent stores the accumulated absorbed force (energy), but no more than 2500 energy. It decays over time at a rate of 2500 energy per second, and the ball will at most absorb 2500 - force_accum_recent energy on a hit. Combined, this prevents players from charging the ball too quickly, limited to 2500 energy every second.

    Example: if you hit the ball with an impact of 2000 uu/s at t=0, and you hit the ball again with a force of 2000 uu/s at t=0.5, the force_accum_recent has decayed by 1250 and will be 750 when you hit the ball the second time, and therefore the ball will not accept more than 1750 energy, which means 250 energy gets lost.

    The ball's charge is reset, whenever it damages a floor tile owned by the opponent of whoever last touched the ball. To make damage the ball must hit the tile with a velocity of 250 uu/s or more perpendicular to the surface of contact. The side of a tile can only be hit if there's an open tile next to it, so usually the ball will hit the top of the tiles, and in those cases only the Z velocity matters, and must be 250 uu/s or more to make damage. There is also must have passed 0.2 seconds since the last time the ball damaged a tile.

    You can tell which team last hit the ball by checking the packet.game_ball.latest_touch object. See Input and output for more.

    At kickoff the ball is launched straight up into the air with a velocity of 1000 uu/s and reaches a height of about 847 uu in 1.54 seconds.

    "},{"location":"botmaking/dropshot/#spawning","title":"Spawning","text":"

    You always spawn with 100 boost.

    Kickoff spawn locations are similar to soccer spawn locations, but not identical. In dropshot spawn locations are:

    Kickoff Blue Orange Right corner loc: (-1867, -2379), yaw: 0.25 pi loc: (1867, 2379), yaw: -0.75 pi Left corner loc: (1867, -2379), yaw: 0.75 pi loc: (-1867, 2379), yaw: -0.25 pi Back right loc: (-256.0, -3576), yaw: 0.5 pi loc: (256.0, 3576), yaw: -0.5 pi Back left loc: (256.0, -3576), yaw: 0.5 pi loc: (-256.0, 3576), yaw: -0.5 pi Far back center loc: (0.0, -4088), yaw: 0.5 pi loc: (0.0, 4088), yaw: -0.5 pi Demolished Blue Orange Right corner loc: (-2176, -3408), yaw: 0.5 pi loc: (2176, 3408), yaw: -0.5 pi Left corner loc: (2176, -3408), yaw: 0.5 pi loc: (-2176, 3408), yaw: -0.5 pi"},{"location":"botmaking/dropshot/#boost-regeneration","title":"Boost regeneration","text":"

    In Dropshot you regenerate boost at a rate of about 10 boost/sec. However, you do not regen boost while boosting. When you stop boosting (or run out of boost), there is a delay of about 0.5 second before you start gaining boost again. If you are at 0 boost and boost button is pressed, the timer will reset every 0.5 seconds until the button is released.

    "},{"location":"botmaking/hoops/","title":"Hoops","text":"

    The RLBot framework support the Hoops game mode. This page contains useful values specifically about Hoops.

    To make RLBot start a Hoops game you have to set the following values in rlbot.cfg:

    game_mode = Hoops\ngame_map = Hoops_DunkHouse\n
    "},{"location":"botmaking/hoops/#arena","title":"Arena","text":"

    Hoops is always played on the map Dunk House. The dimensions for the arena are:

    • Floor: z=0
    • Side wall: x=2966.67
    • Back wall: y=3586
    • Ceiling: z=????
    "},{"location":"botmaking/hoops/#goals","title":"Goals","text":"

    In Hoops the goals are two rings. The rings are placed ??? uu above the ground. Their radius is 753 uu but they are connected to the wall with straight lines.

    Center of goals: ??? Distance from back wall: ???

    "},{"location":"botmaking/hoops/#boost-pads","title":"Boost Pads","text":"

    Locations of all boost pads:

    ????\n
    "},{"location":"botmaking/hoops/#ball","title":"Ball","text":"

    The radius of the ball is 98.38 uu. But other than that, the physics of the ball is similar to soccer.

    "},{"location":"botmaking/hoops/#spawning","title":"Spawning","text":"Kickoff Blue Orange Right corner loc: ???, yaw: 0.25 pi loc: ??? yaw: -0.75 pi Left corner loc: ???, yaw: 0.75 pi loc: ???, yaw: -0.25 pi Back right loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Back left loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Far back center loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Demolished Blue Orange Right corner loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Left corner loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi"},{"location":"botmaking/input-and-output-data/","title":"Input and Output Data (current)","text":"

    All supported languages have access to the same data, though syntax and conventions will vary. It is controlled by this specification: rlbot.fbs

    Language-specific guides:

    • Python
    • Java
    • C#
    • Rust
    • Nim
    "},{"location":"botmaking/jumping-physics/","title":"The Physics Of Jumping","text":"

    There are several forces that can be acting on a Rocket League car at any moment and understanding their influence is an important step towards giving your bot accurate and dependable utilities. This section will be focused on the mechanics of jumping and how these forces interact to allow you to accurately simulate a jump and provide useful information such as how high your bot can reach and at what time they'll get there. So let's get started by first declaring these \"forces\" I've been referring to thus far.

    "},{"location":"botmaking/jumping-physics/#gravity","title":"Gravity","text":"

    Under normal circumstances, gravity functions much like you'd expect. It constantly applies a force downwards towards the floor. By default, the force is 650 uu/s^2 but that's not a given. Luckily the current gravity value is supplied within the GameTickPacket (GameTickPacket.game_info.world_gravity_z) passed to your bot's get_output() every frame.

    "},{"location":"botmaking/jumping-physics/#sticky-force","title":"Sticky Force","text":"

    This force is responsible for the magnet-like effect pulling your wheels to walls and other surfaces. This force unlike gravity is applied in the relative down direction pushing the car's wheels towards a surface in the immediate vicinity with the force of 325 uu/s^2. This effect only persists for a short time after jumping thankfully and is no longer a consideration after 3 frames in the air after a jump. This results in a force of 8.125 ((1/120) * 3 * 325) being negated from jumps.

    "},{"location":"botmaking/jumping-physics/#jump-impulse","title":"Jump Impulse","text":"

    The instantaneous force applied in the relative up direction (towards your car's ceiling) of 292 when the jump button is first pressed. This force is the same for the first jump as well as the second jump without a flip.

    "},{"location":"botmaking/jumping-physics/#jump-hold-bonus","title":"Jump Hold Bonus","text":"

    This is the upwards velocity bonus granted for holding down the jump button on the first jump. It can grant a total additional 292 force in the relative upwards direction over 0.2s. Holding jump longer than 0.2s grants no additional bonus. A minimum of 3 ticks of jump bonus is applied to the first jump resulting in an additional 36.5 ((1/120) * 3 * 1460) force over the first 3 frames of a jump.

    "},{"location":"botmaking/jumping-physics/#throttle-acceleration","title":"Throttle Acceleration","text":"

    Believe it or not, throttle still has an effect on your car even while airborne. Forward throttle while airborne exerts a force of 66.667 uu/s^2 in your car's relative forward direction. Reverse throttle's effect is halved with a force of 33.334 uu/s^2 in the relative rear direction.

    "},{"location":"botmaking/jumping-physics/#implementing-a-jump-simulation","title":"Implementing A Jump Simulation","text":"

    The following code snippet provides an implementation of a jump simulation naively assuming the bot is perfectly flat on the ground with no initial velocity, gravity is at default settings and the bot executes a frame-perfect jump sequence.

    def naive_double_jump_simulation(time_allowed: float) -> list:\n    gravity = -650\n    jump_impulse = 292\n    time_increment = 1 / 120\n    sticky_force = -325\n    sticky_timer = time_increment * 3\n    hold_bonus_increment = (292 * 5) * time_increment\n    max_hold_time = 0.2\n    simulated_z_velocity = 0\n    simulated_height = 17.01  # default sitting height of octane\n    simulation_time = 0\n    double_jumped = False\n    jump_slices = []\n\n    while simulation_time < time_allowed:\n        if simulation_time == 0:\n            simulated_z_velocity += jump_impulse\n\n        elif simulation_time > max_hold_time + time_increment and not double_jumped:\n            simulated_z_velocity += jump_impulse\n            double_jumped = True\n\n        if simulation_time < max_hold_time:\n            simulated_z_velocity += hold_bonus_increment\n\n        if simulation_time < sticky_timer:\n            simulated_z_velocity += sticky_force * time_increment\n\n        simulated_z_velocity += gravity * time_increment\n        simulated_height += simulated_z_velocity * time_increment\n        simulation_time += time_increment\n        jump_slices.append(simulated_height)\n\n    return jump_slices\n

    Calling naive_doublejump_simulation(2.0) will return a list showing the simulated height of the car at every increment from 0 to 2 seconds into the future. A more robust solution should account for more variability in circumstances such as the car's current relative up direction as well as current velocity.

    "},{"location":"botmaking/jumping-physics/#useful-considerations-for-implementing-jumping-simulations-and-mechanics","title":"Useful Considerations For Implementing Jumping Simulations And Mechanics","text":"
    • The second jump remains viable for between 1.25 and 1.45 seconds with the potential 0.2s time extension provided by holding the first jump for the maximum bonus duration.
    • The maximum speed of a car in Rocket League is 2300. Any forces applied that would result in a magnitude exceeding 2300 will be applied as per usual but then normalized back down to the limit of 2300.

    Note: Rocket League's physics engine runs at 120hz so all calculations provided are based on that number as the base of a time step (1/120).

    "},{"location":"botmaking/machine-learning-faq/","title":"Machine learning faq","text":"

    A: There are a lot of helpful resources pinned to the ml-discussion channel of the RLBot discord.

    Q: I'm new to RLBot, how do I get started with ML?

    A: We strongly recommend you begin by writing a hard-coded bot to get the hang of RLBot, and coding for Rocket League. Once you feel confident, check out the dedicated #machine-learning channel in the RLBot discord for helpful resources!

    Q: What can I use ML for in Rocket League?

    A: Lots of things! Optimizing mechanics (wave-dashing, aerials, power-sliding, etc), analyzing replays (predicting shot percentages, car positions, etc), and even playing the game.

    Q: How could I use the replays available at calculated.gg?

    A: Tools like Training Data Extractor and carball exist to format replay data into an RLBot tick packet, and approximate player inputs between frames. These enable users to easily handle data available in replays for whatever purpose they might have.

    Q: Is it possible to get controls from replays so I can train a model to copy humans?:

    A: Training controls directly from replays has not been very successful.

    The reason for this may be that not all conditions the bot will encounter are present in replays, leading to a model being unable to handle certain conditions that were not present in the replays it was trained with.

    The most successful attempt is documented here.

    Q: Can I make a clone of Rocket League for training and then transfer it to the real game?

    A: It would be quite the project to clone Rocket League, but there is no reason that would not work with a little elbow grease!

    The user @Roboserg#9216 has been working on a Rocket League clone for some time, and has made very promising progress. His work is open source, and can be found here.

    Q: Can I use Supervised Learning to train a bot that mimics other bots?

    A: Yes you can! The ML bots Levi and Tensorbot were trained this way.

    Q: Can I use Reinforcement Learning to make a bot?

    A: This is the holy grail for many ML enthusiasts in the RLBot community.

    With the recent release of the Python library and Bakkesmod plugin RLGym, Reinforcement Learning can now be used to train models directly in the game. Some promising results have already been achieved, like Rhobot and Element. These models take quite a lot of compute power and time to train, but they are achievable with consumer-grade hardware. The largest RLGym project is currently a distributed learning bot Necto/Nexto.

    Reinforcement Learning can also be used to train specific mechanics, like Eagle and ElementAerial

    Q: Can I use this or that method to speed up Reinforcement Learning?

    A: You can just try it out, if it works for other problems, then it might also work for Rocket League. Don't hesitate to ask in the discord if you want a second opinion.

    "},{"location":"botmaking/manipulating-game-state/","title":"Manipulating game state","text":""},{"location":"botmaking/manipulating-game-state/#overview","title":"Overview","text":"

    We have a feature that lets you set exact positions, velocities, etc. for the ball and cars. You may be familiar with BakkesMod, this is very similar. It won't be enabled during tournaments, but it's very useful when building and debugging your bot.

    "},{"location":"botmaking/manipulating-game-state/#possibilities","title":"Possibilities","text":"
    • Set up a specific scenario for your bot to try over and over. Better than custom training, because:
    • You have control over car orientation, velocity, angular velocity, and boost amount
    • You can do it in the middle of an exhibition match with opponents
    • You can control it all from inside your bot code
    • Build training sets for machine learning
    • Record snapshots during a game and \"rewind\" if you encounter a natural situation you want to iterate on
    • Hover your car in midair while you work on your orientation code
    • Build wacky physics rules to change the game, e.g. making the ball bounce off invisible walls, accelerate in a certain direction, etc
    "},{"location":"botmaking/manipulating-game-state/#language-specific-documentation","title":"Language-specific documentation","text":"
    • Python
    • Java
    • C#
    "},{"location":"botmaking/matchcomms/","title":"Matchcomms","text":""},{"location":"botmaking/matchcomms/#matchcomms-allows-communication-between-participants-in-a-match","title":"Matchcomms allows communication between participants in a match.","text":"

    Use cases:

    • Telling your teammate where you intend to go
    • Setting parameters on bots in a training exercise
    • Bootstrapping a more efficient form of communication

    Currently only broadcasting to all participants is supported.

    "},{"location":"botmaking/matchcomms/#architecture","title":"Architecture","text":""},{"location":"botmaking/matchcomms/#examples","title":"Examples","text":"

    Python example for reading and replying to messages in a bot.

    Example training exercise which sets parameters on the bot

    "},{"location":"botmaking/matchcomms/#tmcp","title":"TMCP","text":"

    TMCP stands for the Team Match Communication Protocol. It is an attempt at standardizing inter-bot communication via the match comms system.

    See this wiki page for implementation details.

    "},{"location":"botmaking/matchcomms/#supported-languages","title":"Supported Languages","text":"
    • Python has strong support, as described above
    • Java bots will receive args like --matchcomms-url ws://localhost:53970 when starting up. No library support yet for creating / managing the connection.
    • C# bots will receive args like --matchcomms-url ws://localhost:53970 when starting up. No library support yet for creating / managing the connection.
    "},{"location":"botmaking/quickchat/","title":"Quickchat","text":""},{"location":"botmaking/quickchat/#overview","title":"Overview","text":"

    You can make your bot send quickchat! We support sending all standard quickchats, and also some custom ones! You can find the full list here.

    It's now possible to read quick chat too, assuming the framework for your chosen language has added support. You'll be able to read the chat log regardless of what language send the message. Messages sent on the team-only channel will be hidden from opponents appropriately.

    Using quick chat is a little different in each language, see the specific links below.

    "},{"location":"botmaking/quickchat/#language-specific-documentation","title":"Language-specific documentation","text":"
    • Python
    • Java
    • C#

    Other languages support quickchat, we just don't have wikis yet.

    "},{"location":"botmaking/rendering/","title":"Rendering","text":"

    An incredibly useful new addition to RLBot v4 is the rendering feature. It allows you to draw objects on screen, which can make debugging and testing your bot so much easier. For example, you could draw the predicted ball path, or draw where the bot wants to go.

    Rendering in other languages: Java, C#

    "},{"location":"botmaking/rendering/#enablingdisabling-of-rendering","title":"Enabling/disabling of rendering","text":"

    When installing the RLBotGUI, rendering will be disabled by default. You can turn it on by clicking 'Extra' and ticking 'Enable Rendering' in the GUI. However, rendering can also be enabled or disabled any time using the page up and page down keys, respectively. So if your rendering isn't appearing, make sure to press page up before panicking.

    "},{"location":"botmaking/rendering/#the-basics","title":"The basics","text":"

    The renderer object is built into the BaseAgent class, so you don't need to import anything other than the BaseAgent. Each time you want to render something, you start with self.renderer.begin_rendering() and end with self.renderer.end_rendering(). The rendering code goes in between the begin_rendering() and end_rendering(). Let's take a look at an example:

    class RenderingTutorial(BaseAgent):\n    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:\n        controller = SimpleControllerState()\n\n        self.renderer.begin_rendering()\n        self.renderer.draw_rect_2d(20, 20, 200, 200, True, self.renderer.black())\n        self.renderer.end_rendering()\n\n        return controller\n

    We can see here that every get_output call, the on-screen drawings get updated. In this example, the draw_rect_2d method is used. Let's go over all the methods you can use:

    (Note: The argument names aren't exactly what appear in the framework itself, but the argument positions are the same)

    "},{"location":"botmaking/rendering/#rendering-a-large-amount","title":"Rendering a large amount","text":"

    There are a few limits you can hit when rendering:

    • MessageLargerThanMax
    • Not sending message to Rocket League because that would bring the bytes sent since last receive to...

    You can bypass the MessageLargerThanMax one by using multiple render groups. Example:

    self.renderer.begin_rendering('my_big_render')\nfor i in range(0, 200):\n    self.renderer.draw_rect_3d(...)\nself.renderer.end_rendering()\n\nself.renderer.begin_rendering('my_big_render_part_2')\nfor i in range(200, 400):\n    self.renderer.draw_rect_3d(...)\nself.renderer.end_rendering()\n

    If you hit the other limit, you're out of luck.

    "},{"location":"botmaking/rendering/#renderercreate_color-and-other-colors","title":"renderer.create_color and other colors","text":"
    create_color(a, r, g, b)\n
    • a, r, g, b - Alpha, red, green, blue. From 0 to 255.

    This doesn't draw anything on screen, but it is used for creating colors that you can use for the other methods that draw on screen. The renderer also has a list of color methods that gives you the most common colors:

    renderer.black()\nrenderer.white()\nrenderer.gray()\nrenderer.blue()\nrenderer.red()\nrenderer.green()\nrenderer.lime()\nrenderer.yellow()\nrenderer.orange()\nrenderer.cyan()\nrenderer.pink()\nrenderer.purple()\nrenderer.teal()\n

    Lastly, there's the team_color method. Using this your bot renders with different colors depending on which team it is on.

    team_color(team=None, alt_color=False)\n
    • team - (Optional, None by default) Index of a team (0 for blue, 1 for orange) or None. If set to None, it will use calling bot's team.
    • alt_color - (Optional, False by default) Wether or not to return the alternate team color instead. If set to False, this method returns blue for blue team and orange for orange team. If set to True, this method returns cyan for blue team and red for orange team.
    "},{"location":"botmaking/rendering/#rendererdraw_rect_2d","title":"renderer.draw_rect_2d","text":"

    This draws a rectangle on screen. Example : draw_rect_2d(20, 20, 200, 200, True, self.renderer.black())

    draw_rect_2d(x, y, width, height, fill, color)\n
    • x, y - The top left x and y screen coordinates for the rectangle. (0, 0) is the top left of the screen.
    • width, height - The width and height of the rectangle.
    • fill - If True, the entire rectangle is filled with color, else it is just an outline of color.
    • color - The color of the rectangle. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_2d","title":"renderer.draw_line_2d","text":"

    NOTE: Currently not supported.

    Draws a 2D line flat on the screen.

    draw_line_2d(start_x, start_y, end_x, end_y)\n
    • start_x, start_y - Where the line starts. (0, 0) is the top left of the screen.
    • end_x, end_y - Where the line ends.
    "},{"location":"botmaking/rendering/#rendererdraw_string_2d","title":"renderer.draw_string_2d","text":"

    Draws 2D text flat on the screen. Example : draw_string_2d(20, 20, 3, 3, ball_text, self.renderer.black()) example

    draw_string_2d(x, y, scale_x, scale_y, text, color)\n
    • x, y - The top left x and y screen coordinates for the string. (0, 0) is the top left of the screen.
    • scale_x, scale_y - The horizontal and vertical scale of the text.
    • text - The text to render.
    • color - The color of the string. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_rect_3d","title":"renderer.draw_rect_3d","text":"

    Draws a 2D rectangle in game's 3D space. Size does not change with distance.

    draw_rect_3d(location, width, height, fill, color)\n
    • location - The 3D game location where the rectangle should be drawn. Must be a Python list or a tuple (cannot be a ctypes or flatbuffers type).
    • width, height - The width and height of the rectangle.
    • fill - If True, the entire rectangle is filled with color, else it is just an outline of color.
    • color - The color of the rectangle. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_string_3d","title":"renderer.draw_string_3d","text":"

    Draws 2D text in game's 3D space. Size does not change with distance.

    draw_string_3d(location, scale_x, scale_y, text, color)\n
    • location - The 3D game location where the text should be drawn. Must be a Python list or a tuple (cannot be a ctypes or flatbuffers type).
    • scale_x, scale_y - The horizontal and vertical scale of the text.
    • text - The text to render.
    • color - The color of the text. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_3d","title":"renderer.draw_line_3d","text":"

    Draws a 2D line in game's 3D space. Size does not change with distance.

    draw_line_3d(start, end, color)\n
    • start, end - The starting and ending 3D game locations of the line. Must be Python lists or tuples (cannot be ctypes or flatbuffers types).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_2d_3d","title":"renderer.draw_line_2d_3d","text":"

    NOTE: Currently not supported.

    Draws a 2D line which starts at screen coordinates and ends at the game's 3D coordinate.

    draw_line_2d_3d(start_2d_x, start_2d_y, end_3d, color)\n
    • start_2d_x, start_2d_y - Where the line starts (on the screen).
    • end_3d - Where the line ends (in 3D space). Must be a Python list or tuple (cannot be a ctypes or flatbuffers type).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_polyline_2d","title":"renderer.draw_polyline_2d","text":"

    NOTE: Currently not supported.

    Draws multiple connected 2D lines flat on the screen. Useful for rendering paths or pictures.

    draw_polyline_2d(locations, color)\n
    • locations - A list of 2D points. A line will be drawn from first point to the second point, and from second point to the third point, ect. (0, 0) is the top left of the screen.
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_polyline_3d","title":"renderer.draw_polyline_3d","text":"

    Draws multiple connected lines in the game's 3D space. Useful for rendering paths. Size does not change with distance.

    draw_polyline_3d(locations, color)\n
    • locations - A list of 3D locations. A line will be drawn from first location to the second location, and from second location to the third location, ect. Each location must be a Python list or tuple (cannot be a ctypes or flatbuffers type).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/scripts/","title":"Scripts","text":"

    Sometimes it can be useful to have access to game values, debug rendering or state setting while not being a bot playing within the match. The framework has an easy solution for that - scripts.

    Scripts are very similiar to normal bots. They need a config file and a python executable. The config file can be loaded by RLBotGUI like a normal bot - to enable it, just click the checkbox next to its name. The script will be automatically started and terminated by the framework.

    Example config:

    [Locations]\nscript_file = ./my_script.py\nname = My Script\n\n[Details]\ndescription = Example script\nlanguage = python\n

    Example my_script.py:

    import time\n\nfrom rlbot.agents.base_script import BaseScript\nfrom rlbot.utils.game_state_util import GameState\n\n\n# Extending the BaseScript class is purely optional. It's just convenient / abstracts you away from\n# some strange classes like GameInterface\nclass MyScript(BaseScript):\n    def __init__(self):\n        super().__init__(\"My Script\")\n\n    def run(self):\n        # state setting\n        self.set_game_state(GameState(console_commands=[\"Stat FPS\"]))\n\n        while True:\n            time.sleep(0.5)\n\n            # updating packet\n            packet = self.get_game_tick_packet()\n\n            # rendering\n            color = self.renderer.white()\n            text = f\"seconds_elapsed : {packet.game_info.seconds_elapsed}\"\n            self.game_interface.renderer.begin_rendering()\n            self.game_interface.renderer.draw_string_2d(20, 200, 2, 2, text, color)\n            self.game_interface.renderer.end_rendering()\n\n\n# You can use this __name__ == '__main__' thing to ensure that the script doesn't start accidentally if you\n# merely reference its module from somewhere\nif __name__ == \"__main__\":\n    script = MyScript()\n    script.run()\n

    This script will render some text on the screen every 0.5 seconds.

    If you want your loop to be run every tick, you might want to use a blocking call instead of time.sleep like this:

    while True:\n   packet = self.wait_game_tick_packet()\n   ...\n

    For all available methods in the BaseScript class and their descriptions, see its implementation here.

    Another fully functional script example

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/","title":"Shooting the ball towards or away from a target","text":""},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#this-tutorial-is-not-language-specific","title":"This tutorial is NOT language-specific!","text":"

    This tutorial is based on the systems used by VirxERLU which is a fork of GoslingUtils.

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#toc","title":"TOC","text":"
    • This tutorial is NOT language-specific!
    • TOC
    • Targets and anti-targets
    • Direction of approach
    • Ball location offset
    • Aligning with the direction of approach
    • Driving
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#targets-and-anti-targets","title":"Targets and anti-targets","text":"

    Firstly, a target is something that we want to hit the ball towards, and an anti-target is something that we want to hit the ball away from.

    • Targets: This will be a list of two vectors. The first vector will be the left-most target, and the second will be the right-most target.
    • Anti-targets: This is the same as targets, but you swap the left-most and right-most targets before giving them to the algorithm, and all the following code stays the same! This causes the algorithm to shoot the ball anywhere but between the two targets.

    We're using two points instead of just one, central point that represents the target because just one point is unrealistic and restricts our options. Two points, however, gives us a range to work with and some room for error.

    Useful game values

    For example, our left-most target vector could be [800, 5213, 321.3875] (orange's left goal post) and our right-most target vector could be [-800, 5213, 321.3875] (orange's right goal post). These values have been adjusted to account for the ball's radius (which is 92.75).

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#direction-of-approach","title":"Direction of approach","text":"

    Now we need to find the direction that we need to hit the ball in. It wouldn't be fun if we ended up hitting the ball away from our target!

    In order to do this, we need the following information:

    • Left-most target
    • Right-most target
    • Ball location
    • Car location

    Let's get started!

    Vector car_to_ball = ball_location - car_location\nVector car_to_ball_direction = normalize(car_to_ball)\n\nVector ball_to_left_target_direction = normalize(left_target_location - ball_location)\nVector ball_to_right_target_direction = normalize(right_target_location - ball_location)\n

    These are a bunch of directions, and they're fairly well described just by the variable names. You will have to implement your own normalize function, but here's the math behind it if you didn't know. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!

    Next, we need some way to change car_to_ball_direction so that it's between ball_to_left_target_direction and ball_to_right_target_direction. That's what the following function clamp2D does.

    Vector clamp2D(Vector direction, Vector start, Vector end) {\n    bool is_right = dotProduct(direction, crossProduct(end, [0, 0, -1])) < 0\n    bool is_left = dotProduct(direction, crossProduct(start, [0, 0, -1])) > 0\n\n    if ((dotProduct(end, crossProduct(start, [0, 0, -1])) > 0) ? (is_right && is_left) : (is_right || is_left))\n        return direction\n\n    if (dotProduct(start, direction) < dotProduct(end, direction))\n        return end\n\n    return start\n}\n

    You will also have to implement your own dotProduct and crossProduct functions. See here to learn how to find the dot product of two vectors and see here to learn how to find the cross product of two vectors. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!

    • Similar to integer clamping, clamp2D forces a direction between start and end, such that start \\< direction \\< end in terms of clockwise rotation.
    • Note that this is only in the x-axis and y-axis - clamping the z-axis isn't necessary for this problem.
    • For the math nerds: Why does this work? This function relies on Rocket League's inverted X-axis (positive X is left and negative X is right). See this page for a top-down view of the Rocket League field and different coordinates pertaining to the field.

    Now we can use the clamp2D function.

    Vector direction_of_approach = clamp2D(car_to_ball_direction, ball_to_left_target_direction, ball_to_right_target_direction)\n

    This is the direction that our bot should approach the ball at.

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#ball-location-offset","title":"Ball location offset","text":"

    Next, we're going to take the ball's radius as well as our direction of approach into account in order to offset our final target from the ball's location.

    The basis behind this is that we will go in the opposite direction of our direction of approach, and give the direction a magnitude of 92.75 (which is the ball's radius).

    Vector offset_ball_location = ball_location - (direction_of_approach * 92.75)\n
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#aligning-with-the-direction-of-approach","title":"Aligning with the direction of approach","text":"

    This is where the math gets into approximations. What we need to do is cause the car to slowly circle around offset_ball_location until our direction to the ball matches or is close to direction_of_approach while also getting closer and closer to the target.

    int side_of_approach_direction = sign(dotProduct(crossProduct(direction_of_approach, [0, 0, 1]), ball_location - car_location))\nVector car_to_ball_perpendicular = normalize(crossProduct(car_to_ball, [0, 0, side_of_approach_direction]))\nVector adjustment = abs(angle(flatten(car_to_ball), flatten(direction_of_approach))) * 2560\nVector final_target = offset_ball_location + (car_to_ball_perpendicular * adjustment)\n
    • You will need to implement your own sign. This returns -1 if the value is negative, 0 if the value is 0, and 1 if the value is positive.
    • Most languages have their own abs (absolute value) function built-in. See here to learn what absolute value is.
    • You will also need to implement your own flatten and angle functions. Flatten makes the z value of a vector equal to 0. See here to learn how to find the angle between two vectors. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#driving","title":"Driving","text":"

    Once you have final_target, all you have to do is face it and drive towards it. It will automatically adjust itself as your bot starts moving.

    If you want to get to the target at a specific time - for example, if you're using the ball prediction - then you need the required speed in order to get to the target at that exact time. This is fairly simple, as we just need to find the distance that we need to travel and divide by the remaining time.

    double distance_remaining = magnitude(final_target - car_location) // an ESTIMATION of how far we need to drive - this might be spot-on or fairly far off\ndouble time_remaining = intercept_time - current_time\n\ndouble speed_required = distance_remaining / time_remaining\n

    This also has another benefit: you can easily know whether or not it's possible to reach the target in a given time. If the required speed is greater than 1410 (which is the max speed of a car without boost) or 2300 (if the car does have boost) then it's impossible to reach the target in the given time.

    "},{"location":"botmaking/team-match-communication-protocol/","title":"TMCP","text":""},{"location":"botmaking/team-match-communication-protocol/#about","title":"About","text":"

    TMCP stands for the Team Match Communication Protocol. It is an attempt at standardizing inter-bot communication.

    Currently, the match communication system, or match comms, is only supported by Python bots. See Matchcomms for more information on how to use it.

    Match comms do not allow for team-only messages. Until this is implemented, TMCP operates on an honor system: a bot should not look at packets from bots on another team.

    "},{"location":"botmaking/team-match-communication-protocol/#sending-packets","title":"Sending packets","text":"

    Bots should avoid spamming packets. They should aim for a maximum of 10 packets per second.

    Only send a packet when something has changed. If you want to refine a time estimate sent in a previous message, only do so if the time difference is > 0.1 seconds.

    "},{"location":"botmaking/team-match-communication-protocol/#receiving-packets","title":"Receiving packets","text":"

    Packets will only be received when something has changed. If you haven't received a packet from another bot, assume that nothing has changed.

    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-10","title":"TMCP 1.0","text":"

    This is what a packet following TMCP looks like:

    {\n  \"tmcp_version\": [1, 0],\n  \"team\": int,\n  \"index\": int,\n  \"action\": {\n    \"type\": string,\n    ...\n  }\n}\n
    • tmcp_version

    • Major: Breaking revision number

    • Minor: Non-breaking revision number

    • team - The team of the bot that sent the packet. 0 for blue and 1 for orange. This will be removed once match comms allow for team-only communication.

    • index - The index of the bot that sent the packet. If you are using the hivemind, make this the index of the bot which is carrying out the action.

    • action - The current action that the bot is taking. This is an object. The types can be seen below.

    "},{"location":"botmaking/team-match-communication-protocol/#ball","title":"\"BALL\"","text":"

    The bot is going for the ball.

    {\n  \"type\": \"BALL\",\n  \"time\": float,\n  \"direction\": [float, float, float] \n}\n
    • time - Game time that your bot will arrive at the ball. Set to -1 if this is unknown.
    • direction - Anticipated normalized direction of ball travel AFTER contact is made. [0, 0, 0] for unknown.
    "},{"location":"botmaking/team-match-communication-protocol/#boost","title":"\"BOOST\"","text":"

    The bot is going for boost.

    {\n  \"type\": \"BOOST\",\n  \"target\": int\n}\n
    • target - Index of the boost pad the bot is going to collect.
    "},{"location":"botmaking/team-match-communication-protocol/#demo","title":"\"DEMO\"","text":"

    The bot is going to demolish another car.

    {\n  \"type\": \"DEMO\",\n  \"time\": float,\n  \"target\": int\n}\n
    • time - Game time that the bot will demo the other bot. -1 for unknown.
    • target - Index of the bot that will be demoed.
    "},{"location":"botmaking/team-match-communication-protocol/#ready","title":"\"READY\"","text":"

    The bot is waiting for a chance to go for the ball. Some examples are positioning (retreating/shadowing) and recovering.

    {\n  \"type\": \"READY\",\n  \"time\": float\n}\n
    • time - The game time when the bot could arrive at the ball (if it was to go for it). -1 for unknown.
    "},{"location":"botmaking/team-match-communication-protocol/#defend","title":"\"DEFEND\"","text":"

    The bot is in a position to defend the goal and is not planning to move up. Only use DEFEND if your bot is in place to defend, not if still en-route. If the bot decides to leave the net, signal this using either \"BALL\" (if going for a touch) or \"READY\" (if moving upfield).

    A bot should use \"DEFEND\" to let its teammates know it is safe to move up a bit without worrying about an open net.

    {\n  \"type\": \"DEFEND\"\n}\n
    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-implementations","title":"TMCP Implementations","text":""},{"location":"botmaking/team-match-communication-protocol/#virxerlu","title":"VirxERLU","text":"

    If you use VirxERLU, your bot automatically sends out TMCP packets. To process incoming ones, add this to your bot in main.py:

    def handle_tmcp_packet(self, packet):\n    super().handle_tmcp_packet(packet)\n    # process the packet here\n

    However, you will have to implement your own 'minimum time to ball' function. This is the default:

    def get_minimum_game_time_to_ball(self):\n    return -1\n

    It should return -1 if you can't find a shot and the game time of the shot if you could. It should be noted that all shots (except for short_shot) have a property called intercept_time which is the game time that they will intercept the ball at.

    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-handler","title":"TMCP Handler","text":"

    Will made a TMCP python package with helper classes that handle everything protocol-related.

    To install, just do

    pip install tmcp\n

    Then you can use it like this:

    from tmcp import TMCPHandler, TMCPMessage, ActionType\n\nclass MyBot(BaseAgent):\n    def initialize_agent(self):\n        self.tmcp_handler = TMCPHandler(self)\n\n    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:\n        # Receive and parse all new matchcomms messages into TMCPMessage objects.\n        new_messages: List[TMCPMessage] = self.tmcp_handler.recv()\n        # Handle TMCPMessages.\n        for message in new_messages:\n            if message.action_type == ActionType.BALL:\n                print(message.time)\n\n        ...\n\n        # You can send messages like this.\n        self.tmcp_handler.send_boost_action(pad_index)\n\n        # Or you can create them and send them more directly:\n        my_message = TMCPMessage.ball_action(self.team, self.index, estimated_time_of_arrival)\n        self.tmcp_handler.send(my_message)\n
    "},{"location":"botmaking/team-match-communication-protocol/#tgdsmells-handler","title":"TGDSMELLS Handler","text":"

    The TGDSMELLS Handler is very similar in usage to Will's TMCP Handler.

    Can be installed with

    pip install tgdsmells\n
    "},{"location":"botmaking/team-match-communication-protocol/#under-the-hood","title":"Under the hood","text":"

    The following example shows how you could send and receive match comms without a handler. This is shown to give you a better idea of what's going on under the hood. We do still recommend that you use an existing handler instead because it will be up to date and do a lot of error checking for you.

    from queue import Empty\n\nclass MyBot(BaseAgent):\n    def initialize_agent(self):\n        self.ally_actions = {}\n\n    def receive_coms(self):\n        # Process up to 50 messages per tick.\n        for _ in range(50):\n            try:\n                # Grab a message from the queue.\n                msg = self.matchcomms.incoming_broadcast.get_nowait()\n            except Empty:\n                break\n\n            # This message either isn't following the standard protocol\n            # or is intended for the other team.\n            # DO NOT spy on the other team for information!\n            if \"tmcp_version\" not in msg or msg[\"team\"] != self.team:\n                continue\n\n            # Will's handler checks to make sure the message is valid.\n            # Here we are keeping it as simple as possible.\n\n            # If we made it here we know it's information relevant to our team.\n            # Let's save it in a dictionary for reference later.\n            self.ally_actions[msg[\"index\"]] = msg\n\n    def send_coms(self):\n        # Let's assume that our bot is attacking the ball and aiming for prediction slice 100.\n        outgoing_msg = {\n            \"tmcp_version\": [1, 0],\n            \"team\": self.team,\n            \"index\": self.index,\n            \"action\": {\n                \"type\": \"BALL\",\n                # You'll likely have the ball predictions cached locally.\n                # This implementation is for demonstration purposes only.\n                \"time\": self.get_ball_prediction_struct().slices[100].game_seconds,\n                \"direction\": [0, 0, 0]\n            },\n        }\n        self.matchcomms.outgoing_broadcast.put_nowait(outgoing_msg)\n\n    def get_output(self, packet: GameTickPacket):\n        # Get the latest information from matchcomms.\n        self.receive_coms()\n\n        # Your bot code goes here:\n        ...\n\n        # Ideally you only send out communications when your plans change.\n        # Sending 120 messages a second is just overkill and will eat into the processing time of your allies.\n        # Please take proper precautions to prevent excessive spam.\n        if new_plan != old_plan:\n            self.send_coms()\n\n        return self.controls\n
    "},{"location":"botmaking/tick-rate/","title":"Tick rate","text":"

    Bots have a function like get_output(packet) or something similar, depending on language. This gets called some number of times per second, I will refer to this as the tick rate.

    There are several factors which influence tick rate:

    1. The frame rate of Rocket League. If Rocket League is running at 60 FPS, the tick rate will get capped at 60, regardless of any other settings. Note that enabled VSync also limits FPS.
    2. The desired tick rate that you've configured for your bot. Most languages allow you to add an additional cap.
    3. The tick rate can never be higher than 120, since this is the rate at which Rocket League simulates its physics.

    In other words, the tick rate is min(rocketLeagueFPS, desiredTickRate). You can see the tick rate you're getting during a game by hitting the 'home' key and looking for a line like ticks: 120.0 tps

    There used to be another factor, the PacketSendRate configuration. There's a file at C:\\Users\\yourname\\Documents\\My Games\\Rocket League\\TAGame\\Config\\TARLBot.ini where you could write down a PacketSendRate, but RLBot now ignores it and sets 240 no matter what, so it's a non-issue.

    "},{"location":"botmaking/tick-rate/#specifying-desired-tick-rate","title":"Specifying desired tick rate","text":""},{"location":"botmaking/tick-rate/#python","title":"Python","text":"

    In python, you can update your bot cfg file as seen in this example

    Python will assume your desired tick rate is 60 unless you override it. This is because TARLBot.ini is 60 by default, so the vast majority of bot makers have been developing and testing with 60.

    "},{"location":"botmaking/tick-rate/#java","title":"Java","text":"

    In Java, you can configure your bot manager as seen in this example

    Java will assume your desired tick rate is 60 unless you override it. This is for the same reason as Python, and also because Java was hard-coded to use 60 for a long time.

    "},{"location":"botmaking/tick-rate/#net-c","title":".NET / C#","text":"

    In .NET, you can configure your bot manager as seen in this example

    Here, 0 means that you wish to have your desired tick rate be unlimited. You may also pass numbers like 60 or 120.

    "},{"location":"botmaking/tick-rate/#tips","title":"Tips","text":"
    • You should probably specify a tick rate that divides into 120. Tournaments generally run at 120Hz or 60Hz, and if you specify something weird like 100Hz, your bot will get called at varying intervals to achieve that average.
    • In most languages, your choice of tick rate will not affect the 'freshness' of packets delivered. They should all be very fresh, about 1ms old, when they are delivered to you.
    • If your bot is slow to compute a frame, you will fall behind and potentially miss a frame, since bots generally loop on a single thread. If you desire consistency, you may wish to configure a desiredTickRate that always gives enough time for your bot logic.
    • To consistently give bots the same amount of execution time for every tick, rocket leagues fps should be locked to exactly the tick rate that you want the bots to run at. This is especially important if there are many bots running, for example in a tournament.
    • It is possible to lock the FPS when RLBot is active, and unlock it when you're just playing normally. See the RLBot Specific Game Settings page for instructions on how to do this.
    "},{"location":"botmaking/useful-game-values/","title":"Useful game values","text":"

    If you are making a bot, some of these values are given in FieldInfo. You can find more information on that here.

    Rocket League is made in Unreal Engine, which means any dimensions will be in unreal units (uu).

    "},{"location":"botmaking/useful-game-values/#basic-dimensions","title":"Basic Dimensions","text":"

    WARNING: Note that the X-axis is left and it is not the normal Cartesian layout. Also, yaw is zero at the positive x-axis and increases clockwise. Trig functions work out as usual because the two reversed conventions cancel each other.

    Rotations are represented as YZX-ordered Euler angles.

    Note: For scratch divide the values by 32.

    Rocket League uses a coordinate system (X, Y, Z), where Z is upwards. Note also that negative Y is towards Blue's goal (team 0).

    • Floor: 0
    • Center field: (0, 0)
    • Side wall: x=\u00b14096
    • Side wall length: 7936
    • Back wall: y=\u00b15120
    • Back wall length: 5888
    • Ceiling: z=2044
    • Goal height: z=642.775
    • Goal center-to-post: 892.755
    • Goal depth: 880
    • Corner wall length: 1629.174
    • The corner planes intersect the axes at \u00b18064 at a 45 degrees angle

    For wall lengths, the curvature at the intersections is ignored.

    "},{"location":"botmaking/useful-game-values/#boost-pads","title":"Boost Pads","text":"

    Small boost pads:

    • Hitbox is a cylinder, height of 165uu, radius of 144uu
    • 28 in total.
    • Gives 12 boost.
    • Takes 4 seconds to refresh.

    Big boost pads:

    • Hitbox is a cylinder, height of 168uu, radius of 208uu
    • 6 in total.
    • Gives 100 boost.
    • Takes 10 seconds to refresh.
    • The pads with a z-component of 73.0 are the big pads. Mirror these coordinates to get all 6:
    • Midfield: (3584, 0)
    • Corner: (3072, 4096)

    A car picks up a boost pad if the car's center of mass (not hitbox) enters the pad's hitbox. This interaction is different when cars are standing still (see the Rocket Science video on boost pad hitboxes)

    The coordinates of the 34 boost pads (in the order that RLBot uses):

    [    0.0, -4240.0, 70.0] (0)\n[-1792.0, -4184.0, 70.0] (1)\n[ 1792.0, -4184.0, 70.0] (2)\n[-3072.0, -4096.0, 73.0] (3)\n[ 3072.0, -4096.0, 73.0] (4)\n[- 940.0, -3308.0, 70.0] (5)\n[  940.0, -3308.0, 70.0] (6)\n[    0.0, -2816.0, 70.0] (7)\n[-3584.0, -2484.0, 70.0] (8)\n[ 3584.0, -2484.0, 70.0] (9)\n[-1788.0, -2300.0, 70.0] (10)\n[ 1788.0, -2300.0, 70.0] (11)\n[-2048.0, -1036.0, 70.0] (12)\n[    0.0, -1024.0, 70.0] (13)\n[ 2048.0, -1036.0, 70.0] (14)\n[-3584.0,     0.0, 73.0] (15)\n[-1024.0,     0.0, 70.0] (16)\n[ 1024.0,     0.0, 70.0] (17)\n[ 3584.0,     0.0, 73.0] (18)\n[-2048.0,  1036.0, 70.0] (19)\n[    0.0,  1024.0, 70.0] (20)\n[ 2048.0,  1036.0, 70.0] (21)\n[-1788.0,  2300.0, 70.0] (22)\n[ 1788.0,  2300.0, 70.0] (23)\n[-3584.0,  2484.0, 70.0] (24)\n[ 3584.0,  2484.0, 70.0] (25)\n[    0.0,  2816.0, 70.0] (26)\n[- 940.0,  3308.0, 70.0] (27)\n[  940.0,  3308.0, 70.0] (28)\n[-3072.0,  4096.0, 73.0] (29)\n[ 3072.0,  4096.0, 73.0] (30)\n[-1792.0,  4184.0, 70.0] (31)\n[ 1792.0,  4184.0, 70.0] (32)\n[    0.0,  4240.0, 70.0] (33)\n

    NOTE: Some boost pad locations vary from map to map. It is recommended to use the FieldInfo, if you want to have the correct locations for any map.

    "},{"location":"botmaking/useful-game-values/#spawn-locations","title":"Spawn Locations","text":"Kickoff Blue Orange Right corner loc: (-2048, -2560), yaw: 0.25 pi loc: (2048, 2560), yaw: -0.75 pi Left corner loc: (2048, -2560), yaw: 0.75 pi loc: (-2048, 2560), yaw: -0.25 pi Back right loc: (-256.0, -3840), yaw: 0.5 pi loc: (256.0, 3840), yaw: -0.5 pi Back left loc: (256.0, -3840), yaw: 0.5 pi loc: (-256.0, 3840), yaw: -0.5 pi Far back center loc: (0.0, -4608), yaw: 0.5 pi loc: (0.0, 4608), yaw: -0.5 pi Demolished Blue Orange Right inside loc: (-2304, -4608), yaw: 0.5 pi loc: (2304, 4608), yaw: -0.5 pi Right outside loc: (-2688, -4608), yaw: 0.5 pi loc: (2688, 4608), yaw: -0.5 pi Left inside loc: (2304, -4608), yaw: 0.5 pi loc: (-2304, 4608), yaw: -0.5 pi Left outside loc: (2688, -4608), yaw: 0.5 pi loc: (-2688, 4608), yaw: -0.5 pi"},{"location":"botmaking/useful-game-values/#elevation-of-objects-at-rest","title":"Elevation of Objects at Rest:","text":"
    • Ball: 93.15
    • Hybrid: 17.00
    • Octane: 17.01
    • Dominus: 17.05
    • Breakout: 18.33
    • Batmobile/Plank: 18.65

    (these may vary slightly)

    More information on car bodies in this spreadsheet by HalfwayDead.

    "},{"location":"botmaking/useful-game-values/#physics","title":"Physics","text":"

    Conversion: 1 uu = 1 cm (e.g. 2778 uu/s = 100 km/h)

    • Gravity: 650 uu/s^2
    • \"Low\" mutator: 325 uu/s^2
    • \"High\" mutator: 1137.5 uu/s^2
    • \"Super High\" mutator: 3250 uu/s^2
    "},{"location":"botmaking/useful-game-values/#ball","title":"Ball","text":"
    • Radius: 91.25 uu
    • Max speed: 6000 uu/s
    • \"Slow\" mutator: 1500 uu/s
    • \"Fast\" mutator: 9000 uu/s
    • \"Super Fast\" mutator: 15000 uu/s
    • Mass: 30.0 (unit is arbitrary)
    • Coefficient of restitution: 60% (it loses 40% of the component of its velocity that's toward the surface)
    • Maximum ball angular velocity: 6.0 radians/s
    "},{"location":"botmaking/useful-game-values/#car","title":"Car","text":"
    • Max car speed (boosting): 2300 uu/s
    • Supersonic speed threshold: 2200 uu/s
    • Max driving speed (forward and backward) with no boost: 1410 uu/s
    • Car mass: 180.0 (unit is arbitrary)
    • Boost consumption rate: 33.3/s
    • Boost acceleration:
    • on the ground: 991.666 uu/s^2
    • in the air: 1058.333 uu/s^2
    • Acceleration in the ground:
    • due to throttle: depends on velocity - https://samuelpmish.github.io/notes/RocketLeague/ground_control/#throttle
    • due to braking (any amount): -3500.0 uu/s^2
    • due to slowing during zero-throttle coasting: -525.0 uu/s^2
    • Acceleration in the air due to throttle: ~66.667 uu/s^2 (yes, throttling accelerates the car in the air)
    • Jumping
    • Double jump
    • An instantaneous velocity increase of ~291.667 uu/s in the direction of your roof.
    • Minimum and maximum rotation (in radians):
    • Pitch: [-pi/2, pi/2]
    • Yaw: [-pi, pi]
    • Roll: [-pi, pi]
    • Maximum car angular acceleration:
    • Yaw: 9.11 radians/s^2
    • Pitch: 12.46 radians/s^2
    • Roll: 38.34 radians/s^2
    • Maximum car angular velocity: 5.5 radians/s
    • Turning
    • Turning in Rocket League is very complex and not a lot is known. Hopefully, the numbers below can help you out a bit!
    • Turn radius: https://samuelpmish.github.io/notes/RocketLeague/ground_control/#turning. Python implementation:
    def turn_radius(v):\n    if v == 0:\n        return 0\n    return 1.0 / curvature(v)\n\n# v is the magnitude of the velocity in the car's forward direction\ndef curvature(v):\n    if 0.0 <= v < 500.0:\n        return 0.006900 - 5.84e-6 * v\n    if 500.0 <= v < 1000.0:\n        return 0.005610 - 3.26e-6 * v\n    if 1000.0 <= v < 1500.0:\n        return 0.004300 - 1.95e-6 * v\n    if 1500.0 <= v < 1750.0:\n        return 0.003025 - 1.1e-6 * v\n    if 1750.0 <= v < 2500.0:\n        return 0.001800 - 4e-7 * v\n\n    return 0.0\n
    • No matter if you're accelerating or decelerating, (as the throttle is 1) the car's turn radius and velocity balance out so the car turns 90 degrees in about 0.775 seconds, 180 degrees in 1.55 seconds, and 360 degrees in 3.1 seconds.
    • Accelerating while turning (starting from a standstill with throttle and steer set to 1)
    • While turning with steer set to 1 (or -1), the maximum forwards velocity the car can reach is around 1234. It reaches this after 5 seconds.

    • The speed of the car after x time can be estimated with the following equation: 1234 * (1 - e ^ [-{time / 0.74704}])

      Example Python implementation:

    import math\n\nVMAX = 1234\nTAU = 0.74704\n\ndef get_speed_from_time_turning(time):\n    return VMAX * (1 - math.exp(-(time / TAU)))\n\ndef get_turn_time_from_speed(speed):\n    speed_adj = -(speed / VMAX - 1)\n    return -math.log(speed_adj, math.e) * TAU\n
    • Decelerating while turning (starting from the top speed with throttle and steer set to 1)
    • While turning with steer set to 1 (or -1), the minimum forward velocity the car can reach is around 1234. It reaches this after 7.5 seconds.

    • The speed and time can both be estimated with linear piecewise functions. The blue lines is the real velocity, and the orange line is the velocity that is predicted by the piecewise.

      Example Python implementation:

    def get_speed_from_time_turning(time):\n    if time >= 7.5:\n        return 1234\n\n    if time >= 4.5:\n        return 1272.889 - 5.185 * time\n\n    if time >= 4:\n        return 1380 - 27.5 * time\n\n    if time >= 3.2:\n        return 1530 - 65 * time\n\n    if time >= 2.6:\n        return 1743.333 - 131.667 * time\n\n    if time >= 1.3:\n        return 2247 - 325.384615 * time\n\n    if time >= 0.3:\n        return 2344 - 400 * time\n\n    if time >= 0.1:\n        return 2323 - 330 * time\n\n    if time > 0:\n        return 2300 - 100 * time\n\n    return 2300\n\ndef get_time_turning_from_speed(speed):\n    if speed <= 1234:\n        return 7.5\n\n    if speed <= 1248:\n        return 245.4857 - 0.192857 * speed\n\n    if speed <= 1270:\n        return 50.18 - 0.03636 * speed\n\n    if speed <= 1322:\n        return 23.53846 - 0.01538 * speed\n\n    if speed <= 1401:\n        return 13.24 - 0.007595 * speed\n\n    if speed <= 1824:\n        return 6.9 - 0.00307 * speed\n\n    if speed <= 2224:\n        return 5.86 - 0.0025 * speed\n\n    if speed <= 2290:\n        return 7.039 - 0.00303 * speed\n\n    if speed <= 2300:\n        return 23 - 0.01 * speed\n\n    return 0\n
    "},{"location":"community/air-show/","title":"Air show","text":""},{"location":"community/air-show/#summary","title":"Summary","text":"

    Rocket League, Music, and Programming: It all comes together in the 2021 Rocket League Air Show, hosted by Rocket Sledge!

    The best bot choreography presentation will win $1000! Open to both team and solo entries. The bar has been set high by the original video in February 2020. What will you do to rise above the rest and earn the viewers' votes?

    "},{"location":"community/air-show/#dates","title":"Dates","text":"

    February 15th: Check-in and progress report with Sledge. At this time we may be able to indicate how many spots are available for the video and even confirmation of your entry (based on quality and progress).

    March 15th: Full Submission due.

    Video: Youtube

    "},{"location":"community/air-show/#getting-started","title":"Getting Started","text":"

    Tutorial: Youtube

    You can chat / get help / form teams in the special air show discord channel.

    "},{"location":"community/air-show/#previous-years-submissions","title":"Previous year's submissions","text":"

    The code from last year's entries is open source!

    "},{"location":"community/air-show/#2020","title":"2020","text":"
    • Scripted
    • _Fool_
    • Awakening

    You shouldn't lift entire scenes, but feel free to borrow code and concepts.

    "},{"location":"community/air-show/#getting-help","title":"Getting Help","text":"
    • Ask questions on the RLBot #air-show chat room
    • We've heard interest from a few video editing experts, you might be able to team up! Check in the chat room.
    • The folks at the Rocket League Mapmaking Discord might want to collaborate if you have a cool idea.
    • You can watch the teams from previous years talking shop about what worked and what didn't:

    2020: https://www.youtube.com/watch?v=4oMdXBO9I3A 2021: TBA

    "},{"location":"community/air-show/#rules","title":"Rules","text":"

    You may enter solo or as a team.

    In order to win, you must be one of Sledge's personal picks to include in the showcase video on his channel, and then within that group, you must get the most votes from viewers via a google form, similar to the one from last year.

    All music must be sourced from Epidemic Sound ONLY. You can create a month long trial account and download your music here: https://www.epidemicsound.com/subscriptions/choose/. Music outside of this service will not be permitted even if it is \u201ccopyright free\u201d. Epidemic sound has an amazing search filter and every genre of music. It is the same music service used by almost every major RL Youtuber.

    Participation or inclusion in the video is not guaranteed at this point. Quality is important, refer to the original video as an example of what we are looking for. The first goal is to have a basic idea in progress by the February 15th check in date.

    No part of your entry may be shared or posted until Sledge's showcase video has been live for at least 2 weeks. Going forward you are also agreeing that Sledge may use parts of your entry in future videos and promotions. Also you entry will most likely be stolen and posted to tiktok multiple times... welcome to the internet!

    Please save test replay files and bloopers for possible inclusion in secondary video.

    You are welcome to use \"state setting\" to teleport cars / make them move unnaturally. Some viewers last year loved stuff like that, some thought it was cheap, up to you how you want to chase those votes.

    Also fine to use custom maps / any other mods.

    "},{"location":"community/air-show/#prizes","title":"Prizes","text":"
    • 1st = $1000
    • 2nd = TBD
    • 3rd = TBD
    "},{"location":"community/community-guidelines/","title":"Community guidelines","text":""},{"location":"community/community-guidelines/#social-conduct","title":"Social Conduct","text":"
    • No harassment
    • Be inclusive (no racism, sexism, etc)
    • Keep everything safe-for-work
    "},{"location":"community/community-guidelines/#discord","title":"Discord","text":"

    Most communication happens on our discord

    "},{"location":"community/community-guidelines/#code-of-conduct-for-mods","title":"Code of conduct for mods","text":"
    • Protect people from harassment and spam using the minimum required force.
    • De-escalate conflicts, and don't engage in tense arguments.
    • Employ yes-and whenever possible.
    • No power-tripping, no undue influence over people's projects. Be a servant.
    "},{"location":"community/community-guidelines/#roles","title":"Roles","text":"

    Discord users can be assigned roles, which is useful for granting privileges to different groups of people, contacting them all at once, etc.

    "},{"location":"community/community-guidelines/#tournament-roles","title":"Tournament Roles","text":"

    Roles are awarded based on your placement in the latest official tournament. The current roles are Champion, Top 4, Top 8, and Top 16. These roles are permenant, however only the ones from the latest tournament will be colored and displayed seperately from the RLBot member list.

    "},{"location":"community/community-guidelines/#competition","title":"Competition","text":"

    We regularly run tournaments and other events where bots get ranked and programmers get kudos. The specific rules of each event are generally up to the organizer, but here are a few guidelines to promote fairness:

    "},{"location":"community/community-guidelines/#record-the-matches","title":"Record the matches","text":"

    When playing for rank, you should have some kind of stream or recording that people can view and see that the match was played fairly.

    "},{"location":"community/community-guidelines/#make-sure-your-opponent-is-healthy","title":"Make sure your opponent is healthy","text":"

    It's nice to make sure an opponent is working as designed and you have the latest version before playing against it for rank

    • If possible, ask the author before the match.
    • If you don't get pre-approval, and they ask you afterward to make the match not count for rank because their bot was broken by something outside their control, the community is likely to respect those wishes.
    • As a bonus, it's nice to press the [home] key at some point to show bot performance stats. This helps to show that your computer is running the bots at full strength.
    "},{"location":"community/community-guidelines/#make-it-known-when-you-borrow-code","title":"Make it known when you borrow code","text":"

    Using code from other people with permission is good, as long as you make it publicly known. Many people give more praise to bots that they believe are made from scratch.

    • If there's reasonable suspicion that you secretly copied lots of another bot, you may be asked to show your source code to some moderators before entering ranked events.
    • If they find that there is copied code, there must be a public disclosure before entering the event.
    "},{"location":"community/community-guidelines/#the-fork-rule","title":"The Fork Rule","text":"

    If you forked your bot from a publicly recognized bot utility package, the fork rule doesn't apply to you.

    If you fork a bot (except for a tutorial bot), your bot is in fork mode, which means:

    • You can't enter league play or official tournaments or ranked games on braacket.com.
    • You must give your bot a name that makes it clear you're a fork (small events might choose to allow fork-mode competitors). The name should be formatted as \u201cYourBot [OriginalBot]\u201d.
    • Your bot must remain open source.

    This gives proper attribution, and helps the community keep track. You can escape from fork mode by demonstrating to the community (judged by the discord moderator team) that your bot is unique enough to compete under its own name.

    "},{"location":"community/rlbot-pack/","title":"RLBot Pack","text":"

    The RLBotPack is a repository holding frequently requested bots in one convenient place. The main intended users are people joining the discord looking for a fun bot to try out. It may also be useful as a way for people running streams to get an up-to-date version of your bot.

    To be a part of the pack, you just need to create a pull request with your bot to the repository.

    To qualify:

    • Your bot must be capable of auto-run
    • Use Python or Rust? You're all set.
    • Other languages? We have a Java wiki, a C# wiki and a Scratch video.
    • Your bot must not have any crazy external requirements (except for very common ones like Java or Google Chrome)
    • You must be willing to trim out any extra bot configs from your folder that people wouldn't care about
    • Obey the guidelines
    • If you join the bot pack, people will be free to play against you for rank in the braacket league whenever they want!

    After you create the pull request, somebody will come along, review your bot and eventually merge it to the pack.

    "},{"location":"community/rlbot-pack/#pull-request-tips","title":"Pull Request Tips","text":"
    • If you're uploading the files via GitHub, please make sure you're not uploading useless files like __pycache__, because the web upload bypasses .gitignore.
    "},{"location":"community/rlbot-pack/#updating-an-existing-bot","title":"Updating an existing bot","text":"

    It's very common for people's forked repository to get out of sync with the central RLBot/RLBotPack, and then when you make a pull request there's a bit of a mess. Here's a strategy for avoiding that:

    1. Make sure you have latest information from the central repo
    git remote add rlbot-origin https://github.com/RLBot/RLBotPack.git\ngit fetch rlbot-origin\n
    1. Pick a branch name for your change, e.g. my-new-change
    git checkout -b my-new-change rlbot-origin/master\n
    1. Make your changes, e.g. you may be copying / overwriting files in your bot folder.
    2. Make a commit and push it to your forked repo.
    git add .\ngit commit -m \"My new change.\"\ngit push origin my-new-change\n
    1. Visit your forked repo on github.com and create a pull request from the new branch.
    "},{"location":"community/rocket-league-story-mode/","title":"Rocket league story mode","text":""},{"location":"community/rocket-league-story-mode/#playing-rocket-league-story-mode","title":"Playing Rocket League Story Mode","text":"

    To get started with Story Mode, install RLBotGUI.

    Once installed, go to Add->Download Botpack to download the community's bots. Once they are downloaded you can click on \"Story Mode\" on the top right.

    "},{"location":"community/rocket-league-story-mode/#upgrades-and-teammates","title":"Upgrades and Teammates","text":"

    After you win a challenge, you get rewarded 1 currency. You can use it to purchase upgrades or recruit an available teammate. After you win all challenges in a city, all opponents from that city become available to recruit.

    Some matches require you to have teammates. If you don't have enough teammates and no currency, then you can play previous matches to earn some more currency.

    "},{"location":"community/rocket-league-story-mode/#choosing-difficulty","title":"Choosing Difficulty","text":"

    When you start Story Mode, you can choose your difficulty between easy, default and custom.

    • Easy is best for gold/plat players
    • Default is best for diamond/champ players

    Custom allows you to provide a JSON file that is used as the story configuration. This is what the default configurations looks like.

    Here are some example custom configurations:

    • Psyonix-only bots: Best for bronze/silver players who find the default bots too difficult
    • No teammates/Unfair: Best for players who find \"default\" configuration too easy or find bot teammates annoying.
    "},{"location":"community/rocket-league-story-mode/#creating-custom-configurations","title":"Creating Custom Configurations","text":"

    This is the actual story configuration used in Story Mode so you can use that as a reference to create your own custom configuration.

    Note that custom configurations doesn't allow you to change what the map looks like, name of the cities and how many cities there are. The rest is all customizable.

    If you are interested in only changing the \"feel\" of the story without changing any of the challenges then you can update the \"description.message\" for each city and \"challenges.display\" for each challenge. These are the text items shown to the user.

    If you actually want to change the challenges, then you can add/remove/modify the challenges for each city. Here are the fields that are supported for a challenge object:

    field meaning id Usually CITY-# format, just has to be unique across the config humanTeamSize opponentBots List containing keys to bot ids (either in the bots section or base-bots.json) map Rocket League arena to play in display Text to show to the user about this challenge max_score Optional. If set, it will set the maximum goals mutator so only few values are allowed disabledBoost Optional. If true, the map is set with no boost so no one will have boost completionConditions Optional. More details below. limitations Optional. List that can contain: \"half-field\". This maps to heatseeker mode

    completionConditions is an object. If multiple fields are provided, each condition is \"and\"-ed with the other conditions. A user completes a challenge if all of them are true. The default condition is that a player must win.

    {\n  \"win\": true, //set to false if you don't care,\n  \"scoreDifference\": 3 //player must win by at least this much\n  \"selfDemoCount\": 0 //player must not get demoed more than this\n  \"demoAchievedCount\": 2 //player must at least demo opponents this many time\n}\n
    "},{"location":"community/tips-for-running-tournaments/","title":"Tips for running tournaments","text":""},{"location":"community/tips-for-running-tournaments/#announcing-the-tournament","title":"Announcing the Tournament","text":"

    Normally tournament organizers will publish some kind of rules document. Google docs has been popular for that so far. Consider including the following:

    • Tournament format
    • Submission deadline(s)
    • How to submit (upload to google drive folder is a popular technique)
    • Stream time and twitch channel
    • Your intended tick rate (read and understand Tick Rate)
    • Whether or not hive mind style bots are allowed

    Here's an example document

    "},{"location":"community/tips-for-running-tournaments/#gathering-submissions","title":"Gathering Submissions","text":""},{"location":"community/tips-for-running-tournaments/#python-bot-requirements","title":"Python Bot Requirements","text":"

    People generally just send their whole bot folder, and that works well.

    "},{"location":"community/tips-for-running-tournaments/#net-c-bot-requirements","title":".NET / C# Bot Requirements","text":"

    Direct people to Tournament-Submissions, and also encourage them to do Auto Launching

    "},{"location":"community/tips-for-running-tournaments/#java-bot-requirements","title":"Java Bot Requirements","text":"

    Direct people to Tournament Submissions. If they follow those instructions, you'll be given a nice zip file with a README inside it.

    Also encourage them to do this, it'll make your life much easier

    "},{"location":"community/tips-for-running-tournaments/#scratch-bot-requirements","title":"Scratch Bot Requirements","text":"

    People who program their bots in Scratch should submit their whole folder.

    Scratch program (sb3) requirements

    • All the tournament code should be in the player 1 sprite.
    • Clicking the green flag should be the only thing necessary to start your program.

    CFG file requirements

    headless = True\nseparate_browsers = True\npretend_blue_team = True\n
    "},{"location":"community/tips-for-running-tournaments/#deadline-management","title":"Deadline Management","text":"

    It's a good idea to set a bot submission deadline at least 24 hours before the start of the tournament stream. This will give you an opportunity to test all the bots.

    Encourage early submissions so you can get a head-start on testing, and allow people edit their submission up until the deadline. If you feel confident from your pre-deadline testing that you'll be able to run most of the bots with no issues, consider giving an extension on the deadline--many people will need one.

    "},{"location":"community/tips-for-running-tournaments/#pre-tournament-bot-testing","title":"Pre-Tournament Bot Testing","text":"

    You should test all the bots beforehand.

    • Do they start successfully?
    • Do they have any obvious behavior problems that might be a problem with your setup?
    • Feel free to check with the bot maker about the expected behavior.
    • Do they run properly on both blue and orange team? Consider running test matches of each bot vs itself.
    • Are the C#/Java bots running on different ports? Each C# and Java bot must run on a separate port from the rest of the bots.
    "},{"location":"community/tips-for-running-tournaments/#running-bots","title":"Running Bots","text":""},{"location":"community/tips-for-running-tournaments/#net-c-bots","title":".NET / C# Bots","text":"
    • In the ideal case, if they followed Auto Launching successfully, you will only need to load the cfg file like you would for a Python bot.
    • Otherwise, you will need to locate the .exe file in the submission and run it manually. The RLBot framework output will hint about this.
    • Make sure the bot's port is different from the rest of the bots.
    "},{"location":"community/tips-for-running-tournaments/#java-bots","title":"Java Bots","text":"

    Prerequisite: You will need to have the Java Runtime Environment (JRE) installed. You are likely to need the latest one (Java 11 at time of writing) in case any of the botmakers compiled with it.

    You hopefully received a zip file for each bot. Extract it somewhere and consult the README.

    • In the ideal case, if they followed Auto Launching Java successfully, you will only need to load the cfg file like you would for a Python bot.
    • Otherwise, you will need to locate the .bat file associated with the Java portion of their bot and run it manually. The RLBot framework output will hint about this.
    • Make sure the bot's port is different from the rest of the bots.

    If you run into any trouble, consult this video

    "},{"location":"community/tips-for-running-tournaments/#scratch-bots","title":"Scratch Bots","text":"

    All recently-created Scratch bots should auto start with no issues, BUT often the process takes a while. Consider pausing the match until you see something like \"received first input from scratch bot\" in the console.

    If the bot is very old and does not auto run, they may need to do this

    "},{"location":"community/tips-for-running-tournaments/#streaming-and-casting","title":"Streaming and Casting","text":""},{"location":"community/tips-for-running-tournaments/#co-casters","title":"Co-casters","text":"

    If you want to invite others to do commentary with you, you'll need to:

    • Give them a real-time view of the action so they can comment on things as they happen.
    • Get the sound of their voice flowing through your system audio.

    A good way to do this is to start a Discord call and share your screen. If you have internet bandwidth or CPU constraints, make sure you share your screen at a low framerate and / or low resolution.

    "},{"location":"community/tips-for-running-tournaments/#diagnostics","title":"Diagnostics","text":""},{"location":"community/tips-for-running-tournaments/#bot-response-rate","title":"Bot Response Rate","text":"

    You can hit the [home] key to start rendering bot response rates in the upper left corner of Rocket League. You'll see a percentage that indicates how many of the rendered frames in Rocket League received fresh control inputs from a given bot.

    • If you have capped your framerate at 60fps, then you should expect to see 100% for all bots if they are performing well. - If your framerate is higher than 60, you will see percentages lower than 100 for some languages, and that's OK.
    • If you ever see a percentage above 100, that's a big concern. It may mean that there are multiple bot processes trying to control the same player. Make sure bots from the previous match are truly dead.
    "},{"location":"community/tips-for-running-tournaments/#running-the-tournament","title":"Running the tournament","text":""},{"location":"community/tips-for-running-tournaments/#bracket","title":"Bracket","text":"

    All our bots are in their own league on Braacket on which you can also create tournaments with most formats. You can also use your own site of preference or own local program which looks more graphically pleasing. But it's recommended to keep your bracket updated during the tournament so people don't lose track.

    "},{"location":"community/tips-for-running-tournaments/#things-to-do-in-between-games","title":"Things to do in between games","text":"
    • Make sure the FPS is capped at the desired number (maybe 120)
    • Don't forget to press 'H' when the games start, so the remove the useless HUD
    • Try to check twitch/discord in case there is something wrong and do not be afraid to restart a match
    • Have fun!
    "},{"location":"framework/architecture/","title":"Architecture","text":""},{"location":"framework/architecture/#startup","title":"Startup","text":""},{"location":"framework/architecture/#bots","title":"Bots","text":""},{"location":"framework/architecture/#python-bot","title":"Python Bot","text":""},{"location":"framework/architecture/#java-bot","title":"Java Bot","text":""},{"location":"framework/architecture/#diagram-source-code","title":"Diagram Source Code","text":"

    Created at sequencediagram.org with:

    title RLBot Startup Sequence\n\n\n[->Python: start match on map x with bots [y, z]\nbox over Python: Start RLBot.exe\nbox over Python: Start Rocket League\nparallel\nPython->DLL: start match on map x with cars [y, z]\nDLL->RLBot.exe: start match on map x with cars [y, z]\nRLBot.exe -> Rocket League: start match on map x\nparallel off\nRLBot.exe -> Rocket League: spawn cars\nbox over RLBot.exe,Rocket League:Continuous sync\n\nparallel\nPython->DLL: poll for game tick packet\nDLL->RLBot.exe: poll for game tick packet\nparallel off\nparallel\nRLBot.exe->DLL: packet with active match\nDLL->Python: packet with active match\nparallel off\nbox over Python:Launch bot processes y and z,\\ninforming each of their index\n
    title RLBot Python Bot\n\n\n[->Python BotManager: start up with index n\nPython BotManager->Python Bot:construct with index n\nparallel \nPython BotManager->DLL: poll for game tick packet\nDLL->RLBot.exe: poll for game tick packet\nparallel off\nparallel\nRLBot.exe->DLL: game tick packet\nDLL->Python BotManager: game tick packet\nparallel off\nPython BotManager->Python Bot: get_output()\nPython Bot->Python BotManager: SimpleControllerState\nparallel\nPython BotManager->DLL: send controls\nDLL->RLBot.exe: send controls\nparallel off\n
    "},{"location":"framework/console-commands/","title":"Console commands","text":""},{"location":"framework/console-commands/#sending-a-console-command","title":"Sending a Console Command","text":"

    To send a console command from a python bot, e.g. Stat FPS, you would do this:

    from rlbot.utils.game_state_util import GameState\n\n# other code ...\n\ngame_state = GameState(console_commands=[\"Stat FPS\"])\nself.set_game_state(game_state)\n

    Other languages are not supported yet.

    "},{"location":"framework/console-commands/#known-console-commands","title":"Known Console Commands","text":"

    All of these are confirmed to work as intended. Please add more as you find them!

    • QueSaveReplay - Creates a replay keyframe and causes a replay to be saved at the end of the match.
    • Set WorldInfo WorldGravityZ 0.0000001 - Zero gravity (pretty much). Setting to 0 returns it to default. You can also use state setting to set gravity. Warning: Sending this command every frame will likely make your game lag!
    • Set WorldInfo TimeDilation 3 - Speeds up the game by 3 times. Can also be used to slow down the game with a number between 0 and 1. You can also use state setting to set game speed.
    • Stat FPS - Turns on a little in-game FPS counter. Can be turned back off with Stat FPS 0
    • ShowDebug PHYSICS - Nice little text readout which shows you some values, and also the names of some specific classes/attributes that you can use Set on.
    • Pause - Pauses the game. Send Pause to unpause the game. get_output/GetOutput/getOutput will still be called when the game is paused. This pause is the same as the pause when Escape is pressed.
    "},{"location":"framework/console-commands/#research-for-more-console-commands","title":"Research for More Console Commands","text":"

    Try some of these!

    https://www.reddit.com/r/RocketLeagueMods/comments/4vuj0h/list_of_available_console_commands/

    "},{"location":"framework/operating-system-support/","title":"Operating system support","text":""},{"location":"framework/operating-system-support/#windows","title":"Windows","text":"

    RLBot was originally made for Windows, so Windows has the best support. Users are encouraged to watch this video to get started quickly with RLBotGUI!

    "},{"location":"framework/operating-system-support/#linux","title":"Linux","text":"

    RLBot only runs on linux with the old native linux version of rocket league. This version is only available on steam. There is a (probably outdated) install script here.

    If you only have the epic version of the game or you want to run the proton version, you're unfortunately out of luck. This is due to libRLBotInterface.so being broken on linux. A rewrite of RLBot (v5) is being worked on and will support linux.

    "},{"location":"framework/operating-system-support/#mac","title":"Mac","text":"

    Mac support is currently unknown and may not work. If you want to try, see the instructions below.

    "},{"location":"framework/operating-system-support/#instructions","title":"Instructions","text":"
    1. Make sure you have Python 3.11 and pip
    2. Run these commands
    python3 -m pip install --user --upgrade pip\npython3 -m pip install --user gevent eel\npython3 -m pip install --user --upgrade rlbot rlbot_gui\npython3 -c \"from rlbot_gui import gui; gui.start()\"\n
    "},{"location":"framework/psyonix-api-notes/","title":"Psyonix api notes","text":"

    Hello everyone! We're proud to announce that the Psyonix bot API has finally been integrated into RLBot! We hope you're just as excited as we are about this milestone! \ud83c\udf89

    "},{"location":"framework/psyonix-api-notes/#details","title":"Details","text":"

    Check out this diagram to get some intuition for this migration. Everything on the left staying the same or as close to the same as possible, so your bots are expected to keep working with no changes required!

    "},{"location":"framework/psyonix-api-notes/#what-you-can-expect-from-this-new-version-of-rlbot","title":"What you can expect from this new version of RLBot","text":"

    We're aiming for a backwards compatibility with this first bot API release, so expect your bots to play almost exactly like they used to!

    • The renderer now has occlusion, so 3D lines disappear behind objects correctly!
    • You can still use state setting, except:
    • Can\u2019t manipulate boost pads
    • Can\u2019t mess with the car\u2019s jump state
    • Can\u2019t provide partial location / velocity, must fully specify
    • The GameTickPacket will have all the same data except:
    • It will have non-interpolated values straight from the physics engine, same as RigidBodyTick!
    • Latest ball touch will always be blank for now (fixed)
    • Boost respawn timers don't work yet
    • Unfortunately, quick chat is not supported yet (1/2 fixed)
    • We only support Soccer, exhibition mode at the moment. (More modes are supported)
    • The game data will currently update in memory at 60Hz, ~~regardless of Rocket League's frame rate~~ (anecdotally it seems to be capped at the frame rate). We may be able to tune that later. (We now have 120hz)
    • The Psyonix API itself and the code that interfaces with it directly are closed source at the moment.
    "},{"location":"framework/psyonix-api-notes/#what-you-can-look-forward-to-in-the-future","title":"What you can look forward to in the future","text":"
    • No more breaking after updates! Since RLBot no longer relies on DLL injection, RLBot will continue to work after every Rocket League update.
    • LAN support is a possibility in the future. With a virtual LAN (VLAN), this could mean being able to play against bots on different machines over the internet, with your friends!
    • Support for Linux and macOS is planned! (C++ and C# bots won't work)
    • Rumble support is planned. Bots will be able to take part in the mayhem! (Done)
    • Unrelated to the API:
    • DomNomNom is working on a team communication system for bots. (Done)
    • Chip is working on advanced pathfinding for bots.
    "},{"location":"framework/psyonix-api-notes/#regarding-bugs","title":"Regarding Bugs","text":"

    This is a lot buggier than a normal release--RLBot broke due to a Rocket League patch and we chose to move forward with the official API rather than fix our old injection technique. Sorry for the bugs / missing features!

    Please test out your bots and report any bugs to #issues-and-bugs or the GitHub repository's Issues page: https://github.com/RLBot/RLBot/issues. We appreciate all the help we can get!

    List of Busted Bots

    • NV Derevo, on some computers
    "},{"location":"framework/psyonix-api-notes/#rollback-instructions","title":"Rollback Instructions","text":"

    If it's a serious problem for you, you can roll back your Rocket League and use our old 1.14.12 version. Note that while you're on the old Rocket League, you will be unable to play online!

    You can do it by clicking steam://nav/console and then entering download_depot 252950 252951 6062228629972172324. Then read https://www.reddit.com/r/Steam/comments/611h5e/guide_how_to_download_older_versions_of_a_game_on/ starting with step 7.

    And then, once you're done with that, you'll need to pin your rlbot version to 1.14.12. If you're using the old GUI, you can accomplish that by changing this line https://github.com/RLBot/RLBotPythonExample/blob/master/requirements.txt#L3 to rlbot==1.14.12.

    If you're using the new colorful RLBotGUI, you'll need to go find rlbot-requirements.txt in the vicinity of C:\\Users\\yourname\\AppData\\Local\\RLBotGUI\\rlbot-requirements.txt and do the change there.

    "},{"location":"framework/psyonix-api-notes/#thanks","title":"Thanks","text":"

    Thank you to everyone for sticking with the community! Of course, a massive thank you to Psyonix for supporting us and giving us the API! We can't wait to see RLBot evolve further!

    "},{"location":"framework/sockets-specification/","title":"Sockets specification","text":"

    Sockets are currently available with Windows and Mac support only. Linux coming soon.

    You can use https://github.com/RLBot/RLBot/tree/master/src/main/cpp/RLBotInterface/src as a reference implementation in c++.

    "},{"location":"framework/sockets-specification/#data-format","title":"Data Format","text":"

    Unless otherwise specified, data is sent and received on the socket in this format:

    • First two bytes are an integer (big-endian) which specifies the data type (see list below).
    • Next two bytes are an integer (big endian) which specifies the number of bytes in the payload.
    • Remaining bytes are a payload. The logic for parsing it will depend on the data type, but generally it will be binary data in flatbuffer format. Using tools provided by Google (i.e. flatc.exe) and rlbot.fbs you can auto-generate code in various languages suitable for writing / parsing the payload data.
    "},{"location":"framework/sockets-specification/#data-types","title":"Data Types","text":"

    Types expected to flow from RLBot to the client are in bold. Some are bi-directional.

    1. Game tick packet (arrives at a high rate according to /Tick-Rate except \"desired tick rate\" is not relevant here)
    2. Field info (sent once when a match starts, or when you first connect)
    3. Match settings (sent once when a match starts, or when you first connect)
    4. Player input
    5. Actor mapping data (deprecated, related to Remote RLBot)
    6. Computer id (deprecated, related to Remote RLBot)
    7. Desired game state
    8. Render group
    9. Quick chat
    10. Ball prediction (sent every time the ball diverges from the previous prediction, or when the previous prediction no longer gives a full 6 seconds into the future).
    11. Ready Message (clients must send this after connecting to the socket)
    12. Message Packet: List of messages, having one of the following types:
      • PlayerStatEvent - Event when a player performs an action or earns an accolade recognized in statistics, e.g. BicycleHit, HatTrick, MostBoostPickups.
      • PlayerSpectate - Spectator camera is now focusing on a new player.
      • PlayerInputChange - Human or bot has touched their controller, e.g. turned on boost, changed steering, etc.
    "},{"location":"framework/sockets-specification/#connecting","title":"Connecting","text":"

    Prerequisites (handled automatically by RLBotGUI / the RLBot framework):

    • Rocket League must be running under the -rlbot flag.
    • RLBot.exe must be running. After it successfully connects to Rocket League, it will start listening on TCP port 23234.

    • As a client, connect to TCP port 23234. Note: please expect to receive the port as a parameter in the future rather than hard coding

    • Send a 'ready' message, as defined here. Be sure to use the data format explained above (two bytes for data type, two bytes for size...)

    Some attributes in the ready message are not used yet. Once you're connected, you will start receiving data on the socket, with one of the data types specified above.

    "},{"location":"framework/sockets-specification/#sending-data","title":"Sending Data","text":"

    Send data to the same TCP socket, using the same format (two bytes for type, two bytes for size). You can send match settings (starts a new match), player input, desired game state, render group, and quick chat.

    Consult google.github.io/flatbuffers to learn how to construct the byte array for your payload in the language of your choice.

    "},{"location":"framework/sockets-specification/#future-plans","title":"Future plans","text":"
    • Allow clients to connect on a different port and exchange data in json format instead of flatbuffers.
    "},{"location":"framework/sockets-specification/#client-libraries","title":"Client Libraries","text":""},{"location":"framework/sockets-specification/#python","title":"Python","text":"
    • https://github.com/RLBot/RLBot/tree/master/src/main/python/rlbot/socket
    "},{"location":"framework/sockets-specification/#whos-using-sockets","title":"Who's Using Sockets","text":"
    • The core RLBot framework uses sockets from Python to start matches.
    • The core RLBot framework uses sockets from within RLBotInterface.dll to run bots.
    • Javascript / Typescript: easyrlbot
    • RLBotControllerOverlay
    • This little test script
    "},{"location":"framework/supported-programming-languages/","title":"Supported programming languages","text":""},{"location":"framework/supported-programming-languages/#main-languages","title":"Main Languages","text":"

    The following list of languages are supported by core developers of the RLBot framework, or have reached a very high level of documentation and support from the community. They are featured on rlbot.org.

    "},{"location":"framework/supported-programming-languages/#python","title":"Python","text":"

    RLBotPythonExample

    "},{"location":"framework/supported-programming-languages/#java","title":"Java","text":"

    RLBotJavaExample

    "},{"location":"framework/supported-programming-languages/#c-and-other-net-languages","title":"C# (and other .NET languages)","text":"

    RLBotCSharpExample

    "},{"location":"framework/supported-programming-languages/#c","title":"C++","text":"

    CPPExampleBot

    "},{"location":"framework/supported-programming-languages/#rust","title":"Rust","text":"

    crates.io

    RLBotRustTemplateBot

    "},{"location":"framework/supported-programming-languages/#javascript","title":"Javascript","text":"

    EasyRLBot

    EasyRLBotExample

    "},{"location":"framework/supported-programming-languages/#scratch","title":"Scratch","text":"

    RLBotScratchInterface

    "},{"location":"framework/supported-programming-languages/#community-supported-languages","title":"Community Supported Languages","text":"

    What follows is a list of languages, that the community have also made support for, however, their frameworks may be less documented and maintained. If you want to use a language not listed, Nim uses a socket intermediate bot as a bridge between the game and the Nim executable. This can be used by any other language (that can use sockets).

    "},{"location":"framework/supported-programming-languages/#clojure","title":"Clojure","text":"

    Clojure-Bot

    "},{"location":"framework/supported-programming-languages/#nim","title":"Nim","text":"

    NimExampleBot

    "},{"location":"framework/supported-programming-languages/#go","title":"Go","text":"

    RLBotGo

    RLBotGoExample

    "},{"location":"framework/supported-programming-languages/#lua","title":"Lua","text":""},{"location":"framework/supported-programming-languages/#asciidots","title":"Asciidots","text":"

    Because who doesn't love drawing ascii art?

    AsciiDots Documentation

    Documentation for RLBot version of AsciiDots

    Example bot

    "},{"location":"framework/supported-programming-languages/#brainfuck","title":"Brainfuck","text":"

    Scalable and efficient bot-making

    Brainfuck documentation

    Example bot

    "},{"location":"miscellaneous/extracting-map-meshes/","title":"Extracting map meshes","text":""},{"location":"miscellaneous/extracting-map-meshes/#prerequisites","title":"Prerequisites","text":"
    • 64-bit Windows
    • Rocket League
    • U-Model
    • Blender 2.9+
    • Blender .psk addon
    "},{"location":"miscellaneous/extracting-map-meshes/#additional-notes-before-getting-started","title":"Additional notes before getting started","text":"

    This tutorial was tested on Blender 3.1.

    Python knowledge is preferred for this tutorial, but you can get by without it.

    Python does not need to be installed for this to work.

    The resulting .bin files can be imported into any language that can read binary numbers from a file. The id files are a chain of 32-bit integers in little-endian format, and the vertices are stored at 3 32-bit floats in a row (x, y, z), also stored in little-endian format. Each ID in ids corresponds to the index of the vertex if you parsed the vertices in the order that they appear in the file. (By default.)

    "},{"location":"miscellaneous/extracting-map-meshes/#overview","title":"Overview","text":"
    1. Opening U-Model the right way
    2. How to identify a map
    3. Extracting a map
    4. Identifying collision files
    5. Importing to Blender
    6. Converting object to binary data
    "},{"location":"miscellaneous/extracting-map-meshes/#opening-u-model-the-right-way","title":"Opening U-Model the right way","text":"

    Create a bat file called umodel.bat, and save this to it:

    umodel.exe -game=rocketleague -path=\"C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole\"\n

    Depending on where you saved U-Model, you may have to use cd before that to get to it:

    cd C:\\Program Files (x86)\\umodel_win32\numodel.exe -game=rocketleague -path=\"C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole\"\n

    Use this bat file that you create to launch U-Model whenever you need to use it.

    If you have Rocket League install through Epic Games, use this path instead: C:\\Program Files\\Epic Games\\rocketleague\\TAGame\\CookedPCConsole

    WARNING: Be sure to use the 32-bit version of U-Model! You're safe as long as you don't change umodel.exe to umodel_64.exe. Some assets will refuse to load, if you do.

    "},{"location":"miscellaneous/extracting-map-meshes/#how-to-identify-a-map","title":"How to identify a map","text":"

    In the top-left-ish corner, there's space for you to filter all the files. If you type in _P.upk, you will get a list of all of the maps.

    If you're looking for a map, filter by MapImage. You can double-click on a file to view a preview of the map with a similar name. Press the key O (or go top left -> File -> Open package) to get back to the menu with all of the files.

    "},{"location":"miscellaneous/extracting-map-meshes/#extracting-a-map","title":"Extracting a map","text":"

    In this example, I will be using Stadium_P.upk - otherwise known as DFH Stadium.

    Right-click on the map you want to export, click Export, and all of the map data will be extracted for you.

    All files are extracted to the UmodelExport folder in whatever folder you saved U-Model to. For me, this is C:\\Program Files (x86)\\umodel_win32\\UmodelExport.

    "},{"location":"miscellaneous/extracting-map-meshes/#identifying-collision-files","title":"Identifying collision files","text":"

    Inside the folder of the map you extracted, there should be 5 more folders - the one that you want is called StaticMesh3. In this folder, simply look for any .pskx files that have the word collision in them. For DFH Stadium, there are 4 files:

    • Goal_STD_Collision.pskx
    • Field_STD_Collision_Corner.pskx
    • Field_STD_Collision_SideTop.pskx
    • Field_STD_Collision_SideBot.pskx

    These files contain all of the available field collision information.

    "},{"location":"miscellaneous/extracting-map-meshes/#importing-to-blender","title":"Importing to Blender","text":"

    Open Blender, and select \"General.\" This will load a default 3D scene, with a cube, light source, and camera.

    Next, in the top right, delete all three of these things. (Right-click -> Delete)

    Now, we import ONE of our objects. This is important - we can only convert one at a time unless changes are made to the script in the next section. When you want to convert another object, delete the only one in the scene first. The process is the same as deleting the cube, as we did previously.

    To import an object, go to the top right -> Files -> Import -> Skeleton Mesh (.psk). Use this to import one of the .pskx collision files that we got earlier.

    For this, I have imported DFH Stadium's Field_STD_Collision_Corner.pskx.

    "},{"location":"miscellaneous/extracting-map-meshes/#converting-the-object-to-binary-data","title":"Converting the object to binary data","text":"

    At the top of Blender, select the Scripting tab.

    In the top middle, select New.

    Copy & paste the below Python script:

    import bpy\n\n# Blender Python API Documentation\n# https://docs.blender.org/api/current/index.html\n\nprint()\n\nif len(bpy.context.scene.objects) != 1:\n    print(\"MORE THAN ONE OBJECT EXISTS!\")\n    exit()\n\nobj_name = \"soccar_corner\"\n\ndata = bpy.context.scene.objects[0].data\n\nids = []\nverts = []\n\nfor tri in data.polygons:\n    for id in tri.vertices:\n        ids.append(id)\n\nfor vert in data.vertices:\n    for coord in vert.co:\n        verts.append(coord)\n\nprint(f\"Number of ids: {len(ids)}\")\nprint(f\"Number of triangles: {len(ids) / 3}\")\nprint(f\"Number of coordinates: {len(verts)}\")\nprint(f\"Number of vertices: {len(verts) / 3}\")\n\nimport os\nfrom pathlib import Path\n\nos.chdir(Path.home() / \"Documents\")\n\n#import json\n\n#with open(obj_name + \"_ids.json\", \"w\") as f:\n#    json.dump(ids, f)\n\n#print(\"Wrote json ids\")\n\n#with open(obj_name + \"_vertices.json\", \"w\") as f:\n#    json.dump(verts, f)\n#    \n#print(\"Wrote json vertices\")\n\nimport struct\n\nwith open(obj_name + \"_ids.bin\", \"wb\") as f:\n    f.write(struct.pack(\"<\" + \"i\" * len(ids), *ids))\n\nprint(\"Wrote binary ids\")\n\nwith open(obj_name + \"_vertices.bin\", \"wb\") as f:\n    f.write(struct.pack(\"<\" + \"f\" * len(verts), *verts))\n\nprint(\"Wrote binary vertices\")\n

    You can edit the line obj_name = \"soccar_corner\" near the top to adjust the name of the outputted file, and os.chdir(Path.home() / \"Documents\") to edit the output folder.

    Click on the Play/Run button in the top middle to run the script.

    This creates the two bin files containing the ids and vertices from the object.

    If you want an example of using collision data and compiling them into a mesh to run collision queries on, check out the rl_ball_sym Rust project:

    • Reading into a mesh
    • Loading all collision data
    • Compiling all collision data into a big mesh, then triangles and a BVH
    "},{"location":"miscellaneous/lan-setup/","title":"Lan setup","text":""},{"location":"miscellaneous/lan-setup/#option-1-online-private-match-steam-or-epic","title":"Option 1 - online private match (Steam or Epic)","text":""},{"location":"miscellaneous/lan-setup/#requirements","title":"Requirements","text":"
    • Hamachi
    • BakkesMod
    • Rocket Plugin installed in Bakkesmod
    • RLBotGUI (only needed for the host)

    Quick Note: If the host can forward port 7777 / configure their firewall, then neither the host nor the clients need to use Hamachi. Then the host only has to provide their IP address to the clients who enter it into Rocket Plugin to connect. This allows more connections than the free version of Hamachi.

    "},{"location":"miscellaneous/lan-setup/#instructions-for-host","title":"Instructions for Host","text":"

    Only the host can load bots into the game!

    1. Create a network in Hamachi and note the network ID (tutorials can be found online).
    2. Make sure that BakkesMod is running.
    3. Start Rocket League with RLBotGUI (start a match, then quit the match to the menu).
    4. Use the Rocket Plugin to host a LAN match
    5. Press the \"Home\" key to open the Rocket Plugin menu.
    6. Setting a large team size helps, otherwise bots may de-spawn after demos.
    7. Click Host after setting the game options (and password if desired).
    8. Tell your friends to join the match via Hamachi + Rocket Plugin (see below for details).
    9. If they get a message saying that they could not connect to the host, make sure that you're using the same password for the match as your password for private matches or delete your private match password. See this post for details.
    10. In RLBotGUI, set Extra -> Existing Match Behaviour -> Continue And Spawn.
    11. Drag desired bots onto teams in RLBotGUI.
    12. Don't worry about adding Human players in RLBotGUI. Human players can simply join ingame.
    13. Click Start Match in RLBotGUI. Expect the bots to join the teams.

    The setup is basically the same as playing custom maps. If the instructions above are not clear enough, see this video tutorial by Lethamyr.

    "},{"location":"miscellaneous/lan-setup/#instructions-for-clients","title":"Instructions for Clients","text":"

    Use the standard procedure for joining a LAN match via Rocket Plugin. You can find more detailed tutorials elsewhere, here's a short summary:

    1. Open Hamachi and join the host's network via the network ID they tell you.
    2. Right-click on the host and click \"Copy IPv4 Address\".
    3. Open Rocket League
    4. Open the Rocket Plugin menu with the \"Home\" key.
    5. Under the Multiplayer tab in the \"Join a local game\" section, paste the host's address into the IP Address field and click Join.
    6. The port can be left at its default of 7777.
    "},{"location":"miscellaneous/lan-setup/#option-2-online-splitscreen-steam-or-epic","title":"Option 2 - online splitscreen (Steam or Epic)","text":""},{"location":"miscellaneous/lan-setup/#requirements_1","title":"Requirements","text":"
    • Parsec
    "},{"location":"miscellaneous/lan-setup/#instructions-for-host_1","title":"Instructions for Host","text":"

    Only the host can loads bots into the game!

    1. Start Rocket League with RLBotGUI (launch a match, then quit the match to the lobby).
    2. Create a Parsec room and have your friends join
    3. Start new match with bots and players
    4. Have friends join appropriate team
    "},{"location":"miscellaneous/lan-setup/#instructions-for-clients_1","title":"Instructions for Clients","text":"
    1. Join Parsec room
    2. Press Start to join local Rocket League lobby
    3. Join appropriate team
    "},{"location":"miscellaneous/missing-pages/","title":"Missing pages","text":"

    The following wiki pages are not moved yet:

    • Deploying Changes (maybe this should stay on the github wiki?)
    • Remote RLBot (isn't this very outdated?)
    • Setup Instructions (current) (self-explanatory)
    "},{"location":"miscellaneous/rlbot-specific-game-settings/","title":"Rlbot specific game settings","text":"

    RLBot has the ability to change game settings only when RLBot is active. This can be useful when a different environment is desired for developing or running bots compared to playing the game yourself.

    This is achieved by briefly altering TASystemSettings.ini as RLBot starts up Rocket League. This feature is currently only available on windows, and for the default TASystemSettings.ini location of %USERPROFILE%\\Documents\\My Games\\Rocket League\\TAGame\\Config.

    To have settings that only apply when using RLBot, a TASystemSettings.RLBot.ini file has to be created in the same folder as TASystemSettings.ini. This file does not need to be a full copy of TASystemSettings.ini, but should only contain the differences with TASystemSettings.ini to improve compatibility with Rocket League updates. When RLBot starts up, the changes found in TASystemSettings.RLBot.ini will be temporarily applied to TASystemSettings.ini.

    The remainder of this page contains some example use cases.

    "},{"location":"miscellaneous/rlbot-specific-game-settings/#cap-the-in-game-fps-to-120-for-rlbot-uncap-the-fps-during-normal-play","title":"Cap the in game FPS to 120 for RLBot, uncap the FPS during normal play","text":"

    This is useful to create the most consistent environment for RLBot. See Tick Rate for more info.

    • The FPS will have to be uncapped during normal play. This is achieved by setting AllowPerFrameSleep=False in TASystemSettings.ini.
    • In the game pause screen, the fps cap has to be set to 120 exactly.
    • TASystemSettings.RLBot.ini should contain the following configuration to turn the FPS cap back on for RLBot:
    [SystemSettings]\nAllowPerFrameSleep=True\n
    "},{"location":"miscellaneous/rlbot-specific-game-settings/#other-useful-settings-for-bot-testing","title":"Other Useful Settings For Bot Testing","text":"

    in [SystemSettings]:

    • ResX=1280 (Change the x value of your resolution)
    • ResY=720 (Change the y value of your resolution)
    • Fullscreen=False (False for window mode, True for fullscreen)
    • Borderless=True (enable borderless for windowed mode aka Fullscreen=False)
    "},{"location":"miscellaneous/workshop-custom-maps/","title":"Workshop custom maps","text":""},{"location":"miscellaneous/workshop-custom-maps/#automated-solution","title":"Automated Solution","text":"

    RLBot has built in support for custom maps. It allows you to select a folder that has custom map (`*.upk) files anywhere in the directory. Once added, you can select any of the custom maps in the directory and play with bots on that map.

    "},{"location":"miscellaneous/workshop-custom-maps/#steps","title":"Steps","text":"
    1. Run RLBot. Add -> Load Folder and select a directory with custom maps
    2. In Match Settings, click on the \"Map\" dropdown and you should see all the *.upk files listed there.
    3. Select and press \"Start Match\"
    "},{"location":"miscellaneous/workshop-custom-maps/#manual-solution","title":"Manual Solution","text":"
    1. Find the workshop map you want to use. It will be located at \\Steam\\steamapps\\workshop\\content\\252950 Find the map you want inside one of those folders. The map has a .udk extension.

    2. Change the map name to Labs_Underpass_P.upk. Be sure to change the extension as well.

    3. Copy the map to C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole. It will replace the Underpass map.

    4. On RLBotGui select Underpass to play the custom map.

    "},{"location":"troubleshooting/antivirus-notes/","title":"Antivirus notes","text":"

    If RLBotGUI can't open, won't start a match, or acts in other strange ways it may be related to your antivirus software. Do not disable your antivirus.

    "},{"location":"troubleshooting/antivirus-notes/#if-you-suspect-your-antivirus-has-broken-rlbot","title":"If you suspect your antivirus has broken RLBot:","text":"
    1. Press Windows + R, and type in %localappdata%\\RLBotGUIX and then press Enter
    2. Delete the folders Python37 and venv
    3. Redownload RLBotGUI if necessary
    4. Create an exception for RLBotGUI in your antivirus software. The executable is located at C:\\Program Files\\RLBot
    5. Launch RLBotGUI

    You might also be having a problem with your firewall. Windows Defender Firewall has been known to wrongly block RLBotGUI.exe in the past. To fix this problem:

    1. Go to Control Panel
    2. System and Security
    3. Under Windows Defender Firewall, click \"Allow an app through Windows Firewall\"
    4. Click \"Change settings\" (In the top-left-ish)
    5. Click \"Allow another app\" (In the bottom-left-ish)
    6. Navigate to RLBotGUI and select it.
    7. Click \"Network types...\"
    8. Make sure that both Private and Public networks are checked
    9. Click \"OK\"
    10. Click \"Add\"
    11. Click \"OK\"

    You're done!

    "},{"location":"troubleshooting/installation-errors/","title":"Installation errors","text":""},{"location":"troubleshooting/installation-errors/#you-are-using-a-third-party-antivirus","title":"You are using a third-party antivirus","text":"

    RLBotGUI may open for a second before closing, it may install but fail to work, or produce other weird behavior. A list of known antivirus-related error messages is listed down below under Miscellaneous Issues

    1. Check out our other wiki page: Antivirus Notes
    "},{"location":"troubleshooting/installation-errors/#rlbotgui-gets-stuck-updatingcollecting-packages-during-installation","title":"RLBotGUI gets stuck updating/collecting packages during installation","text":"

    This usually happens because of:

    1. slow internet (try giving it 5 minutes)
    2. pip (python's package installer) broke

    If you've given it time and nothing's happened:

    1. Restart your computer and try again
    2. If that doesn't work, delete pip's cache folder located in %localappdata%/pip and try again
    "},{"location":"troubleshooting/installation-errors/#problems-starting-a-match","title":"Problems starting a match","text":"

    Check the console window for any error messages.

    "},{"location":"troubleshooting/installation-errors/#encountered-a-std-exception-listen","title":"Encountered a std Exception: listen","text":"

    Another program is preventing RLBot from talking to Rocket League.

    1. Restart your computer
    "},{"location":"troubleshooting/installation-errors/#encountered-a-std-exception-unknown-error","title":"Encountered a std Exception: Unknown Error","text":"

    A Bakkesmod plugin that you are using isn't compatible with RLBot.

    1. Disable Bakkesmod
    2. Restart Rocket League and RLBotGUI
    "},{"location":"troubleshooting/installation-errors/#the-game-is-open-but-no-match-started","title":"The game is open but no match started","text":"
    1. Ensure you started with Rocket League closed. RLBotGUI has to launch it for you
    2. Check for the above errors in the console
    3. Check your antivirus to ensure it didn't delete RLBot's files
    "},{"location":"troubleshooting/installation-errors/#the-game-doesnt-launch-and-theres-no-error-in-the-console","title":"The game doesn't launch and there's no error in the console","text":"
    1. Ensure you set RLBotGUI to launch from the correct (Steam/Epic) platform.
    "},{"location":"troubleshooting/installation-errors/#javalangruntimeexception-javaniocharsetmalformedinputexception-input-length-1","title":"java.lang.RuntimeException: java.nio.charset.MalformedInputException: Input length = 1","text":"

    This currently happens to people with strange letters/characters in their Steam username.

    1. Change your steam username
    "},{"location":"troubleshooting/installation-errors/#miscellaneous-issues","title":"Miscellaneous Issues","text":""},{"location":"troubleshooting/installation-errors/#common-antivirus-related-error-messages","title":"Common Antivirus-related error messages","text":"
    • FileNotFoundError [WinError 2]: The system cannot find the file specified
    • Please check that the file exists and your antivirus is not removing it
    • Windows: OSError: [WinError 1450] Insufficient system resources exist to complete the requested service
    • Encountered exception: [WinError 5] Access is denied
    • [WinError 225] Operation did not complete successfully because the file contains a virus or potentially unwanted software

    For all of the above:

    1. Check out our other wiki page for this issue: Antivirus Notes
    "},{"location":"troubleshooting/installation-errors/#cannot-proceed-because-vcruntime140dll-was-not-found","title":"Cannot proceed because VCRUNTIME140.dll was not found","text":"

    Your computer may be missing some important files, which you can download from here:

    • https://go.microsoft.com/fwlink/?LinkId=746572
    • https://go.microsoft.com/fwlink/?LinkId=746571
    "},{"location":"troubleshooting/installation-errors/#application-error-the-application-was-unable-to-start-correctly-0xc000007b","title":"Application Error: The application was unable to start correctly (0xc000007b).","text":"
    1. Restart your computer
    "},{"location":"troubleshooting/installation-errors/#frame-stuttering-when-using-rlbot","title":"Frame stuttering when using RLBot","text":"
    1. Restart your computer
    2. Close or disable DropBox if it is running
    "},{"location":"troubleshooting/installation-errors/#bot-development-issues","title":"Bot development Issues","text":""},{"location":"troubleshooting/installation-errors/#python-acting-super-weird","title":"Python Acting Super Weird","text":"

    Sometimes on Windows 10, ~\\AppData\\Local\\Microsoft\\WindowsApps will end up on your system path, which supplies a fake python.exe taking you to the Microsoft Store. This causes bizarre things to happen, e.g. nothing at all being printed when you run python --version.

    You can confirm whether this is happening to you by opening a command prompt and running where.exe like this:

    >where.exe python\nC:\\Users\\tareh\\AppData\\Local\\Microsoft\\WindowsApps\\python.exe\n

    If it shows the Microsoft\\WindowsApps\\python.exe one at the top, you need to fix it. You can try this

    "},{"location":"troubleshooting/installation-errors/#javalangunsatisfiedlinkerror-a-dynamic-link-library-dll-initialization-routine-failed","title":"java.lang.UnsatisfiedLinkError: A dynamic link library (DLL) initialization routine failed.","text":"
    1. Run your .bat files as administrator to get past this error.
    "},{"location":"troubleshooting/installation-errors/#could-not-locate-a-suitable-bot-class-in-module","title":"Could not locate a suitable bot class in module","text":"

    This means that your bot's python file was found, but there's something messed up in it.

    1. Ensure you saved the file
    2. Check to make sure your bot extends the framework's agent class
    "},{"location":"troubleshooting/installation-errors/#could-not-find-a-version-that-satisfies-the-requirement-pyqt5","title":"Could not find a version that satisfies the requirement PyQt5","text":"

    Your system might be using python 2 instead of python 3. This can happen even if you successfully installed python 3 and added it to your path. Verify whether this is the case by running python --version. If it says python 2, try these:

    1. Make sure you've installed python 3 and chosen \"Add to PATH\" during the installation.
    2. Open the windows \"environment variables\" dialog and make sure that python 3 is listed before python 2.
    "},{"location":"troubleshooting/installation-errors/#scratch-the-project-file-that-was-selected-failed-to-load","title":"Scratch: The project file that was selected failed to load.","text":"

    We're using Scratch 3.0 which is pre-release and a bit buggy. Sometimes the save gets corrupted. Here's how to avoid that, and recover your file if it does get corrupted:

    • If you save a vector in a variable then save your project, it will be broken.
    • If you somehow insert null values into a list then save your project, it will be broken.

    General strategy for recovering the file:

    1. Hit F12 in your browser to view the javascript console and read the error that appears when you try to upload the broken file. It will look something like this:
    gui {\"validationError\":\"Could not parse as a valid SB2 or SB3 project.\",\"sb2Errors\":[{\"keyword\":\"required\",\"dataPath\":\"\",\"schemaPath\":\"#/required\",\"params\":{\"missingProperty\":\"objName\"},\"message\":\"should have required property 'objName'\"}],\"sb3Errors\":[{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf/0/type\",\"params\":{\"type\":\"string\"},\"message\":\"should be string\"},{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf/1/type\",\"params\":{\"type\":\"number\"},\"message\":\"should be number\"},{\"keyword\":\"oneOf\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf\",\"params\":{\"passingSchemas\":null},\"message\":\"should match exactly one schema in oneOf\"},{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/oneOf/1/type\",\"params\":{\"type\":\"boolean\"},\"message\":\"should be boolean\"},{\"keyword\":\"oneOf\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/oneOf\",\"params\":{\"passingSchemas\":null},\"message\":\"should match exactly one schema in oneOf\"}]}\n
    1. Your sb3 is really a zip file, so unzip it and look inside project.json.
    2. Search for xWn5EppiH.9NKPVF and see if there's anything funky saved in it, and manually make a fix. For a list, you could delete the list items. For a variable, you could set it to \"\".
    3. Then put the fixed version of project.json back in the zip and try uploading again.
    "},{"location":"troubleshooting/installation-errors/#import-errors","title":"Import errors:","text":"

    If you run into an import error that works fine when testing outside of rlbot but crashes when loading your agent, it can most often be solved by simply moving the import statement to your agent's init method. This is helpful for libraries such as tensorflow and rlutilities

    "},{"location":"troubleshooting/installation-errors/#old-issues-that-are-probably-irrelevant","title":"Old issues that are probably irrelevant","text":""},{"location":"troubleshooting/installation-errors/#pip-is-not-recognized-as-an-internal-or-external-command","title":"'pip 'is not recognized as an internal or external command","text":"

    Something blocked RLBotGUI from installing Python on the first try, and you have to reinstall by following these steps:

    1. Press Windows + R, and type in %localappdata%\\RLBotGUIX and then press Enter
    2. Delete the folders Python37 and venv
    3. Relaunch RLBotGUI.exe
    "},{"location":"troubleshooting/installation-errors/#the-term-expand-archive-is-not-recognized-as-the-name-of-a-cmdlet","title":"The term 'Expand-Archive' is not recognized as the name of a cmdlet","text":"

    You are using an older version of Windows and must manually perform some of the installation with the following steps:

    1. Download our copy of Python from here
    2. Press Windows + R, type in %localappdata%\\RLBotGUIX and then press Enter
    3. Create a new folder called Python37 and open the folder
    4. Find the zip file of Python you downloaded and double click it
    5. Drag the contents from the zip file into the folder Python37
    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"RLBot","text":"

    Welcome to the RLBot wiki!

    "},{"location":"#getting-started","title":"Getting Started","text":"
    • Download RLBot
    • Botmaking Setup Guides
    "},{"location":"#video-tutorials","title":"Video tutorials","text":"
    • Setup/Python/GoslingUtils Tutorials by GooseFairy
    • C#/RedUtils tutorial by CodeRed
    • Java tutorial by Eastvillage
    • Python/VirxERLU Tutorials by VirxEC
    • Python video tutorials from Learn Code By Gaming
    • Language agnostic tutorial explaining useful concepts by b2studios
    "},{"location":"#language-specific-wikis","title":"Language-specific wikis","text":"
    • Officially supported languages
    • Other community supported languages
    • Machine Learning FAQ
    • RLGym
    "},{"location":"#text-tutorials","title":"Text tutorials","text":"
    • Shooting the ball towards or away from a target
    • Dodges (C#)
    • State systems (C#)
    "},{"location":"#commonly-used-resources","title":"Commonly Used Resources","text":"
    • GameTickPacket, FieldInfo, and Controllers
    • Useful Game Values (Field Size, Boost Pad Locations, and more)
    • Quickchats
    • Rendering
    • Dropshot and Related Information
    • Appearance Customization
    • Ball Prediction
    • The RLBotPack
    • Team Match Communication Protocol (TMCP)
    • Troubleshooting
    "},{"location":"#physics","title":"Physics","text":"
    • RocketSim by Zealan
    • Ball Physics by @Chip
    • Ball Collision by @Chip
    • Ground Car Control by @Chip
    • Aerial Car Control by @Chip
    • Inverse Aerial Car Control by @Chip
    • Aerial ball intercept/hit by @Chip
    • How Car and Ball Interact by @Chip
    • How to Analyze Drivable Paths by @Chip
    • The Physics Of Jumping by Impossibum
    • Extracting Map Meshes by Virx
    "},{"location":"#unofficial-but-helpful-code-repositories","title":"Unofficial but Helpful Code Repositories","text":"
    • Utilities by @Chip
    • GoslingUtils by GooseFairy
    • VirxERLU (aka GoslingUtils 2.0) by VirxEC
    • Source code to East's Java Tutorial
    • RedUtils by CodeRed
    "},{"location":"botmaking/ball-path-prediction/","title":"Ball path prediction","text":"

    When writing a bot, it's very useful to know where the ball will be a few seconds in the future. This is very challenging because the ball responds to gravity, drag, friction, spin, and bounces off of curvy walls. Fortunately, chip has your back. He did a meticulous study of the ball physics and built an extremely accurate model: https://samuelpmish.github.io/notes/RocketLeague/ball_bouncing/

    Note: this is just an estimate of what the ball will be doing in the future, it is not exact! It is recommended that you routinely update your predictions to have the most accurate estimates.

    The fruit of that labor is now available to your bot with a simple function! Just call the function and you get 6 seconds' worth of ball positions, each advancing 1/60 of a second into the future.

    "},{"location":"botmaking/ball-path-prediction/#language-specific-examples","title":"Language-specific examples","text":"

    (support for more languages coming soon):

    • Python
    • Java
    • C#
    "},{"location":"botmaking/bot-customization/","title":"Bot customization","text":""},{"location":"botmaking/bot-customization/#gui-customization","title":"GUI Customization","text":"

    The easiest way to customize your bot appearance is via RLBotGUI. To bring up the appearance editor, click on the bot info icon and then click Edit Appearance.

    Video guide

    You can use any item in the game, including painted items. The editor should have the latest items, but we have to manually update them. So if some recently added items are missing, please remind us on our discord. You can also click the bottom left buttons to preview your loadout in-game instantly!

    Tip: When previewing in-game and trying multiple loadouts, sometimes the camera will lose track of your car when it respawns. You can avoid this by cycling the camera with your mouse buttons instead of using the number keys. With this technique it should be possible to get into a camera mode like hard-attach and have it be stable as you look at different wheels, blue car vs orange car, etc.

    "},{"location":"botmaking/bot-customization/#manual-customization","title":"Manual Customization","text":"

    In your bot's config file you can set your bot's display name. You can have a name of max 31 characters. If your name is too long or there is duplicates that is handled in the framework.

    Example (bot.cfg file):

    [Locations]\n# Path to loadout config. Can use relative path from here.\nlooks_config = ./appearance.cfg\n\n# Path to python file. Can use relative path from here.\npython_file = ./python_example.py\n\n# Path to a file that can dynamically generate your bot's appearance. Optional.\nloadout_generator = example_loadout_generator.py\n\n# Name of the bot in-game\nname = PythonExampleBot\n\n# Optional: Location of a logo file to to show in RLBotGUI and tournament overlays. 400x300px preferred.\nlogo_file = ./logo.png\n

    The field looks_config should point to an appearance file. An appearance.cfg file could look like this:

    [Bot Loadout]\nteam_color_id = 27\ncustom_color_id = 75\ncar_id = 23\ndecal_id = 307\nwheels_id = 1656\nboost_id = 0\nantenna_id = 287\nhat_id = 0\npaint_finish_id = 1978\ncustom_finish_id = 1978\nengine_audio_id = 0\ntrails_id = 0\ngoal_explosion_id = 1971\nprimary_color_lookup = [50, 0, 200]\nsecondary_color_lookup = [100, 100, 250]\n\n[Bot Loadout Orange]\n# Same as above, except it applies to the orange car\n
    "},{"location":"botmaking/bot-customization/#item-ids","title":"Item IDs","text":"

    The GUI appearance editor uses a csv file generated by BakkesMod using the dumpitems command. You can see the most recently generated file here: https://github.com/RLBot/RLBotGUI/blob/master/rlbot_gui/gui/csv/items.csv

    To see the items, you might want to browse at: https://rocket-league.com/items/

    "},{"location":"botmaking/bot-customization/#colors","title":"Colors","text":"

    There are two ways to specify your colors:

    1. Use team_color_id and custom_color_id to index into the swatches (see images below).
    2. Use primary_color_lookup and secondary_color_lookup to choose a swatch closest to the RGB value you provide.

    In either case, you're limited to the same set of colors that can be selected in-game.

    NOTE: The shade of the colors may not be correspond exactly with following pictures.

    team_color_id are the primary color of the car. The top left color is index 0 increasing as you go right:

    custom_color_id is the secondary color, also called accent. These are identical for both teams:

    "},{"location":"botmaking/bot-customization/#painted-items","title":"Painted Items","text":"

    You can use a number based on this list:

    • 0 - None
    • 1 - Crimson
    • 2 - Lime
    • 3 - Black
    • 4 - Sky Blue
    • 5 - Cobalt
    • 6 - Burnt Sienna
    • 7 - Forest Green
    • 8 - Purple
    • 9 - Pink
    • 10 - Orange
    • 11 - Grey
    • 12 - Titanium White
    • 13 - Saffron

    These are set in your appearance cfg file. Example:

    [Bot Paint Blue]\ncar_paint_id = 12\ndecal_paint_id = 0\nwheels_paint_id = 7 \nboost_paint_id = 7\nantenna_paint_id = 0\nhat_paint_id = 0\ntrails_paint_id = 2\ngoal_explosion_paint_id = 0\n\n[Bot Paint Orange]\n...\n
    "},{"location":"botmaking/bot-customization/#loadout-generator","title":"Loadout Generator","text":"

    This is completely optional!

    Recently we added the ability to generate your bot's loadout with a python script. This lets you choose different loadouts based on player index, randomize parts of your loadout, etc. The script is executed at the beginning of every match.

    To use this feature, put a line like loadout_generator = loadout_generator_example.py in your bot cfg file, in the [Locations] section. Then create a python file like this:

    import random\nfrom pathlib import Path\n\nfrom rlbot.agents.base_loadout_generator import BaseLoadoutGenerator\nfrom rlbot.matchconfig.loadout_config import LoadoutConfig\n\n\nclass SampleLoadoutGenerator(BaseLoadoutGenerator):\n    def generate_loadout(self, player_index: int, team: int) -> LoadoutConfig:\n\n        # You could start with a loadout based on a cfg file in the same directory as this generator\n        loadout = self.load_cfg_file(Path('appearance.cfg'), team)\n\n        # Or you could start from scratch like this\n        # loadout = LoadoutConfig()\n\n        if player_index == 0:\n            loadout.antenna_id = 287  # use a Psyonix flag if you're the first player\n\n        loadout.team_color_id = player_index  # Different primary color depending on player index\n        loadout.paint_config.wheels_paint_id = random.choice([1, 2, 4, 5])  # Random wheel color\n\n        return loadout\n
    "},{"location":"botmaking/bot-customization/#bot-logos","title":"Bot Logos","text":"

    Either put a file called logo.png in the same folder as your bot cfg, OR specify logo_file = ... in your bot cfg in the same section as python_file. Dimensions of 400x300 px are preferred. It will appear in RLBotGUI, and maybe on stream!

    "},{"location":"botmaking/bot-customization/#need-inspiration","title":"Need inspiration?","text":"

    reddit.com/r/RLFashionAdvice

    "},{"location":"botmaking/config-file-documenation/","title":"Bot Config File","text":""},{"location":"botmaking/config-file-documenation/#sections","title":"Sections","text":""},{"location":"botmaking/config-file-documenation/#locations","title":"Locations","text":"

    This section is poorly named at this point, but oh well. It includes:

    • looks_config: The location of your bot's appearance config, relative to the cfg file.
    • python_file: The location of your bot's python file, relative to the cfg file.
    • logo_file: Optional. The location of an image that will represent your bot in RLBotGUI, tournament overlays, etc.
    • name: The name of your bot in-game.
    • supports_early_start: Optional. Indicates whether your bot can handle the early start system. Read below for details.
    • requirements_file: Optional. The location of a requirements.txt for your bot. If specified, RLBotGUI will use it to warn people if there's a missing dependency, and they'll have the option to install your requirements.txt file.
    • use_virtual_environment: Optional, defaults to False. Installs your bot's requirements from the requirements.txt file into a python venv so they're isolated from potentially conflicting requirements from other bots. See pr #535
    • loadout_generator: Optional. Location of a script that can influence your bot's appearance on startup for randomization / index-dependent changes. See loadout generator
    • requires_tkinter: Optional. Set it to true if your bot needs tkinter, and if the user is running a GUI which lacks tkinter, they will be warned.
    "},{"location":"botmaking/config-file-documenation/#bot-parameters","title":"Bot Parameters","text":"

    This is mainly for bot makers to add arbitrary config values useful to them. Generally the framework doesn't care what you put here, except in the case of Scratch bots.

    "},{"location":"botmaking/config-file-documenation/#details","title":"Details","text":"

    This section is for metadata about your bot which can be displayed to people in RLBotGUI, tournament overlays, etc. Common details included:

    • developer: The name of the developer(s) of the bot.
    • description: Textual description of the bot, its playstyle, how to use it, etc.
    • fun_fact: A short fun fact about the bot. Sometimes displayed on stream during tournaments.
    • github: A github link
    • language: Which language/technology the bots was made with
    • tags: A comma separated list of tags. Primarily used by the RLBotGUI to put the bot in the correct tabs. Common tags include: 1v1, teamplay, goalie, hoops, dropshot, snow-day, rumble, spike-rush, heatseeker, memebot
    "},{"location":"botmaking/config-file-documenation/#early-start-system","title":"Early Start System","text":"

    If a bot adds supports_early_start = True then it will be started up before the Rocket League match loads, which gives it lots of extra time. To live happily in this situation the bot MUST be able to deal with weird game tick packets, e.g.:

    • Could have unexpected bots / unexpected teams
    • The bot's index might be higher than the packet's num_cars
    • The packet may transition suddenly to a different set of cars, different game type, etc
    "},{"location":"botmaking/config-file-documenation/#match-config-file-rlbotcfg","title":"Match Config File (rlbot.cfg)","text":"

    This configuration controls which bots are in the game, what arena to play on, what mutators to use, etc. Example config

    "},{"location":"botmaking/config-file-documenation/#sections_1","title":"Sections","text":"
    • RLBot Configuration: Contains miscellaneous overall configurations
    • Team Configuration: Configurations at the team level
    • Match Configuration: Configurations for a specific match
    • Mutator Configuration: Mutators for a specific match
    • Participant Configuration: What participants are playing
    • Scripts: What scripts should be ran
    "},{"location":"botmaking/config-file-documenation/#rlbot-configuration","title":"RLBot Configuration","text":"
    • extensions_path: A path to the extension file used later on for extra game controlling needs
    • launcher_preference: 'steam' or 'epic'. For people who have the game on both, determines which launcher is preferred for opening Rocket League.
    "},{"location":"botmaking/config-file-documenation/#team-configuration","title":"Team Configuration","text":"

    NOTE: None of these take an effect currently

    • Team Blue Color: Changes Blue team color, use 0 to use default color
    • Team Blue Name: Changes the Team name to use instead of 'Blue'
    • Team Orange Color: Changes Blue team color, use 0 to use default color
    • Team Orange Name: Changes the Team name to use instead of 'Orange'
    "},{"location":"botmaking/config-file-documenation/#match-configuration","title":"Match Configuration","text":"
    • num_participants: The total number of cars that will be spawned into the match.
    • game_mode: 'Soccer', 'Hoops', 'Dropshot', 'Hockey', 'Rumble'
    • game_map, e.g. \"Mannfield\". All possible values
    • skip_replays: If True, replays are automatically skipped after a goal. However, also prevents match replays from being saved.
    • start_without_countdown: If True, skips kickoff countdown
    • existing_match_behavior: 'Restart If Different', 'Restart', 'Continue And Spawn'
    • enable_lockstep: If True, the framework will wait for outputs from all bots before advancing to the next frame.
    • enable_rendering: If True, bots' debug rendering is turned on at the start of a match (toggle it with page up/down).
    • enable_state_setting: If True, bots are allowed to manipulate the game state (useful during development).
    • auto_save_replay: If True, the match replay is automatically saved.
    "},{"location":"botmaking/config-file-documenation/#mutator-configuration","title":"Mutator Configuration","text":"

    All of these default to the \"normal\" value (the first in the list) if you don't specify them.

    • Match Length: Changes the length of the match. '5 Minutes', '10 Minutes', '20 Minutes', 'Unlimited'
    • Max Score: Changes the number of goals needed to win. 'Unlimited', '1 Goal', '3 Goals', '5 Goals'
    • Game Speed: 'Default', 'Slo-Mo', 'Time Warp'
    • Overtime: 'Unlimited', '+5 Max, First Score', '+5 Max, Random Team'
    • Ball Max Speed: 'Default', 'Slow', 'Fast', 'Super Fast'
    • Ball Type: 'Default', 'Cube', 'Puck' or 'Basketball'
    • Ball Weight: 'Default', 'Super Light', 'Light' or 'Heavy'
    • Ball Size: 'Default', 'Small', 'Large', 'Gigantic'
    • Ball Bounciness: 'Default', 'Low', 'High', 'Super High'
    • Boost Amount: 'Default', 'Unlimited', 'Recharge (Slow)', 'Recharge (Fast)' or 'No Boost'
    • Rumble: 'None', 'Default', 'Slow', 'Civilized', 'Destruction Derby', 'Spring Loaded', 'Spikes Only' or 'Spike Rush'
    • Boost Strength: '1x', '1.5x', '2x', '10x'
    • Gravity: 'Default', 'Low', 'High' or 'Super High'
    • Demolish: 'Default', 'Disabled', 'Friendly Fire', 'On Contact' or 'On Contact (FF)'
    • Respawn Time: '3 Seconds', '2 Seconds', '1 Second', 'Disable Goal Reset'
    "},{"location":"botmaking/config-file-documenation/#participant-configuration","title":"Participant Configuration","text":"
    • participant_config_NUMBER: The path to a participant configuration
    • participant_team_NUMBER: what team the bot is on
    • participant_type_NUMBER: the type of the bot Accepted values are \"human\", \"rlbot\", \"psyonix\", \"party_member_bot\", and \"controller_passthrough\", You can have up to 4 local humans and they must be activated in game or it will crash. If no player is specified you will be spawned in as spectator!
    • human - not controlled by the framework (but must appear before bot entries)
    • rlbot - controlled by the framework
    • psyonix - default bots (skill level can be changed with participant_bot_skill
    • party_member_bot - controlled by an rlbot but the game detects it as a human
    • controller_passthrough - controlled by a human but runs through the framework
    • participant_bot_skill_NUMBER: 0.0 is Rookie, 0.5 is pro, 1.0 is all-star
    • participant_loadout_config_NUMBER: the path to the loadout. This overrides the agent config if not None

    Example contents:

    participant_config_0 = my_folder/my_bot.cfg\nparticipant_config_1 = my_folder/other_bot.cfg\n\nparticipant_team_0 = 0\nparticipant_team_1 = 1\n\nparticipant_type_0 = rlbot\nparticipant_type_1 = rlbot\n\nparticipant_bot_skill_0 = 1.0\nparticipant_bot_skill_1 = 1.0\n
    "},{"location":"botmaking/config-file-documenation/#scripts","title":"Scripts","text":"

    This field is optional, by default no scripts will be ran.

    • script_config_NUMBER: The path to the script configuration

    Example contents:

    script_config_0 = src/test/python/agents/script/sample_script.cfg\nscript_config_1 = src/test/python/agents/script/sample_script.cfg\n
    "},{"location":"botmaking/dropshot/","title":"Dropshot","text":"

    As of August 19. 2018 the RLBot framework officially supports Dropshot with access to locations and states of floor tiles. This page contains information and useful values related to the Dropshot game mode.

    To make RLBot start a Dropshot game you have to set the following values in rlbot.cfg:

    game_mode = Dropshot\ngame_map = DropShot_Core707\n
    "},{"location":"botmaking/dropshot/#tiles","title":"Tiles","text":"

    There are 140 tiles in total. Locations and owning team can be found in the agent's FieldInfo as GoalInfo objects. In Python self.get_field_info().goals will be a list of the floor tiles with following attributes:

    GoalInfo: {\n  'team_num': int,\n  'location': Vector3,\n  'direction': Vector3,\n}\n

    Example: To access the location of tile 0 in Python, write: self.get_field_info().goals[0].location

    A list of all locations can be found here.

    To access the state of tile 0 in Python, write: packet.dropshot_tiles[0].tile_state. This is an integer which corresponds to:

    • 0: Unknown
    • 1: Filled
    • 2: Damaged
    • 3: Open

    The tiles will be sorted the same way in FieldInfo and GameTickPacket so indices match.

    The tiles are hexagonal in shape. The distance between centres is 768 uu (except for the middle where the distance from blue tiles to orange tiles is 256 uu. A neutral strip about 128 uu wide covers the tiles partially). The image below shows the relative dimensions of a Dropshot tile.

    "},{"location":"botmaking/dropshot/#arena","title":"Arena","text":"

    The tiles are layed out in rows of 7,8,9,10,11,12,13 |middle| 13,12,11,10,9,8,7. Where tile 0 is in the blue corner (back left if you are on blue team) and tile 139 is in an orange corner (back left if you are on the orange team).

    The overall layout of the arena and tile indices can be seen below.

    The arena is a regular hexagon except its rounded corners. Here are some dimensions:

    • Center: (0, 0)
    • Floor level: 3.2 uu
    • Center to wall: 4555 uu
    • Center to corner: 5026 uu
    • Center to corner (without rounding walls): 5259.66 uu
    • Wall length: about 5026 uu
    • Arena height: 1986 uu

    Note that the tiles on the boundaries are not complete - the rounded base of the walls overlaps the tiles to varying degrees (approximately 30-40% of the tile is overlapped, and the tile centrepoints are always visible).

    You may notice that tiles' locations are at z=0, but floor level is z=3.2. This is because the tiles have a thickness.

    "},{"location":"botmaking/dropshot/#within-arena-script","title":"Within arena script","text":"

    Here's a small script to check if a point is within the arena:

    def is_within_arena(point):\n    HEIGHT = 1986\n    TO_WALL = 4555\n    TO_CORNER = 5260  # 4555 / math.sin(60)\n\n    if point.z < 0 or HEIGHT < point.z:\n        return False\n\n    ax = abs(point.x)\n    ay = abs(point.y)\n\n    if TO_CORNER < ax or TO_WALL < ay:\n        return False\n\n    return TO_WALL * TO_CORNER - TO_WALL * ax - 0.5 * TO_CORNER * ay >= 0;\n
    "},{"location":"botmaking/dropshot/#ball","title":"Ball","text":"

    Ball radius: 102.24 uu

    The GameTickPacket contains Dropshot info about the ball. It can be found in the DropshotBallInfo object at packet.game_ball.drop_shot_info which contains the variables: absorbed_force, damage_index, and force_accum_recent.

    The ball has three phases. The current phase is the variable damage_index where:

    • 0: Normal
    • 1: Charged
    • 2: Super Charged

    The ball gains charge as it is hit by cars. When a car exerts a force on the ball, the ball charges up equal to the magnitude of the force (energy). The ball enters the next phase when it reaches a certain threshold:

    • Charged: 2500 energy
    • Super Charged: 11000 energy

    The current amount of energy (force absorded) is the absorbed_force variable.

    However, a hit does not always charge the ball. To make the ball charge up, the impact must be at least 500 energy, otherwise the ball will not charge at all. Furthermore, when the ball gets hit, it will temporarily accept less energy. The variable force_accum_recent stores the accumulated absorbed force (energy), but no more than 2500 energy. It decays over time at a rate of 2500 energy per second, and the ball will at most absorb 2500 - force_accum_recent energy on a hit. Combined, this prevents players from charging the ball too quickly, limited to 2500 energy every second.

    Example: if you hit the ball with an impact of 2000 uu/s at t=0, and you hit the ball again with a force of 2000 uu/s at t=0.5, the force_accum_recent has decayed by 1250 and will be 750 when you hit the ball the second time, and therefore the ball will not accept more than 1750 energy, which means 250 energy gets lost.

    The ball's charge is reset, whenever it damages a floor tile owned by the opponent of whoever last touched the ball. To make damage the ball must hit the tile with a velocity of 250 uu/s or more perpendicular to the surface of contact. The side of a tile can only be hit if there's an open tile next to it, so usually the ball will hit the top of the tiles, and in those cases only the Z velocity matters, and must be 250 uu/s or more to make damage. There is also must have passed 0.2 seconds since the last time the ball damaged a tile.

    You can tell which team last hit the ball by checking the packet.game_ball.latest_touch object. See Input and output for more.

    At kickoff the ball is launched straight up into the air with a velocity of 1000 uu/s and reaches a height of about 847 uu in 1.54 seconds.

    "},{"location":"botmaking/dropshot/#spawning","title":"Spawning","text":"

    You always spawn with 100 boost.

    Kickoff spawn locations are similar to soccer spawn locations, but not identical. In dropshot spawn locations are:

    Kickoff Blue Orange Right corner loc: (-1867, -2379), yaw: 0.25 pi loc: (1867, 2379), yaw: -0.75 pi Left corner loc: (1867, -2379), yaw: 0.75 pi loc: (-1867, 2379), yaw: -0.25 pi Back right loc: (-256.0, -3576), yaw: 0.5 pi loc: (256.0, 3576), yaw: -0.5 pi Back left loc: (256.0, -3576), yaw: 0.5 pi loc: (-256.0, 3576), yaw: -0.5 pi Far back center loc: (0.0, -4088), yaw: 0.5 pi loc: (0.0, 4088), yaw: -0.5 pi Demolished Blue Orange Right corner loc: (-2176, -3408), yaw: 0.5 pi loc: (2176, 3408), yaw: -0.5 pi Left corner loc: (2176, -3408), yaw: 0.5 pi loc: (-2176, 3408), yaw: -0.5 pi"},{"location":"botmaking/dropshot/#boost-regeneration","title":"Boost regeneration","text":"

    In Dropshot you regenerate boost at a rate of about 10 boost/sec. However, you do not regen boost while boosting. When you stop boosting (or run out of boost), there is a delay of about 0.5 second before you start gaining boost again. If you are at 0 boost and boost button is pressed, the timer will reset every 0.5 seconds until the button is released.

    "},{"location":"botmaking/hoops/","title":"Hoops","text":"

    The RLBot framework support the Hoops game mode. This page contains useful values specifically about Hoops.

    To make RLBot start a Hoops game you have to set the following values in rlbot.cfg:

    game_mode = Hoops\ngame_map = Hoops_DunkHouse\n
    "},{"location":"botmaking/hoops/#arena","title":"Arena","text":"

    Hoops is always played on the map Dunk House. The dimensions for the arena are:

    • Floor: z=0
    • Side wall: x=2966.67
    • Back wall: y=3586
    • Ceiling: z=????
    "},{"location":"botmaking/hoops/#goals","title":"Goals","text":"

    In Hoops the goals are two rings. The rings are placed ??? uu above the ground. Their radius is 753 uu but they are connected to the wall with straight lines.

    Center of goals: ??? Distance from back wall: ???

    "},{"location":"botmaking/hoops/#boost-pads","title":"Boost Pads","text":"

    Locations of all boost pads:

    ????\n
    "},{"location":"botmaking/hoops/#ball","title":"Ball","text":"

    The radius of the ball is 98.38 uu. But other than that, the physics of the ball is similar to soccer.

    "},{"location":"botmaking/hoops/#spawning","title":"Spawning","text":"Kickoff Blue Orange Right corner loc: ???, yaw: 0.25 pi loc: ??? yaw: -0.75 pi Left corner loc: ???, yaw: 0.75 pi loc: ???, yaw: -0.25 pi Back right loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Back left loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Far back center loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Demolished Blue Orange Right corner loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi Left corner loc: ???, yaw: 0.5 pi loc: ???, yaw: -0.5 pi"},{"location":"botmaking/input-and-output-data/","title":"Input and Output Data (current)","text":"

    All supported languages have access to the same data, though syntax and conventions will vary. It is controlled by this specification: rlbot.fbs

    Language-specific guides:

    • Python
    • Java
    • C#
    • Rust
    • Nim
    "},{"location":"botmaking/jumping-physics/","title":"The Physics Of Jumping","text":"

    There are several forces that can be acting on a Rocket League car at any moment and understanding their influence is an important step towards giving your bot accurate and dependable utilities. This section will be focused on the mechanics of jumping and how these forces interact to allow you to accurately simulate a jump and provide useful information such as how high your bot can reach and at what time they'll get there. So let's get started by first declaring these \"forces\" I've been referring to thus far.

    "},{"location":"botmaking/jumping-physics/#gravity","title":"Gravity","text":"

    Under normal circumstances, gravity functions much like you'd expect. It constantly applies a force downwards towards the floor. By default, the force is 650 uu/s^2 but that's not a given. Luckily the current gravity value is supplied within the GameTickPacket (GameTickPacket.game_info.world_gravity_z) passed to your bot's get_output() every frame.

    "},{"location":"botmaking/jumping-physics/#sticky-force","title":"Sticky Force","text":"

    This force is responsible for the magnet-like effect pulling your wheels to walls and other surfaces. This force unlike gravity is applied in the relative down direction pushing the car's wheels towards a surface in the immediate vicinity with the force of 325 uu/s^2. This effect only persists for a short time after jumping thankfully and is no longer a consideration after 3 frames in the air after a jump. This results in a force of 8.125 ((1/120) * 3 * 325) being negated from jumps.

    "},{"location":"botmaking/jumping-physics/#jump-impulse","title":"Jump Impulse","text":"

    The instantaneous force applied in the relative up direction (towards your car's ceiling) of 292 when the jump button is first pressed. This force is the same for the first jump as well as the second jump without a flip.

    "},{"location":"botmaking/jumping-physics/#jump-hold-bonus","title":"Jump Hold Bonus","text":"

    This is the upwards velocity bonus granted for holding down the jump button on the first jump. It can grant a total additional 292 force in the relative upwards direction over 0.2s. Holding jump longer than 0.2s grants no additional bonus. A minimum of 3 ticks of jump bonus is applied to the first jump resulting in an additional 36.5 ((1/120) * 3 * 1460) force over the first 3 frames of a jump.

    "},{"location":"botmaking/jumping-physics/#throttle-acceleration","title":"Throttle Acceleration","text":"

    Believe it or not, throttle still has an effect on your car even while airborne. Forward throttle while airborne exerts a force of 66.667 uu/s^2 in your car's relative forward direction. Reverse throttle's effect is halved with a force of 33.334 uu/s^2 in the relative rear direction.

    "},{"location":"botmaking/jumping-physics/#implementing-a-jump-simulation","title":"Implementing A Jump Simulation","text":"

    The following code snippet provides an implementation of a jump simulation naively assuming the bot is perfectly flat on the ground with no initial velocity, gravity is at default settings and the bot executes a frame-perfect jump sequence.

    def naive_double_jump_simulation(time_allowed: float) -> list:\n    gravity = -650\n    jump_impulse = 292\n    time_increment = 1 / 120\n    sticky_force = -325\n    sticky_timer = time_increment * 3\n    hold_bonus_increment = (292 * 5) * time_increment\n    max_hold_time = 0.2\n    simulated_z_velocity = 0\n    simulated_height = 17.01  # default sitting height of octane\n    simulation_time = 0\n    double_jumped = False\n    jump_slices = []\n\n    while simulation_time < time_allowed:\n        if simulation_time == 0:\n            simulated_z_velocity += jump_impulse\n\n        elif simulation_time > max_hold_time + time_increment and not double_jumped:\n            simulated_z_velocity += jump_impulse\n            double_jumped = True\n\n        if simulation_time < max_hold_time:\n            simulated_z_velocity += hold_bonus_increment\n\n        if simulation_time < sticky_timer:\n            simulated_z_velocity += sticky_force * time_increment\n\n        simulated_z_velocity += gravity * time_increment\n        simulated_height += simulated_z_velocity * time_increment\n        simulation_time += time_increment\n        jump_slices.append(simulated_height)\n\n    return jump_slices\n

    Calling naive_doublejump_simulation(2.0) will return a list showing the simulated height of the car at every increment from 0 to 2 seconds into the future. A more robust solution should account for more variability in circumstances such as the car's current relative up direction as well as current velocity.

    "},{"location":"botmaking/jumping-physics/#useful-considerations-for-implementing-jumping-simulations-and-mechanics","title":"Useful Considerations For Implementing Jumping Simulations And Mechanics","text":"
    • The second jump remains viable for between 1.25 and 1.45 seconds with the potential 0.2s time extension provided by holding the first jump for the maximum bonus duration.
    • The maximum speed of a car in Rocket League is 2300. Any forces applied that would result in a magnitude exceeding 2300 will be applied as per usual but then normalized back down to the limit of 2300.

    Note: Rocket League's physics engine runs at 120hz so all calculations provided are based on that number as the base of a time step (1/120).

    "},{"location":"botmaking/machine-learning-faq/","title":"Machine learning faq","text":"

    A: There are a lot of helpful resources pinned to the ml-discussion channel of the RLBot discord.

    Q: I'm new to RLBot, how do I get started with ML?

    A: We strongly recommend you begin by writing a hard-coded bot to get the hang of RLBot, and coding for Rocket League. Once you feel confident, check out the dedicated #machine-learning channel in the RLBot discord for helpful resources!

    Q: What can I use ML for in Rocket League?

    A: Lots of things! Optimizing mechanics (wave-dashing, aerials, power-sliding, etc), analyzing replays (predicting shot percentages, car positions, etc), and even playing the game.

    Q: How could I use the replays available at calculated.gg?

    A: Tools like Training Data Extractor and carball exist to format replay data into an RLBot tick packet, and approximate player inputs between frames. These enable users to easily handle data available in replays for whatever purpose they might have.

    Q: Is it possible to get controls from replays so I can train a model to copy humans?:

    A: Training controls directly from replays has not been very successful.

    The reason for this may be that not all conditions the bot will encounter are present in replays, leading to a model being unable to handle certain conditions that were not present in the replays it was trained with.

    The most successful attempt is documented here.

    Q: Can I make a clone of Rocket League for training and then transfer it to the real game?

    A: It would be quite the project to clone Rocket League, but there is no reason that would not work with a little elbow grease!

    The user @Roboserg#9216 has been working on a Rocket League clone for some time, and has made very promising progress. His work is open source, and can be found here.

    Q: Can I use Supervised Learning to train a bot that mimics other bots?

    A: Yes you can! The ML bots Levi and Tensorbot were trained this way.

    Q: Can I use Reinforcement Learning to make a bot?

    A: This is the holy grail for many ML enthusiasts in the RLBot community.

    With the recent release of the Python library and Bakkesmod plugin RLGym, Reinforcement Learning can now be used to train models directly in the game. Some promising results have already been achieved, like Rhobot and Element. These models take quite a lot of compute power and time to train, but they are achievable with consumer-grade hardware. The largest RLGym project is currently a distributed learning bot Necto/Nexto.

    Reinforcement Learning can also be used to train specific mechanics, like Eagle and ElementAerial

    Q: Can I use this or that method to speed up Reinforcement Learning?

    A: You can just try it out, if it works for other problems, then it might also work for Rocket League. Don't hesitate to ask in the discord if you want a second opinion.

    "},{"location":"botmaking/manipulating-game-state/","title":"Manipulating game state","text":""},{"location":"botmaking/manipulating-game-state/#overview","title":"Overview","text":"

    We have a feature that lets you set exact positions, velocities, etc. for the ball and cars. You may be familiar with BakkesMod, this is very similar. It won't be enabled during tournaments, but it's very useful when building and debugging your bot.

    "},{"location":"botmaking/manipulating-game-state/#possibilities","title":"Possibilities","text":"
    • Set up a specific scenario for your bot to try over and over. Better than custom training, because:
    • You have control over car orientation, velocity, angular velocity, and boost amount
    • You can do it in the middle of an exhibition match with opponents
    • You can control it all from inside your bot code
    • Build training sets for machine learning
    • Record snapshots during a game and \"rewind\" if you encounter a natural situation you want to iterate on
    • Hover your car in midair while you work on your orientation code
    • Build wacky physics rules to change the game, e.g. making the ball bounce off invisible walls, accelerate in a certain direction, etc
    "},{"location":"botmaking/manipulating-game-state/#language-specific-documentation","title":"Language-specific documentation","text":"
    • Python
    • Java
    • C#
    "},{"location":"botmaking/matchcomms/","title":"Matchcomms","text":""},{"location":"botmaking/matchcomms/#matchcomms-allows-communication-between-participants-in-a-match","title":"Matchcomms allows communication between participants in a match.","text":"

    Use cases:

    • Telling your teammate where you intend to go
    • Setting parameters on bots in a training exercise
    • Bootstrapping a more efficient form of communication

    Currently only broadcasting to all participants is supported.

    "},{"location":"botmaking/matchcomms/#architecture","title":"Architecture","text":""},{"location":"botmaking/matchcomms/#examples","title":"Examples","text":"

    Python example for reading and replying to messages in a bot.

    Example training exercise which sets parameters on the bot

    "},{"location":"botmaking/matchcomms/#tmcp","title":"TMCP","text":"

    TMCP stands for the Team Match Communication Protocol. It is an attempt at standardizing inter-bot communication via the match comms system.

    See this wiki page for implementation details.

    "},{"location":"botmaking/matchcomms/#supported-languages","title":"Supported Languages","text":"
    • Python has strong support, as described above
    • Java bots will receive args like --matchcomms-url ws://localhost:53970 when starting up. No library support yet for creating / managing the connection.
    • C# bots will receive args like --matchcomms-url ws://localhost:53970 when starting up. No library support yet for creating / managing the connection.
    "},{"location":"botmaking/quickchat/","title":"Quickchat","text":""},{"location":"botmaking/quickchat/#overview","title":"Overview","text":"

    You can make your bot send quickchat! We support sending all standard quickchats, and also some custom ones! You can find the full list here.

    It's now possible to read quick chat too, assuming the framework for your chosen language has added support. You'll be able to read the chat log regardless of what language send the message. Messages sent on the team-only channel will be hidden from opponents appropriately.

    Using quick chat is a little different in each language, see the specific links below.

    "},{"location":"botmaking/quickchat/#language-specific-documentation","title":"Language-specific documentation","text":"
    • Python
    • Java
    • C#

    Other languages support quickchat, we just don't have wikis yet.

    "},{"location":"botmaking/rendering/","title":"Rendering","text":"

    An incredibly useful new addition to RLBot v4 is the rendering feature. It allows you to draw objects on screen, which can make debugging and testing your bot so much easier. For example, you could draw the predicted ball path, or draw where the bot wants to go.

    Rendering in other languages: Java, C#

    "},{"location":"botmaking/rendering/#enablingdisabling-of-rendering","title":"Enabling/disabling of rendering","text":"

    When installing the RLBotGUI, rendering will be disabled by default. You can turn it on by clicking 'Extra' and ticking 'Enable Rendering' in the GUI. However, rendering can also be enabled or disabled any time using the page up and page down keys, respectively. So if your rendering isn't appearing, make sure to press page up before panicking.

    "},{"location":"botmaking/rendering/#the-basics","title":"The basics","text":"

    The renderer object is built into the BaseAgent class, so you don't need to import anything other than the BaseAgent. Each time you want to render something, you start with self.renderer.begin_rendering() and end with self.renderer.end_rendering(). The rendering code goes in between the begin_rendering() and end_rendering(). Let's take a look at an example:

    class RenderingTutorial(BaseAgent):\n    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:\n        controller = SimpleControllerState()\n\n        self.renderer.begin_rendering()\n        self.renderer.draw_rect_2d(20, 20, 200, 200, True, self.renderer.black())\n        self.renderer.end_rendering()\n\n        return controller\n

    We can see here that every get_output call, the on-screen drawings get updated. In this example, the draw_rect_2d method is used. Let's go over all the methods you can use:

    (Note: The argument names aren't exactly what appear in the framework itself, but the argument positions are the same)

    "},{"location":"botmaking/rendering/#rendering-a-large-amount","title":"Rendering a large amount","text":"

    There are a few limits you can hit when rendering:

    • MessageLargerThanMax
    • Not sending message to Rocket League because that would bring the bytes sent since last receive to...

    You can bypass the MessageLargerThanMax one by using multiple render groups. Example:

    self.renderer.begin_rendering('my_big_render')\nfor i in range(0, 200):\n    self.renderer.draw_rect_3d(...)\nself.renderer.end_rendering()\n\nself.renderer.begin_rendering('my_big_render_part_2')\nfor i in range(200, 400):\n    self.renderer.draw_rect_3d(...)\nself.renderer.end_rendering()\n

    If you hit the other limit, you're out of luck.

    "},{"location":"botmaking/rendering/#renderercreate_color-and-other-colors","title":"renderer.create_color and other colors","text":"
    create_color(a, r, g, b)\n
    • a, r, g, b - Alpha, red, green, blue. From 0 to 255.

    This doesn't draw anything on screen, but it is used for creating colors that you can use for the other methods that draw on screen. The renderer also has a list of color methods that gives you the most common colors:

    renderer.black()\nrenderer.white()\nrenderer.gray()\nrenderer.blue()\nrenderer.red()\nrenderer.green()\nrenderer.lime()\nrenderer.yellow()\nrenderer.orange()\nrenderer.cyan()\nrenderer.pink()\nrenderer.purple()\nrenderer.teal()\n

    Lastly, there's the team_color method. Using this your bot renders with different colors depending on which team it is on.

    team_color(team=None, alt_color=False)\n
    • team - (Optional, None by default) Index of a team (0 for blue, 1 for orange) or None. If set to None, it will use calling bot's team.
    • alt_color - (Optional, False by default) Wether or not to return the alternate team color instead. If set to False, this method returns blue for blue team and orange for orange team. If set to True, this method returns cyan for blue team and red for orange team.
    "},{"location":"botmaking/rendering/#rendererdraw_rect_2d","title":"renderer.draw_rect_2d","text":"

    This draws a rectangle on screen. Example : draw_rect_2d(20, 20, 200, 200, True, self.renderer.black())

    draw_rect_2d(x, y, width, height, fill, color)\n
    • x, y - The top left x and y screen coordinates for the rectangle. (0, 0) is the top left of the screen.
    • width, height - The width and height of the rectangle.
    • fill - If True, the entire rectangle is filled with color, else it is just an outline of color.
    • color - The color of the rectangle. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_2d","title":"renderer.draw_line_2d","text":"

    NOTE: Currently not supported.

    Draws a 2D line flat on the screen.

    draw_line_2d(start_x, start_y, end_x, end_y)\n
    • start_x, start_y - Where the line starts. (0, 0) is the top left of the screen.
    • end_x, end_y - Where the line ends.
    "},{"location":"botmaking/rendering/#rendererdraw_string_2d","title":"renderer.draw_string_2d","text":"

    Draws 2D text flat on the screen. Example : draw_string_2d(20, 20, 3, 3, ball_text, self.renderer.black()) example

    draw_string_2d(x, y, scale_x, scale_y, text, color)\n
    • x, y - The top left x and y screen coordinates for the string. (0, 0) is the top left of the screen.
    • scale_x, scale_y - The horizontal and vertical scale of the text.
    • text - The text to render.
    • color - The color of the string. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_rect_3d","title":"renderer.draw_rect_3d","text":"

    Draws a 2D rectangle in game's 3D space. Size does not change with distance.

    draw_rect_3d(location, width, height, fill, color)\n
    • location - The 3D game location where the rectangle should be drawn. Must be a Python list or a tuple (cannot be a ctypes or flatbuffers type).
    • width, height - The width and height of the rectangle.
    • fill - If True, the entire rectangle is filled with color, else it is just an outline of color.
    • color - The color of the rectangle. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_string_3d","title":"renderer.draw_string_3d","text":"

    Draws 2D text in game's 3D space. Size does not change with distance.

    draw_string_3d(location, scale_x, scale_y, text, color)\n
    • location - The 3D game location where the text should be drawn. Must be a Python list or a tuple (cannot be a ctypes or flatbuffers type).
    • scale_x, scale_y - The horizontal and vertical scale of the text.
    • text - The text to render.
    • color - The color of the text. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_3d","title":"renderer.draw_line_3d","text":"

    Draws a 2D line in game's 3D space. Size does not change with distance.

    draw_line_3d(start, end, color)\n
    • start, end - The starting and ending 3D game locations of the line. Must be Python lists or tuples (cannot be ctypes or flatbuffers types).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_line_2d_3d","title":"renderer.draw_line_2d_3d","text":"

    NOTE: Currently not supported.

    Draws a 2D line which starts at screen coordinates and ends at the game's 3D coordinate.

    draw_line_2d_3d(start_2d_x, start_2d_y, end_3d, color)\n
    • start_2d_x, start_2d_y - Where the line starts (on the screen).
    • end_3d - Where the line ends (in 3D space). Must be a Python list or tuple (cannot be a ctypes or flatbuffers type).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_polyline_2d","title":"renderer.draw_polyline_2d","text":"

    NOTE: Currently not supported.

    Draws multiple connected 2D lines flat on the screen. Useful for rendering paths or pictures.

    draw_polyline_2d(locations, color)\n
    • locations - A list of 2D points. A line will be drawn from first point to the second point, and from second point to the third point, ect. (0, 0) is the top left of the screen.
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/rendering/#rendererdraw_polyline_3d","title":"renderer.draw_polyline_3d","text":"

    Draws multiple connected lines in the game's 3D space. Useful for rendering paths. Size does not change with distance.

    draw_polyline_3d(locations, color)\n
    • locations - A list of 3D locations. A line will be drawn from first location to the second location, and from second location to the third location, ect. Each location must be a Python list or tuple (cannot be a ctypes or flatbuffers type).
    • color - The color of the line. See renderer.create_color.
    "},{"location":"botmaking/scripts/","title":"Scripts","text":"

    Sometimes it can be useful to have access to game values, debug rendering or state setting while not being a bot playing within the match. The framework has an easy solution for that - scripts.

    Scripts are very similiar to normal bots. They need a config file and a python executable. The config file can be loaded by RLBotGUI like a normal bot - to enable it, just click the checkbox next to its name. The script will be automatically started and terminated by the framework.

    Example config:

    [Locations]\nscript_file = ./my_script.py\nname = My Script\n\n[Details]\ndescription = Example script\nlanguage = python\n

    Example my_script.py:

    import time\n\nfrom rlbot.agents.base_script import BaseScript\nfrom rlbot.utils.game_state_util import GameState\n\n\n# Extending the BaseScript class is purely optional. It's just convenient / abstracts you away from\n# some strange classes like GameInterface\nclass MyScript(BaseScript):\n    def __init__(self):\n        super().__init__(\"My Script\")\n\n    def run(self):\n        # state setting\n        self.set_game_state(GameState(console_commands=[\"Stat FPS\"]))\n\n        while True:\n            time.sleep(0.5)\n\n            # updating packet\n            packet = self.get_game_tick_packet()\n\n            # rendering\n            color = self.renderer.white()\n            text = f\"seconds_elapsed : {packet.game_info.seconds_elapsed}\"\n            self.game_interface.renderer.begin_rendering()\n            self.game_interface.renderer.draw_string_2d(20, 200, 2, 2, text, color)\n            self.game_interface.renderer.end_rendering()\n\n\n# You can use this __name__ == '__main__' thing to ensure that the script doesn't start accidentally if you\n# merely reference its module from somewhere\nif __name__ == \"__main__\":\n    script = MyScript()\n    script.run()\n

    This script will render some text on the screen every 0.5 seconds.

    If you want your loop to be run every tick, you might want to use a blocking call instead of time.sleep like this:

    while True:\n   packet = self.wait_game_tick_packet()\n   ...\n

    For all available methods in the BaseScript class and their descriptions, see its implementation here.

    Another fully functional script example

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/","title":"Shooting the ball towards or away from a target","text":""},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#this-tutorial-is-not-language-specific","title":"This tutorial is NOT language-specific!","text":"

    This tutorial is based on the systems used by VirxERLU which is a fork of GoslingUtils.

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#toc","title":"TOC","text":"
    • This tutorial is NOT language-specific!
    • TOC
    • Targets and anti-targets
    • Direction of approach
    • Ball location offset
    • Aligning with the direction of approach
    • Driving
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#targets-and-anti-targets","title":"Targets and anti-targets","text":"

    Firstly, a target is something that we want to hit the ball towards, and an anti-target is something that we want to hit the ball away from.

    • Targets: This will be a list of two vectors. The first vector will be the left-most target, and the second will be the right-most target.
    • Anti-targets: This is the same as targets, but you swap the left-most and right-most targets before giving them to the algorithm, and all the following code stays the same! This causes the algorithm to shoot the ball anywhere but between the two targets.

    We're using two points instead of just one, central point that represents the target because just one point is unrealistic and restricts our options. Two points, however, gives us a range to work with and some room for error.

    Useful game values

    For example, our left-most target vector could be [800, 5213, 321.3875] (orange's left goal post) and our right-most target vector could be [-800, 5213, 321.3875] (orange's right goal post). These values have been adjusted to account for the ball's radius (which is 92.75).

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#direction-of-approach","title":"Direction of approach","text":"

    Now we need to find the direction that we need to hit the ball in. It wouldn't be fun if we ended up hitting the ball away from our target!

    In order to do this, we need the following information:

    • Left-most target
    • Right-most target
    • Ball location
    • Car location

    Let's get started!

    Vector car_to_ball = ball_location - car_location\nVector car_to_ball_direction = normalize(car_to_ball)\n\nVector ball_to_left_target_direction = normalize(left_target_location - ball_location)\nVector ball_to_right_target_direction = normalize(right_target_location - ball_location)\n

    These are a bunch of directions, and they're fairly well described just by the variable names. You will have to implement your own normalize function, but here's the math behind it if you didn't know. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!

    Next, we need some way to change car_to_ball_direction so that it's between ball_to_left_target_direction and ball_to_right_target_direction. That's what the following function clamp2D does.

    Vector clamp2D(Vector direction, Vector start, Vector end) {\n    bool is_right = dotProduct(direction, crossProduct(end, [0, 0, -1])) < 0\n    bool is_left = dotProduct(direction, crossProduct(start, [0, 0, -1])) > 0\n\n    if ((dotProduct(end, crossProduct(start, [0, 0, -1])) > 0) ? (is_right && is_left) : (is_right || is_left))\n        return direction\n\n    if (dotProduct(start, direction) < dotProduct(end, direction))\n        return end\n\n    return start\n}\n

    You will also have to implement your own dotProduct and crossProduct functions. See here to learn how to find the dot product of two vectors and see here to learn how to find the cross product of two vectors. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!

    • Similar to integer clamping, clamp2D forces a direction between start and end, such that start \\< direction \\< end in terms of clockwise rotation.
    • Note that this is only in the x-axis and y-axis - clamping the z-axis isn't necessary for this problem.
    • For the math nerds: Why does this work? This function relies on Rocket League's inverted X-axis (positive X is left and negative X is right). See this page for a top-down view of the Rocket League field and different coordinates pertaining to the field.

    Now we can use the clamp2D function.

    Vector direction_of_approach = clamp2D(car_to_ball_direction, ball_to_left_target_direction, ball_to_right_target_direction)\n

    This is the direction that our bot should approach the ball at.

    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#ball-location-offset","title":"Ball location offset","text":"

    Next, we're going to take the ball's radius as well as our direction of approach into account in order to offset our final target from the ball's location.

    The basis behind this is that we will go in the opposite direction of our direction of approach, and give the direction a magnitude of 92.75 (which is the ball's radius).

    Vector offset_ball_location = ball_location - (direction_of_approach * 92.75)\n
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#aligning-with-the-direction-of-approach","title":"Aligning with the direction of approach","text":"

    This is where the math gets into approximations. What we need to do is cause the car to slowly circle around offset_ball_location until our direction to the ball matches or is close to direction_of_approach while also getting closer and closer to the target.

    int side_of_approach_direction = sign(dotProduct(crossProduct(direction_of_approach, [0, 0, 1]), ball_location - car_location))\nVector car_to_ball_perpendicular = normalize(crossProduct(car_to_ball, [0, 0, side_of_approach_direction]))\nVector adjustment = abs(angle(flatten(car_to_ball), flatten(direction_of_approach))) * 2560\nVector final_target = offset_ball_location + (car_to_ball_perpendicular * adjustment)\n
    • You will need to implement your own sign. This returns -1 if the value is negative, 0 if the value is 0, and 1 if the value is positive.
    • Most languages have their own abs (absolute value) function built-in. See here to learn what absolute value is.
    • You will also need to implement your own flatten and angle functions. Flatten makes the z value of a vector equal to 0. See here to learn how to find the angle between two vectors. Many example bots, including the ones for Python and Java, already have vector classes that have implemented this for you!
    "},{"location":"botmaking/shooting-the-ball-towards-or-away-from-a-target/#driving","title":"Driving","text":"

    Once you have final_target, all you have to do is face it and drive towards it. It will automatically adjust itself as your bot starts moving.

    If you want to get to the target at a specific time - for example, if you're using the ball prediction - then you need the required speed in order to get to the target at that exact time. This is fairly simple, as we just need to find the distance that we need to travel and divide by the remaining time.

    double distance_remaining = magnitude(final_target - car_location) // an ESTIMATION of how far we need to drive - this might be spot-on or fairly far off\ndouble time_remaining = intercept_time - current_time\n\ndouble speed_required = distance_remaining / time_remaining\n

    This also has another benefit: you can easily know whether or not it's possible to reach the target in a given time. If the required speed is greater than 1410 (which is the max speed of a car without boost) or 2300 (if the car does have boost) then it's impossible to reach the target in the given time.

    "},{"location":"botmaking/team-match-communication-protocol/","title":"TMCP","text":""},{"location":"botmaking/team-match-communication-protocol/#about","title":"About","text":"

    TMCP stands for the Team Match Communication Protocol. It is an attempt at standardizing inter-bot communication.

    Currently, the match communication system, or match comms, is only supported by Python bots. See Matchcomms for more information on how to use it.

    Match comms do not allow for team-only messages. Until this is implemented, TMCP operates on an honor system: a bot should not look at packets from bots on another team.

    "},{"location":"botmaking/team-match-communication-protocol/#sending-packets","title":"Sending packets","text":"

    Bots should avoid spamming packets. They should aim for a maximum of 10 packets per second.

    Only send a packet when something has changed. If you want to refine a time estimate sent in a previous message, only do so if the time difference is > 0.1 seconds.

    "},{"location":"botmaking/team-match-communication-protocol/#receiving-packets","title":"Receiving packets","text":"

    Packets will only be received when something has changed. If you haven't received a packet from another bot, assume that nothing has changed.

    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-10","title":"TMCP 1.0","text":"

    This is what a packet following TMCP looks like:

    {\n  \"tmcp_version\": [1, 0],\n  \"team\": int,\n  \"index\": int,\n  \"action\": {\n    \"type\": string,\n    ...\n  }\n}\n
    • tmcp_version

    • Major: Breaking revision number

    • Minor: Non-breaking revision number

    • team - The team of the bot that sent the packet. 0 for blue and 1 for orange. This will be removed once match comms allow for team-only communication.

    • index - The index of the bot that sent the packet. If you are using the hivemind, make this the index of the bot which is carrying out the action.

    • action - The current action that the bot is taking. This is an object. The types can be seen below.

    "},{"location":"botmaking/team-match-communication-protocol/#ball","title":"\"BALL\"","text":"

    The bot is going for the ball.

    {\n  \"type\": \"BALL\",\n  \"time\": float,\n  \"direction\": [float, float, float] \n}\n
    • time - Game time that your bot will arrive at the ball. Set to -1 if this is unknown.
    • direction - Anticipated normalized direction of ball travel AFTER contact is made. [0, 0, 0] for unknown.
    "},{"location":"botmaking/team-match-communication-protocol/#boost","title":"\"BOOST\"","text":"

    The bot is going for boost.

    {\n  \"type\": \"BOOST\",\n  \"target\": int\n}\n
    • target - Index of the boost pad the bot is going to collect.
    "},{"location":"botmaking/team-match-communication-protocol/#demo","title":"\"DEMO\"","text":"

    The bot is going to demolish another car.

    {\n  \"type\": \"DEMO\",\n  \"time\": float,\n  \"target\": int\n}\n
    • time - Game time that the bot will demo the other bot. -1 for unknown.
    • target - Index of the bot that will be demoed.
    "},{"location":"botmaking/team-match-communication-protocol/#ready","title":"\"READY\"","text":"

    The bot is waiting for a chance to go for the ball. Some examples are positioning (retreating/shadowing) and recovering.

    {\n  \"type\": \"READY\",\n  \"time\": float\n}\n
    • time - The game time when the bot could arrive at the ball (if it was to go for it). -1 for unknown.
    "},{"location":"botmaking/team-match-communication-protocol/#defend","title":"\"DEFEND\"","text":"

    The bot is in a position to defend the goal and is not planning to move up. Only use DEFEND if your bot is in place to defend, not if still en-route. If the bot decides to leave the net, signal this using either \"BALL\" (if going for a touch) or \"READY\" (if moving upfield).

    A bot should use \"DEFEND\" to let its teammates know it is safe to move up a bit without worrying about an open net.

    {\n  \"type\": \"DEFEND\"\n}\n
    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-implementations","title":"TMCP Implementations","text":""},{"location":"botmaking/team-match-communication-protocol/#virxerlu","title":"VirxERLU","text":"

    If you use VirxERLU, your bot automatically sends out TMCP packets. To process incoming ones, add this to your bot in main.py:

    def handle_tmcp_packet(self, packet):\n    super().handle_tmcp_packet(packet)\n    # process the packet here\n

    However, you will have to implement your own 'minimum time to ball' function. This is the default:

    def get_minimum_game_time_to_ball(self):\n    return -1\n

    It should return -1 if you can't find a shot and the game time of the shot if you could. It should be noted that all shots (except for short_shot) have a property called intercept_time which is the game time that they will intercept the ball at.

    "},{"location":"botmaking/team-match-communication-protocol/#tmcp-handler","title":"TMCP Handler","text":"

    Will made a TMCP python package with helper classes that handle everything protocol-related.

    To install, just do

    pip install tmcp\n

    Then you can use it like this:

    from tmcp import TMCPHandler, TMCPMessage, ActionType\n\nclass MyBot(BaseAgent):\n    def initialize_agent(self):\n        self.tmcp_handler = TMCPHandler(self)\n\n    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:\n        # Receive and parse all new matchcomms messages into TMCPMessage objects.\n        new_messages: List[TMCPMessage] = self.tmcp_handler.recv()\n        # Handle TMCPMessages.\n        for message in new_messages:\n            if message.action_type == ActionType.BALL:\n                print(message.time)\n\n        ...\n\n        # You can send messages like this.\n        self.tmcp_handler.send_boost_action(pad_index)\n\n        # Or you can create them and send them more directly:\n        my_message = TMCPMessage.ball_action(self.team, self.index, estimated_time_of_arrival)\n        self.tmcp_handler.send(my_message)\n
    "},{"location":"botmaking/team-match-communication-protocol/#tgdsmells-handler","title":"TGDSMELLS Handler","text":"

    The TGDSMELLS Handler is very similar in usage to Will's TMCP Handler.

    Can be installed with

    pip install tgdsmells\n
    "},{"location":"botmaking/team-match-communication-protocol/#under-the-hood","title":"Under the hood","text":"

    The following example shows how you could send and receive match comms without a handler. This is shown to give you a better idea of what's going on under the hood. We do still recommend that you use an existing handler instead because it will be up to date and do a lot of error checking for you.

    from queue import Empty\n\nclass MyBot(BaseAgent):\n    def initialize_agent(self):\n        self.ally_actions = {}\n\n    def receive_coms(self):\n        # Process up to 50 messages per tick.\n        for _ in range(50):\n            try:\n                # Grab a message from the queue.\n                msg = self.matchcomms.incoming_broadcast.get_nowait()\n            except Empty:\n                break\n\n            # This message either isn't following the standard protocol\n            # or is intended for the other team.\n            # DO NOT spy on the other team for information!\n            if \"tmcp_version\" not in msg or msg[\"team\"] != self.team:\n                continue\n\n            # Will's handler checks to make sure the message is valid.\n            # Here we are keeping it as simple as possible.\n\n            # If we made it here we know it's information relevant to our team.\n            # Let's save it in a dictionary for reference later.\n            self.ally_actions[msg[\"index\"]] = msg\n\n    def send_coms(self):\n        # Let's assume that our bot is attacking the ball and aiming for prediction slice 100.\n        outgoing_msg = {\n            \"tmcp_version\": [1, 0],\n            \"team\": self.team,\n            \"index\": self.index,\n            \"action\": {\n                \"type\": \"BALL\",\n                # You'll likely have the ball predictions cached locally.\n                # This implementation is for demonstration purposes only.\n                \"time\": self.get_ball_prediction_struct().slices[100].game_seconds,\n                \"direction\": [0, 0, 0]\n            },\n        }\n        self.matchcomms.outgoing_broadcast.put_nowait(outgoing_msg)\n\n    def get_output(self, packet: GameTickPacket):\n        # Get the latest information from matchcomms.\n        self.receive_coms()\n\n        # Your bot code goes here:\n        ...\n\n        # Ideally you only send out communications when your plans change.\n        # Sending 120 messages a second is just overkill and will eat into the processing time of your allies.\n        # Please take proper precautions to prevent excessive spam.\n        if new_plan != old_plan:\n            self.send_coms()\n\n        return self.controls\n
    "},{"location":"botmaking/tick-rate/","title":"Tick rate","text":"

    Bots have a function like get_output(packet) or something similar, depending on language. This gets called some number of times per second, I will refer to this as the tick rate.

    There are several factors which influence tick rate:

    1. The frame rate of Rocket League. If Rocket League is running at 60 FPS, the tick rate will get capped at 60, regardless of any other settings. Note that enabled VSync also limits FPS.
    2. The desired tick rate that you've configured for your bot. Most languages allow you to add an additional cap.
    3. The tick rate can never be higher than 120, since this is the rate at which Rocket League simulates its physics.

    In other words, the tick rate is min(rocketLeagueFPS, desiredTickRate). You can see the tick rate you're getting during a game by hitting the 'home' key and looking for a line like ticks: 120.0 tps

    There used to be another factor, the PacketSendRate configuration. There's a file at C:\\Users\\yourname\\Documents\\My Games\\Rocket League\\TAGame\\Config\\TARLBot.ini where you could write down a PacketSendRate, but RLBot now ignores it and sets 240 no matter what, so it's a non-issue.

    "},{"location":"botmaking/tick-rate/#specifying-desired-tick-rate","title":"Specifying desired tick rate","text":""},{"location":"botmaking/tick-rate/#python","title":"Python","text":"

    In python, you can update your bot cfg file as seen in this example

    Python will assume your desired tick rate is 60 unless you override it. This is because TARLBot.ini is 60 by default, so the vast majority of bot makers have been developing and testing with 60.

    "},{"location":"botmaking/tick-rate/#java","title":"Java","text":"

    In Java, you can configure your bot manager as seen in this example

    Java will assume your desired tick rate is 60 unless you override it. This is for the same reason as Python, and also because Java was hard-coded to use 60 for a long time.

    "},{"location":"botmaking/tick-rate/#net-c","title":".NET / C#","text":"

    In .NET, you can configure your bot manager as seen in this example

    Here, 0 means that you wish to have your desired tick rate be unlimited. You may also pass numbers like 60 or 120.

    "},{"location":"botmaking/tick-rate/#tips","title":"Tips","text":"
    • You should probably specify a tick rate that divides into 120. Tournaments generally run at 120Hz or 60Hz, and if you specify something weird like 100Hz, your bot will get called at varying intervals to achieve that average.
    • In most languages, your choice of tick rate will not affect the 'freshness' of packets delivered. They should all be very fresh, about 1ms old, when they are delivered to you.
    • If your bot is slow to compute a frame, you will fall behind and potentially miss a frame, since bots generally loop on a single thread. If you desire consistency, you may wish to configure a desiredTickRate that always gives enough time for your bot logic.
    • To consistently give bots the same amount of execution time for every tick, rocket leagues fps should be locked to exactly the tick rate that you want the bots to run at. This is especially important if there are many bots running, for example in a tournament.
    • It is possible to lock the FPS when RLBot is active, and unlock it when you're just playing normally. See the RLBot Specific Game Settings page for instructions on how to do this.
    "},{"location":"botmaking/useful-game-values/","title":"Useful game values","text":"

    If you are making a bot, some of these values are given in FieldInfo. You can find more information on that here.

    Rocket League is made in Unreal Engine, which means any dimensions will be in unreal units (uu).

    "},{"location":"botmaking/useful-game-values/#basic-dimensions","title":"Basic Dimensions","text":"

    WARNING: Note that the X-axis is left and it is not the normal Cartesian layout. Also, yaw is zero at the positive x-axis and increases clockwise. Trig functions work out as usual because the two reversed conventions cancel each other.

    Rotations are represented as YZX-ordered Euler angles.

    Note: For scratch divide the values by 32.

    Rocket League uses a coordinate system (X, Y, Z), where Z is upwards. Note also that negative Y is towards Blue's goal (team 0).

    • Floor: 0
    • Center field: (0, 0)
    • Side wall: x=\u00b14096
    • Side wall length: 7936
    • Back wall: y=\u00b15120
    • Back wall length: 5888
    • Ceiling: z=2044
    • Goal height: z=642.775
    • Goal center-to-post: 892.755
    • Goal depth: 880
    • Corner wall length: 1629.174
    • The corner planes intersect the axes at \u00b18064 at a 45 degrees angle

    For wall lengths, the curvature at the intersections is ignored.

    "},{"location":"botmaking/useful-game-values/#boost-pads","title":"Boost Pads","text":"

    Small boost pads:

    • Hitbox is a cylinder, height of 165uu, radius of 144uu
    • 28 in total.
    • Gives 12 boost.
    • Takes 4 seconds to refresh.

    Big boost pads:

    • Hitbox is a cylinder, height of 168uu, radius of 208uu
    • 6 in total.
    • Gives 100 boost.
    • Takes 10 seconds to refresh.
    • The pads with a z-component of 73.0 are the big pads. Mirror these coordinates to get all 6:
    • Midfield: (3584, 0)
    • Corner: (3072, 4096)

    A car picks up a boost pad if the car's center of mass (not hitbox) enters the pad's hitbox. This interaction is different when cars are standing still (see the Rocket Science video on boost pad hitboxes)

    The coordinates of the 34 boost pads (in the order that RLBot uses):

    [    0.0, -4240.0, 70.0] (0)\n[-1792.0, -4184.0, 70.0] (1)\n[ 1792.0, -4184.0, 70.0] (2)\n[-3072.0, -4096.0, 73.0] (3)\n[ 3072.0, -4096.0, 73.0] (4)\n[- 940.0, -3308.0, 70.0] (5)\n[  940.0, -3308.0, 70.0] (6)\n[    0.0, -2816.0, 70.0] (7)\n[-3584.0, -2484.0, 70.0] (8)\n[ 3584.0, -2484.0, 70.0] (9)\n[-1788.0, -2300.0, 70.0] (10)\n[ 1788.0, -2300.0, 70.0] (11)\n[-2048.0, -1036.0, 70.0] (12)\n[    0.0, -1024.0, 70.0] (13)\n[ 2048.0, -1036.0, 70.0] (14)\n[-3584.0,     0.0, 73.0] (15)\n[-1024.0,     0.0, 70.0] (16)\n[ 1024.0,     0.0, 70.0] (17)\n[ 3584.0,     0.0, 73.0] (18)\n[-2048.0,  1036.0, 70.0] (19)\n[    0.0,  1024.0, 70.0] (20)\n[ 2048.0,  1036.0, 70.0] (21)\n[-1788.0,  2300.0, 70.0] (22)\n[ 1788.0,  2300.0, 70.0] (23)\n[-3584.0,  2484.0, 70.0] (24)\n[ 3584.0,  2484.0, 70.0] (25)\n[    0.0,  2816.0, 70.0] (26)\n[- 940.0,  3308.0, 70.0] (27)\n[  940.0,  3308.0, 70.0] (28)\n[-3072.0,  4096.0, 73.0] (29)\n[ 3072.0,  4096.0, 73.0] (30)\n[-1792.0,  4184.0, 70.0] (31)\n[ 1792.0,  4184.0, 70.0] (32)\n[    0.0,  4240.0, 70.0] (33)\n

    NOTE: Some boost pad locations vary from map to map. It is recommended to use the FieldInfo, if you want to have the correct locations for any map.

    "},{"location":"botmaking/useful-game-values/#spawn-locations","title":"Spawn Locations","text":"Kickoff Blue Orange Right corner loc: (-2048, -2560), yaw: 0.25 pi loc: (2048, 2560), yaw: -0.75 pi Left corner loc: (2048, -2560), yaw: 0.75 pi loc: (-2048, 2560), yaw: -0.25 pi Back right loc: (-256.0, -3840), yaw: 0.5 pi loc: (256.0, 3840), yaw: -0.5 pi Back left loc: (256.0, -3840), yaw: 0.5 pi loc: (-256.0, 3840), yaw: -0.5 pi Far back center loc: (0.0, -4608), yaw: 0.5 pi loc: (0.0, 4608), yaw: -0.5 pi Demolished Blue Orange Right inside loc: (-2304, -4608), yaw: 0.5 pi loc: (2304, 4608), yaw: -0.5 pi Right outside loc: (-2688, -4608), yaw: 0.5 pi loc: (2688, 4608), yaw: -0.5 pi Left inside loc: (2304, -4608), yaw: 0.5 pi loc: (-2304, 4608), yaw: -0.5 pi Left outside loc: (2688, -4608), yaw: 0.5 pi loc: (-2688, 4608), yaw: -0.5 pi"},{"location":"botmaking/useful-game-values/#elevation-of-objects-at-rest","title":"Elevation of Objects at Rest:","text":"
    • Ball: 93.15
    • Hybrid: 17.00
    • Octane: 17.01
    • Dominus: 17.05
    • Breakout: 18.33
    • Batmobile/Plank: 18.65

    (these may vary slightly)

    More information on car bodies in this spreadsheet by HalfwayDead.

    "},{"location":"botmaking/useful-game-values/#physics","title":"Physics","text":"

    Conversion: 1 uu = 1 cm (e.g. 2778 uu/s = 100 km/h)

    • Gravity: 650 uu/s^2
    • \"Low\" mutator: 325 uu/s^2
    • \"High\" mutator: 1137.5 uu/s^2
    • \"Super High\" mutator: 3250 uu/s^2
    "},{"location":"botmaking/useful-game-values/#ball","title":"Ball","text":"
    • Radius: 91.25 uu
    • Max speed: 6000 uu/s
    • \"Slow\" mutator: 1500 uu/s
    • \"Fast\" mutator: 9000 uu/s
    • \"Super Fast\" mutator: 15000 uu/s
    • Mass: 30.0 (unit is arbitrary)
    • Coefficient of restitution: 60% (it loses 40% of the component of its velocity that's toward the surface)
    • Maximum ball angular velocity: 6.0 radians/s
    "},{"location":"botmaking/useful-game-values/#car","title":"Car","text":"
    • Max car speed (boosting): 2300 uu/s
    • Supersonic speed threshold: 2200 uu/s
    • Max driving speed (forward and backward) with no boost: 1410 uu/s
    • Car mass: 180.0 (unit is arbitrary)
    • Boost consumption rate: 33.3/s
    • Boost acceleration:
    • on the ground: 991.666 uu/s^2
    • in the air: 1058.333 uu/s^2
    • Acceleration in the ground:
    • due to throttle: depends on velocity - https://samuelpmish.github.io/notes/RocketLeague/ground_control/#throttle
    • due to braking (any amount): -3500.0 uu/s^2
    • due to slowing during zero-throttle coasting: -525.0 uu/s^2
    • Acceleration in the air due to throttle: ~66.667 uu/s^2 (yes, throttling accelerates the car in the air)
    • Jumping
    • Double jump
    • An instantaneous velocity increase of ~291.667 uu/s in the direction of your roof.
    • Minimum and maximum rotation (in radians):
    • Pitch: [-pi/2, pi/2]
    • Yaw: [-pi, pi]
    • Roll: [-pi, pi]
    • Maximum car angular acceleration:
    • Yaw: 9.11 radians/s^2
    • Pitch: 12.46 radians/s^2
    • Roll: 38.34 radians/s^2
    • Maximum car angular velocity: 5.5 radians/s
    • Turning
    • Turning in Rocket League is very complex and not a lot is known. Hopefully, the numbers below can help you out a bit!
    • Turn radius: https://samuelpmish.github.io/notes/RocketLeague/ground_control/#turning. Python implementation:
    def turn_radius(v):\n    if v == 0:\n        return 0\n    return 1.0 / curvature(v)\n\n# v is the magnitude of the velocity in the car's forward direction\ndef curvature(v):\n    if 0.0 <= v < 500.0:\n        return 0.006900 - 5.84e-6 * v\n    if 500.0 <= v < 1000.0:\n        return 0.005610 - 3.26e-6 * v\n    if 1000.0 <= v < 1500.0:\n        return 0.004300 - 1.95e-6 * v\n    if 1500.0 <= v < 1750.0:\n        return 0.003025 - 1.1e-6 * v\n    if 1750.0 <= v < 2500.0:\n        return 0.001800 - 4e-7 * v\n\n    return 0.0\n
    • No matter if you're accelerating or decelerating, (as the throttle is 1) the car's turn radius and velocity balance out so the car turns 90 degrees in about 0.775 seconds, 180 degrees in 1.55 seconds, and 360 degrees in 3.1 seconds.
    • Accelerating while turning (starting from a standstill with throttle and steer set to 1)
    • While turning with steer set to 1 (or -1), the maximum forwards velocity the car can reach is around 1234. It reaches this after 5 seconds.

    • The speed of the car after x time can be estimated with the following equation: 1234 * (1 - e ^ [-{time / 0.74704}])

      Example Python implementation:

    import math\n\nVMAX = 1234\nTAU = 0.74704\n\ndef get_speed_from_time_turning(time):\n    return VMAX * (1 - math.exp(-(time / TAU)))\n\ndef get_turn_time_from_speed(speed):\n    speed_adj = -(speed / VMAX - 1)\n    return -math.log(speed_adj, math.e) * TAU\n
    • Decelerating while turning (starting from the top speed with throttle and steer set to 1)
    • While turning with steer set to 1 (or -1), the minimum forward velocity the car can reach is around 1234. It reaches this after 7.5 seconds.

    • The speed and time can both be estimated with linear piecewise functions. The blue lines is the real velocity, and the orange line is the velocity that is predicted by the piecewise.

      Example Python implementation:

    def get_speed_from_time_turning(time):\n    if time >= 7.5:\n        return 1234\n\n    if time >= 4.5:\n        return 1272.889 - 5.185 * time\n\n    if time >= 4:\n        return 1380 - 27.5 * time\n\n    if time >= 3.2:\n        return 1530 - 65 * time\n\n    if time >= 2.6:\n        return 1743.333 - 131.667 * time\n\n    if time >= 1.3:\n        return 2247 - 325.384615 * time\n\n    if time >= 0.3:\n        return 2344 - 400 * time\n\n    if time >= 0.1:\n        return 2323 - 330 * time\n\n    if time > 0:\n        return 2300 - 100 * time\n\n    return 2300\n\ndef get_time_turning_from_speed(speed):\n    if speed <= 1234:\n        return 7.5\n\n    if speed <= 1248:\n        return 245.4857 - 0.192857 * speed\n\n    if speed <= 1270:\n        return 50.18 - 0.03636 * speed\n\n    if speed <= 1322:\n        return 23.53846 - 0.01538 * speed\n\n    if speed <= 1401:\n        return 13.24 - 0.007595 * speed\n\n    if speed <= 1824:\n        return 6.9 - 0.00307 * speed\n\n    if speed <= 2224:\n        return 5.86 - 0.0025 * speed\n\n    if speed <= 2290:\n        return 7.039 - 0.00303 * speed\n\n    if speed <= 2300:\n        return 23 - 0.01 * speed\n\n    return 0\n
    "},{"location":"community/air-show/","title":"Air show","text":""},{"location":"community/air-show/#summary","title":"Summary","text":"

    Rocket League, Music, and Programming: It all comes together in the 2021 Rocket League Air Show, hosted by Rocket Sledge!

    The best bot choreography presentation will win $1000! Open to both team and solo entries. The bar has been set high by the original video in February 2020. What will you do to rise above the rest and earn the viewers' votes?

    "},{"location":"community/air-show/#dates","title":"Dates","text":"

    February 15th: Check-in and progress report with Sledge. At this time we may be able to indicate how many spots are available for the video and even confirmation of your entry (based on quality and progress).

    March 15th: Full Submission due.

    Video: Youtube

    "},{"location":"community/air-show/#getting-started","title":"Getting Started","text":"

    Tutorial: Youtube

    You can chat / get help / form teams in the special air show discord channel.

    "},{"location":"community/air-show/#previous-years-submissions","title":"Previous year's submissions","text":"

    The code from last year's entries is open source!

    "},{"location":"community/air-show/#2020","title":"2020","text":"
    • Scripted
    • _Fool_
    • Awakening

    You shouldn't lift entire scenes, but feel free to borrow code and concepts.

    "},{"location":"community/air-show/#getting-help","title":"Getting Help","text":"
    • Ask questions on the RLBot #air-show chat room
    • We've heard interest from a few video editing experts, you might be able to team up! Check in the chat room.
    • The folks at the Rocket League Mapmaking Discord might want to collaborate if you have a cool idea.
    • You can watch the teams from previous years talking shop about what worked and what didn't:

    2020: https://www.youtube.com/watch?v=4oMdXBO9I3A 2021: TBA

    "},{"location":"community/air-show/#rules","title":"Rules","text":"

    You may enter solo or as a team.

    In order to win, you must be one of Sledge's personal picks to include in the showcase video on his channel, and then within that group, you must get the most votes from viewers via a google form, similar to the one from last year.

    All music must be sourced from Epidemic Sound ONLY. You can create a month long trial account and download your music here: https://www.epidemicsound.com/subscriptions/choose/. Music outside of this service will not be permitted even if it is \u201ccopyright free\u201d. Epidemic sound has an amazing search filter and every genre of music. It is the same music service used by almost every major RL Youtuber.

    Participation or inclusion in the video is not guaranteed at this point. Quality is important, refer to the original video as an example of what we are looking for. The first goal is to have a basic idea in progress by the February 15th check in date.

    No part of your entry may be shared or posted until Sledge's showcase video has been live for at least 2 weeks. Going forward you are also agreeing that Sledge may use parts of your entry in future videos and promotions. Also you entry will most likely be stolen and posted to tiktok multiple times... welcome to the internet!

    Please save test replay files and bloopers for possible inclusion in secondary video.

    You are welcome to use \"state setting\" to teleport cars / make them move unnaturally. Some viewers last year loved stuff like that, some thought it was cheap, up to you how you want to chase those votes.

    Also fine to use custom maps / any other mods.

    "},{"location":"community/air-show/#prizes","title":"Prizes","text":"
    • 1st = $1000
    • 2nd = TBD
    • 3rd = TBD
    "},{"location":"community/community-guidelines/","title":"Community guidelines","text":""},{"location":"community/community-guidelines/#social-conduct","title":"Social Conduct","text":"
    • No harassment
    • Be inclusive (no racism, sexism, etc)
    • Keep everything safe-for-work
    "},{"location":"community/community-guidelines/#discord","title":"Discord","text":"

    Most communication happens on our discord

    "},{"location":"community/community-guidelines/#code-of-conduct-for-mods","title":"Code of conduct for mods","text":"
    • Protect people from harassment and spam using the minimum required force.
    • De-escalate conflicts, and don't engage in tense arguments.
    • Employ yes-and whenever possible.
    • No power-tripping, no undue influence over people's projects. Be a servant.
    "},{"location":"community/community-guidelines/#roles","title":"Roles","text":"

    Discord users can be assigned roles, which is useful for granting privileges to different groups of people, contacting them all at once, etc.

    "},{"location":"community/community-guidelines/#tournament-roles","title":"Tournament Roles","text":"

    Roles are awarded based on your placement in the latest official tournament. The current roles are Champion, Top 4, Top 8, and Top 16. These roles are permenant, however only the ones from the latest tournament will be colored and displayed seperately from the RLBot member list.

    "},{"location":"community/community-guidelines/#competition","title":"Competition","text":"

    We regularly run tournaments and other events where bots get ranked and programmers get kudos. The specific rules of each event are generally up to the organizer, but here are a few guidelines to promote fairness:

    "},{"location":"community/community-guidelines/#record-the-matches","title":"Record the matches","text":"

    When playing for rank, you should have some kind of stream or recording that people can view and see that the match was played fairly.

    "},{"location":"community/community-guidelines/#make-sure-your-opponent-is-healthy","title":"Make sure your opponent is healthy","text":"

    It's nice to make sure an opponent is working as designed and you have the latest version before playing against it for rank

    • If possible, ask the author before the match.
    • If you don't get pre-approval, and they ask you afterward to make the match not count for rank because their bot was broken by something outside their control, the community is likely to respect those wishes.
    • As a bonus, it's nice to press the [home] key at some point to show bot performance stats. This helps to show that your computer is running the bots at full strength.
    "},{"location":"community/community-guidelines/#make-it-known-when-you-borrow-code","title":"Make it known when you borrow code","text":"

    Using code from other people with permission is good, as long as you make it publicly known. Many people give more praise to bots that they believe are made from scratch.

    • If there's reasonable suspicion that you secretly copied lots of another bot, you may be asked to show your source code to some moderators before entering ranked events.
    • If they find that there is copied code, there must be a public disclosure before entering the event.
    "},{"location":"community/community-guidelines/#the-fork-rule","title":"The Fork Rule","text":"

    If you forked your bot from a publicly recognized bot utility package, the fork rule doesn't apply to you.

    If you fork a bot (except for a tutorial bot), your bot is in fork mode, which means:

    • You can't enter league play or official tournaments or ranked games on braacket.com.
    • You must give your bot a name that makes it clear you're a fork (small events might choose to allow fork-mode competitors). The name should be formatted as \u201cYourBot [OriginalBot]\u201d.
    • Your bot must remain open source.

    This gives proper attribution, and helps the community keep track. You can escape from fork mode by demonstrating to the community (judged by the discord moderator team) that your bot is unique enough to compete under its own name.

    "},{"location":"community/rlbot-pack/","title":"RLBot Pack","text":"

    The RLBotPack is a repository holding frequently requested bots in one convenient place. The main intended users are people joining the discord looking for a fun bot to try out. It may also be useful as a way for people running streams to get an up-to-date version of your bot.

    To be a part of the pack, you just need to create a pull request with your bot to the repository.

    To qualify:

    • Your bot must be capable of auto-run
    • Use Python or Rust? You're all set.
    • Other languages? We have a Java wiki, a C# wiki and a Scratch video.
    • Your bot must not have any crazy external requirements (except for very common ones like Java or Google Chrome)
    • You must be willing to trim out any extra bot configs from your folder that people wouldn't care about
    • Obey the guidelines
    • If you join the bot pack, people will be free to play against you for rank in the braacket league whenever they want!

    After you create the pull request, somebody will come along, review your bot and eventually merge it to the pack.

    "},{"location":"community/rlbot-pack/#pull-request-tips","title":"Pull Request Tips","text":"
    • If you're uploading the files via GitHub, please make sure you're not uploading useless files like __pycache__, because the web upload bypasses .gitignore.
    "},{"location":"community/rlbot-pack/#updating-an-existing-bot","title":"Updating an existing bot","text":"

    It's very common for people's forked repository to get out of sync with the central RLBot/RLBotPack, and then when you make a pull request there's a bit of a mess. Here's a strategy for avoiding that:

    1. Make sure you have latest information from the central repo
    git remote add rlbot-origin https://github.com/RLBot/RLBotPack.git\ngit fetch rlbot-origin\n
    1. Pick a branch name for your change, e.g. my-new-change
    git checkout -b my-new-change rlbot-origin/master\n
    1. Make your changes, e.g. you may be copying / overwriting files in your bot folder.
    2. Make a commit and push it to your forked repo.
    git add .\ngit commit -m \"My new change.\"\ngit push origin my-new-change\n
    1. Visit your forked repo on github.com and create a pull request from the new branch.
    "},{"location":"community/rocket-league-story-mode/","title":"Rocket league story mode","text":""},{"location":"community/rocket-league-story-mode/#playing-rocket-league-story-mode","title":"Playing Rocket League Story Mode","text":"

    To get started with Story Mode, install RLBotGUI.

    Once installed, go to Add->Download Botpack to download the community's bots. Once they are downloaded you can click on \"Story Mode\" on the top right.

    "},{"location":"community/rocket-league-story-mode/#upgrades-and-teammates","title":"Upgrades and Teammates","text":"

    After you win a challenge, you get rewarded 1 currency. You can use it to purchase upgrades or recruit an available teammate. After you win all challenges in a city, all opponents from that city become available to recruit.

    Some matches require you to have teammates. If you don't have enough teammates and no currency, then you can play previous matches to earn some more currency.

    "},{"location":"community/rocket-league-story-mode/#choosing-difficulty","title":"Choosing Difficulty","text":"

    When you start Story Mode, you can choose your difficulty between easy, default and custom.

    • Easy is best for gold/plat players
    • Default is best for diamond/champ players

    Custom allows you to provide a JSON file that is used as the story configuration. This is what the default configurations looks like.

    Here are some example custom configurations:

    • Psyonix-only bots: Best for bronze/silver players who find the default bots too difficult
    • No teammates/Unfair: Best for players who find \"default\" configuration too easy or find bot teammates annoying.
    "},{"location":"community/rocket-league-story-mode/#creating-custom-configurations","title":"Creating Custom Configurations","text":"

    This is the actual story configuration used in Story Mode so you can use that as a reference to create your own custom configuration.

    Note that custom configurations doesn't allow you to change what the map looks like, name of the cities and how many cities there are. The rest is all customizable.

    If you are interested in only changing the \"feel\" of the story without changing any of the challenges then you can update the \"description.message\" for each city and \"challenges.display\" for each challenge. These are the text items shown to the user.

    If you actually want to change the challenges, then you can add/remove/modify the challenges for each city. Here are the fields that are supported for a challenge object:

    field meaning id Usually CITY-# format, just has to be unique across the config humanTeamSize opponentBots List containing keys to bot ids (either in the bots section or base-bots.json) map Rocket League arena to play in display Text to show to the user about this challenge max_score Optional. If set, it will set the maximum goals mutator so only few values are allowed disabledBoost Optional. If true, the map is set with no boost so no one will have boost completionConditions Optional. More details below. limitations Optional. List that can contain: \"half-field\". This maps to heatseeker mode

    completionConditions is an object. If multiple fields are provided, each condition is \"and\"-ed with the other conditions. A user completes a challenge if all of them are true. The default condition is that a player must win.

    {\n  \"win\": true, //set to false if you don't care,\n  \"scoreDifference\": 3 //player must win by at least this much\n  \"selfDemoCount\": 0 //player must not get demoed more than this\n  \"demoAchievedCount\": 2 //player must at least demo opponents this many time\n}\n
    "},{"location":"community/tips-for-running-tournaments/","title":"Tips for running tournaments","text":""},{"location":"community/tips-for-running-tournaments/#announcing-the-tournament","title":"Announcing the Tournament","text":"

    Normally tournament organizers will publish some kind of rules document. Google docs has been popular for that so far. Consider including the following:

    • Tournament format
    • Submission deadline(s)
    • How to submit (upload to google drive folder is a popular technique)
    • Stream time and twitch channel
    • Your intended tick rate (read and understand Tick Rate)
    • Whether or not hive mind style bots are allowed

    Here's an example document

    "},{"location":"community/tips-for-running-tournaments/#gathering-submissions","title":"Gathering Submissions","text":""},{"location":"community/tips-for-running-tournaments/#python-bot-requirements","title":"Python Bot Requirements","text":"

    People generally just send their whole bot folder, and that works well.

    "},{"location":"community/tips-for-running-tournaments/#net-c-bot-requirements","title":".NET / C# Bot Requirements","text":"

    Direct people to Tournament-Submissions, and also encourage them to do Auto Launching

    "},{"location":"community/tips-for-running-tournaments/#java-bot-requirements","title":"Java Bot Requirements","text":"

    Direct people to Tournament Submissions. If they follow those instructions, you'll be given a nice zip file with a README inside it.

    Also encourage them to do this, it'll make your life much easier

    "},{"location":"community/tips-for-running-tournaments/#scratch-bot-requirements","title":"Scratch Bot Requirements","text":"

    People who program their bots in Scratch should submit their whole folder.

    Scratch program (sb3) requirements

    • All the tournament code should be in the player 1 sprite.
    • Clicking the green flag should be the only thing necessary to start your program.

    CFG file requirements

    headless = True\nseparate_browsers = True\npretend_blue_team = True\n
    "},{"location":"community/tips-for-running-tournaments/#deadline-management","title":"Deadline Management","text":"

    It's a good idea to set a bot submission deadline at least 24 hours before the start of the tournament stream. This will give you an opportunity to test all the bots.

    Encourage early submissions so you can get a head-start on testing, and allow people edit their submission up until the deadline. If you feel confident from your pre-deadline testing that you'll be able to run most of the bots with no issues, consider giving an extension on the deadline--many people will need one.

    "},{"location":"community/tips-for-running-tournaments/#pre-tournament-bot-testing","title":"Pre-Tournament Bot Testing","text":"

    You should test all the bots beforehand.

    • Do they start successfully?
    • Do they have any obvious behavior problems that might be a problem with your setup?
    • Feel free to check with the bot maker about the expected behavior.
    • Do they run properly on both blue and orange team? Consider running test matches of each bot vs itself.
    • Are the C#/Java bots running on different ports? Each C# and Java bot must run on a separate port from the rest of the bots.
    "},{"location":"community/tips-for-running-tournaments/#running-bots","title":"Running Bots","text":""},{"location":"community/tips-for-running-tournaments/#net-c-bots","title":".NET / C# Bots","text":"
    • In the ideal case, if they followed Auto Launching successfully, you will only need to load the cfg file like you would for a Python bot.
    • Otherwise, you will need to locate the .exe file in the submission and run it manually. The RLBot framework output will hint about this.
    • Make sure the bot's port is different from the rest of the bots.
    "},{"location":"community/tips-for-running-tournaments/#java-bots","title":"Java Bots","text":"

    Prerequisite: You will need to have the Java Runtime Environment (JRE) installed. You are likely to need the latest one (Java 11 at time of writing) in case any of the botmakers compiled with it.

    You hopefully received a zip file for each bot. Extract it somewhere and consult the README.

    • In the ideal case, if they followed Auto Launching Java successfully, you will only need to load the cfg file like you would for a Python bot.
    • Otherwise, you will need to locate the .bat file associated with the Java portion of their bot and run it manually. The RLBot framework output will hint about this.
    • Make sure the bot's port is different from the rest of the bots.

    If you run into any trouble, consult this video

    "},{"location":"community/tips-for-running-tournaments/#scratch-bots","title":"Scratch Bots","text":"

    All recently-created Scratch bots should auto start with no issues, BUT often the process takes a while. Consider pausing the match until you see something like \"received first input from scratch bot\" in the console.

    If the bot is very old and does not auto run, they may need to do this

    "},{"location":"community/tips-for-running-tournaments/#streaming-and-casting","title":"Streaming and Casting","text":""},{"location":"community/tips-for-running-tournaments/#co-casters","title":"Co-casters","text":"

    If you want to invite others to do commentary with you, you'll need to:

    • Give them a real-time view of the action so they can comment on things as they happen.
    • Get the sound of their voice flowing through your system audio.

    A good way to do this is to start a Discord call and share your screen. If you have internet bandwidth or CPU constraints, make sure you share your screen at a low framerate and / or low resolution.

    "},{"location":"community/tips-for-running-tournaments/#diagnostics","title":"Diagnostics","text":""},{"location":"community/tips-for-running-tournaments/#bot-response-rate","title":"Bot Response Rate","text":"

    You can hit the [home] key to start rendering bot response rates in the upper left corner of Rocket League. You'll see a percentage that indicates how many of the rendered frames in Rocket League received fresh control inputs from a given bot.

    • If you have capped your framerate at 60fps, then you should expect to see 100% for all bots if they are performing well. - If your framerate is higher than 60, you will see percentages lower than 100 for some languages, and that's OK.
    • If you ever see a percentage above 100, that's a big concern. It may mean that there are multiple bot processes trying to control the same player. Make sure bots from the previous match are truly dead.
    "},{"location":"community/tips-for-running-tournaments/#running-the-tournament","title":"Running the tournament","text":""},{"location":"community/tips-for-running-tournaments/#bracket","title":"Bracket","text":"

    All our bots are in their own league on Braacket on which you can also create tournaments with most formats. You can also use your own site of preference or own local program which looks more graphically pleasing. But it's recommended to keep your bracket updated during the tournament so people don't lose track.

    "},{"location":"community/tips-for-running-tournaments/#things-to-do-in-between-games","title":"Things to do in between games","text":"
    • Make sure the FPS is capped at the desired number (maybe 120)
    • Don't forget to press 'H' when the games start, so the remove the useless HUD
    • Try to check twitch/discord in case there is something wrong and do not be afraid to restart a match
    • Have fun!
    "},{"location":"framework/architecture/","title":"Architecture","text":""},{"location":"framework/architecture/#startup","title":"Startup","text":""},{"location":"framework/architecture/#bots","title":"Bots","text":""},{"location":"framework/architecture/#python-bot","title":"Python Bot","text":""},{"location":"framework/architecture/#java-bot","title":"Java Bot","text":""},{"location":"framework/architecture/#diagram-source-code","title":"Diagram Source Code","text":"

    Created at sequencediagram.org with:

    title RLBot Startup Sequence\n\n\n[->Python: start match on map x with bots [y, z]\nbox over Python: Start RLBot.exe\nbox over Python: Start Rocket League\nparallel\nPython->DLL: start match on map x with cars [y, z]\nDLL->RLBot.exe: start match on map x with cars [y, z]\nRLBot.exe -> Rocket League: start match on map x\nparallel off\nRLBot.exe -> Rocket League: spawn cars\nbox over RLBot.exe,Rocket League:Continuous sync\n\nparallel\nPython->DLL: poll for game tick packet\nDLL->RLBot.exe: poll for game tick packet\nparallel off\nparallel\nRLBot.exe->DLL: packet with active match\nDLL->Python: packet with active match\nparallel off\nbox over Python:Launch bot processes y and z,\\ninforming each of their index\n
    title RLBot Python Bot\n\n\n[->Python BotManager: start up with index n\nPython BotManager->Python Bot:construct with index n\nparallel \nPython BotManager->DLL: poll for game tick packet\nDLL->RLBot.exe: poll for game tick packet\nparallel off\nparallel\nRLBot.exe->DLL: game tick packet\nDLL->Python BotManager: game tick packet\nparallel off\nPython BotManager->Python Bot: get_output()\nPython Bot->Python BotManager: SimpleControllerState\nparallel\nPython BotManager->DLL: send controls\nDLL->RLBot.exe: send controls\nparallel off\n
    "},{"location":"framework/architecture/#rlbot-v5","title":"RLBot v5","text":""},{"location":"framework/console-commands/","title":"Console commands","text":""},{"location":"framework/console-commands/#sending-a-console-command","title":"Sending a Console Command","text":"

    To send a console command from a python bot, e.g. Stat FPS, you would do this:

    from rlbot.utils.game_state_util import GameState\n\n# other code ...\n\ngame_state = GameState(console_commands=[\"Stat FPS\"])\nself.set_game_state(game_state)\n

    Other languages are not supported yet.

    "},{"location":"framework/console-commands/#known-console-commands","title":"Known Console Commands","text":"

    All of these are confirmed to work as intended. Please add more as you find them!

    • QueSaveReplay - Creates a replay keyframe and causes a replay to be saved at the end of the match.
    • Set WorldInfo WorldGravityZ 0.0000001 - Zero gravity (pretty much). Setting to 0 returns it to default. You can also use state setting to set gravity. Warning: Sending this command every frame will likely make your game lag!
    • Set WorldInfo TimeDilation 3 - Speeds up the game by 3 times. Can also be used to slow down the game with a number between 0 and 1. You can also use state setting to set game speed.
    • Stat FPS - Turns on a little in-game FPS counter. Can be turned back off with Stat FPS 0
    • ShowDebug PHYSICS - Nice little text readout which shows you some values, and also the names of some specific classes/attributes that you can use Set on.
    • Pause - Pauses the game. Send Pause to unpause the game. get_output/GetOutput/getOutput will still be called when the game is paused. This pause is the same as the pause when Escape is pressed.
    • ViewAutoCam - This will set the camera to auto-cam mode.
    • ViewDefault - Go to the default director camera mode.
    • ViewPlayer <team index> <player index> To go a specific player POV - e.x. ViewPlayer 0 2 to view the third player on blue and ViewPlayer 1 2 to view the third player on orange.
    • CycleHUD - The equivalent of pressing H to cycle through the HUD options.
    • CycleCamera - Goes to the next camera view. For example, ViewAutoCam and then CycleCamera puts the camera into the free-flying mode.
    "},{"location":"framework/console-commands/#research-for-more-console-commands","title":"Research for More Console Commands","text":"

    Try some of these!

    https://www.reddit.com/r/RocketLeagueMods/comments/4vuj0h/list_of_available_console_commands/

    "},{"location":"framework/operating-system-support/","title":"Operating system support","text":""},{"location":"framework/operating-system-support/#windows","title":"Windows","text":"

    RLBot was originally made for Windows, so Windows has the best support. Users are encouraged to watch this video to get started quickly with RLBotGUI!

    "},{"location":"framework/operating-system-support/#linux","title":"Linux","text":"

    RLBot v4 only runs on Linux with the old native Linux version of Rocket League. This version is only available on Steam. There is a (probably outdated) install script here.

    If you only have the Epic version of the game or you want to run the Proton version, you're unfortunately out of luck. This is due to libRLBotInterface.so being broken on Linux.

    "},{"location":"framework/operating-system-support/#rlbot-v5-on-linux","title":"RLBot v5 on Linux","text":"

    RLBot's next major version, RLBot v5, is aiming to properly support Linux. RLBot v5 currently supports either Rocket League running under Proton on Steam or Rocket League installed from the Epic Games Store via Legendary.

    This version is currently in development, but you can inquire about the progress in the RLBot Discord. While support has been added for Linux, very few bots have been ported to run in RLBot v5.

    "},{"location":"framework/operating-system-support/#mac","title":"Mac","text":"

    Mac support is currently unknown and may not work. If you want to try, see the instructions below.

    "},{"location":"framework/operating-system-support/#instructions","title":"Instructions","text":"
    1. Make sure you have Python 3.11 and pip
    2. Run these commands
    python3 -m pip install --user --upgrade pip\npython3 -m pip install --user gevent eel\npython3 -m pip install --user --upgrade rlbot rlbot_gui\npython3 -c \"from rlbot_gui import gui; gui.start()\"\n
    "},{"location":"framework/operating-system-support/#rlbot-v5-on-mac","title":"RLBot v5 on Mac","text":"

    Native MacOS support has been dropped. It's recommended to run both Rocket League and RLBot under a virtual machine running Windows or Linux.

    "},{"location":"framework/psyonix-api-notes/","title":"Psyonix api notes","text":"

    Hello everyone! We're proud to announce that the Psyonix bot API has finally been integrated into RLBot! We hope you're just as excited as we are about this milestone! \ud83c\udf89

    "},{"location":"framework/psyonix-api-notes/#details","title":"Details","text":"

    Check out this diagram to get some intuition for this migration. Everything on the left staying the same or as close to the same as possible, so your bots are expected to keep working with no changes required!

    "},{"location":"framework/psyonix-api-notes/#what-you-can-expect-from-this-new-version-of-rlbot-v4","title":"What you can expect from this new version of RLBot (v4)","text":"

    We're aiming for a backwards compatibility with this first bot API release, so expect your bots to play almost exactly like they used to!

    • The renderer now has occlusion, so 3D lines disappear behind objects correctly!
    • You can still use state setting, except:
    • Can\u2019t manipulate boost pads
    • Can\u2019t mess with the car\u2019s jump state
    • Can\u2019t provide partial location / velocity, must fully specify
    • The GameTickPacket will have all the same data except:
    • It will have non-interpolated values straight from the physics engine, same as RigidBodyTick!
    • Latest ball touch will always be blank for now (fixed)
    • Boost respawn timers don't work yet
    • Unfortunately, quick chat is not supported yet (1/2 fixed)
    • We only support Soccer, exhibition mode at the moment. (More modes are supported)
    • The game data will currently update in memory at 60Hz, ~~regardless of Rocket League's frame rate~~ (anecdotally it seems to be capped at the frame rate). We may be able to tune that later. (We now have 120hz)
    • The Psyonix API itself and the code that interfaces with it directly are closed source at the moment.
    "},{"location":"framework/psyonix-api-notes/#what-you-can-look-forward-to-in-the-future","title":"What you can look forward to in the future","text":"
    • No more breaking after updates! Since RLBot no longer relies on DLL injection, RLBot will continue to work after every Rocket League update.
    • LAN support is a possibility in the future. With a virtual LAN (VLAN), this could mean being able to play against bots on different machines over the internet, with your friends!
    • Support for Linux and macOS is planned! (C++ and C# bots won't work)
    • Rumble support is planned. Bots will be able to take part in the mayhem! (Done)
    • Unrelated to the API:
    • DomNomNom is working on a team communication system for bots. (Done)
    • Chip is working on advanced pathfinding for bots.
    "},{"location":"framework/psyonix-api-notes/#regarding-bugs","title":"Regarding Bugs","text":"

    This is a lot buggier than a normal release--RLBot broke due to a Rocket League patch and we chose to move forward with the official API rather than fix our old injection technique. Sorry for the bugs / missing features!

    Please test out your bots and report any bugs to #issues-and-bugs or the GitHub repository's Issues page: https://github.com/RLBot/RLBot/issues. We appreciate all the help we can get!

    List of Busted Bots

    • NV Derevo, on some computers
    "},{"location":"framework/psyonix-api-notes/#rollback-instructions","title":"Rollback Instructions","text":"

    If it's a serious problem for you, you can roll back your Rocket League and use our old 1.14.12 version. Note that while you're on the old Rocket League, you will be unable to play online!

    You can do it by clicking steam://nav/console and then entering download_depot 252950 252951 6062228629972172324. Then read https://www.reddit.com/r/Steam/comments/611h5e/guide_how_to_download_older_versions_of_a_game_on/ starting with step 7.

    And then, once you're done with that, you'll need to pin your rlbot version to 1.14.12. If you're using the old GUI, you can accomplish that by changing this line https://github.com/RLBot/RLBotPythonExample/blob/master/requirements.txt#L3 to rlbot==1.14.12.

    If you're using the new colorful RLBotGUI, you'll need to go find rlbot-requirements.txt in the vicinity of C:\\Users\\yourname\\AppData\\Local\\RLBotGUI\\rlbot-requirements.txt and do the change there.

    "},{"location":"framework/psyonix-api-notes/#thanks","title":"Thanks","text":"

    Thank you to everyone for sticking with the community! Of course, a massive thank you to Psyonix for supporting us and giving us the API! We can't wait to see RLBot evolve further!

    "},{"location":"framework/sockets-specification/","title":"Sockets specification","text":"

    Sockets are currently available with Windows and Mac support only. Linux coming soon.

    You can use https://github.com/RLBot/RLBot/tree/master/src/main/cpp/RLBotInterface/src as a reference implementation in c++.

    "},{"location":"framework/sockets-specification/#data-format","title":"Data Format","text":"

    Unless otherwise specified, data is sent and received on the socket in this format:

    • First two bytes are an integer (big-endian) which specifies the data type (see list below).
    • Next two bytes are an integer (big endian) which specifies the number of bytes in the payload.
    • Remaining bytes are a payload. The logic for parsing it will depend on the data type, but generally it will be binary data in flatbuffer format. Using tools provided by Google (i.e. flatc.exe) and rlbot.fbs you can auto-generate code in various languages suitable for writing / parsing the payload data.
    "},{"location":"framework/sockets-specification/#data-types","title":"Data Types","text":"

    Types expected to flow from RLBot to the client are in bold. Some are bi-directional.

    1. Game tick packet (arrives at a high rate according to /Tick-Rate except \"desired tick rate\" is not relevant here)
    2. Field info (sent once when a match starts, or when you first connect)
    3. Match settings (sent once when a match starts, or when you first connect)
    4. Player input
    5. Actor mapping data (deprecated, related to Remote RLBot)
    6. Computer id (deprecated, related to Remote RLBot)
    7. Desired game state
    8. Render group
    9. Quick chat
    10. Ball prediction (sent every time the ball diverges from the previous prediction, or when the previous prediction no longer gives a full 6 seconds into the future).
    11. Ready Message (clients must send this after connecting to the socket)
    12. Message Packet: List of messages, having one of the following types:
      • PlayerStatEvent - Event when a player performs an action or earns an accolade recognized in statistics, e.g. BicycleHit, HatTrick, MostBoostPickups.
      • PlayerSpectate - Spectator camera is now focusing on a new player.
      • PlayerInputChange - Human or bot has touched their controller, e.g. turned on boost, changed steering, etc.
    "},{"location":"framework/sockets-specification/#rlbot-v5","title":"RLBot v5","text":"
    1. None
      • Aka the disconnect request.
    2. GameTickPacket
      • Received by sessions at a high rate according to tick rate (except \"desired tick rate\" is always 120hz in v5)
    3. FieldInfo
      • Received by a session after it sends ConnectionSettings.
    4. StartCommand
      • Starts a new match after reading the given config file.
    5. MatchSettings
      • Received by a session after it sends ConnectionSettings.
      • Can be sent by sessions to start a new match.
    6. PlayerInput
      • Sent by sessions to control their cars.
    7. DesiredGameState
      • Sent by sessions to change the game state.
      • Ignored if state setting was disabled in the match settings.
    8. RenderGroup
      • Sent by sessions to render lines & text in the game.
      • Ignored if render setting was disabled in the match settings.
    9. RemoveRenderGroup
      • Sent by sessions to remove a render group.
      • Ignored if render setting was disabled in the match settings.
    10. MatchComm
      • A copy is received by sessions when another session sends the message.
      • Messages may not be received if the message was filtered due to team_only being requested in the message.
      • Only received if enabled in ConnectionSettings.
    11. BallPrediction
      • Received by sessions right before every GameTickPacket if enabled in ConnectionSettings.
    12. ConnectionSettings
      • Sessions send this immediately after connecting.
      • Tells the server what kind of data it wants to receive.
    13. StopCommand
      • Ends the current match, and optionally tells RLBotServer.exe to shut itself down.
    14. SetLoadout
      • Sent by sessions to change the loadout of their cars.
      • Will always work if a loadout was not specified in match settings and when sent before InitComplete.
      • Ignored if state setting was disabled in the match settings, and a loadout was set in match settings.
    15. InitComplete
      • Indicates that the session has finished all initialization and is ready to start receiving game messages without delay.
      • The match will not start until all sessions have sent this message.
      • SpawnId will be used to set the name of the session in RLBot's performance monitor and when filtering messages. Hiveminds should simply send the first spawn id they received from the framework.
    "},{"location":"framework/sockets-specification/#connecting","title":"Connecting","text":"

    Prerequisites (handled automatically by RLBotGUI / the RLBot framework):

    • Rocket League must be running under the -rlbot flag.
    • RLBot.exe must be running. After it successfully connects to Rocket League, it will start listening on TCP port 23234.

    • As a client, connect to TCP port 23234. Note: please expect to receive the port as a parameter in the future rather than hard coding

    • Send a 'ready' message, as defined here. Be sure to use the data format explained above (two bytes for data type, two bytes for size...)

    Some attributes in the ready message are not used yet. Once you're connected, you will start receiving data on the socket, with one of the data types specified above.

    "},{"location":"framework/sockets-specification/#sending-data","title":"Sending Data","text":"

    Send data to the same TCP socket, using the same format (two bytes for type, two bytes for size). You can send match settings (starts a new match), player input, desired game state, render group, and quick chat.

    Consult google.github.io/flatbuffers to learn how to construct the byte array for your payload in the language of your choice.

    "},{"location":"framework/sockets-specification/#client-libraries","title":"Client Libraries","text":""},{"location":"framework/sockets-specification/#python","title":"Python","text":"
    • https://github.com/RLBot/RLBot/tree/master/src/main/python/rlbot/socket
    "},{"location":"framework/sockets-specification/#whos-using-sockets","title":"Who's Using Sockets","text":"
    • The core RLBot framework uses sockets from Python to start matches.
    • The core RLBot framework uses sockets from within RLBotInterface.dll to run bots.
    • Javascript / Typescript: easyrlbot
    • RLBotControllerOverlay
    • This little test script
    "},{"location":"framework/supported-programming-languages/","title":"Supported programming languages","text":""},{"location":"framework/supported-programming-languages/#main-languages","title":"Main Languages","text":"

    The following list of languages are supported by core developers of the RLBot framework, or have reached a very high level of documentation and support from the community. They are featured on rlbot.org.

    "},{"location":"framework/supported-programming-languages/#python","title":"Python","text":"

    RLBotPythonExample

    "},{"location":"framework/supported-programming-languages/#java","title":"Java","text":"

    RLBotJavaExample

    "},{"location":"framework/supported-programming-languages/#c-and-other-net-languages","title":"C# (and other .NET languages)","text":"

    RLBotCSharpExample

    "},{"location":"framework/supported-programming-languages/#c","title":"C++","text":"

    CPPExampleBot

    "},{"location":"framework/supported-programming-languages/#rust","title":"Rust","text":"

    crates.io

    RLBotRustTemplateBot

    "},{"location":"framework/supported-programming-languages/#javascript","title":"Javascript","text":"

    EasyRLBot

    EasyRLBotExample

    "},{"location":"framework/supported-programming-languages/#scratch","title":"Scratch","text":"

    RLBotScratchInterface

    "},{"location":"framework/supported-programming-languages/#community-supported-languages","title":"Community Supported Languages","text":"

    What follows is a list of languages, that the community have also made support for, however, their frameworks may be less documented and maintained. If you want to use a language not listed, Nim uses a socket intermediate bot as a bridge between the game and the Nim executable. This can be used by any other language (that can use sockets).

    "},{"location":"framework/supported-programming-languages/#clojure","title":"Clojure","text":"

    Clojure-Bot

    "},{"location":"framework/supported-programming-languages/#nim","title":"Nim","text":"

    NimExampleBot

    "},{"location":"framework/supported-programming-languages/#go","title":"Go","text":"

    RLBotGo

    RLBotGoExample

    "},{"location":"framework/supported-programming-languages/#lua","title":"Lua","text":""},{"location":"framework/supported-programming-languages/#asciidots","title":"Asciidots","text":"

    Because who doesn't love drawing ascii art?

    AsciiDots Documentation

    Documentation for RLBot version of AsciiDots

    Example bot

    "},{"location":"framework/supported-programming-languages/#brainfuck","title":"Brainfuck","text":"

    Scalable and efficient bot-making

    Brainfuck documentation

    Example bot

    "},{"location":"framework/v5/","title":"RLBot v5 (Beta) Overview","text":"

    RLBot v5 is the next major update to the RLBot framework bringing a host of reliability improvements and some new features to the table.

    RLBot v5 is now in beta. In this beta period we will fix bugs, incorporate feedback, and potentially make minor breaking changes. However, RLBot v5 should now be feature-complete and people can start adopting it. Note that the various language interfaces are currently in development and may be unstable. There is also no GUI and distribution method yet. You can find the newest version of RLBotServer.exe on github.com/RLBot/core/releases. See Virx' Video on how to get started in RLBot v5 beta with Python.

    Any updates to RLBot v5 beta and language interfaces will be announced in the RLBot Discord #annoucements channel.

    • If you find bugs, please report them on Github.
    • If you run into issues with v5, you can find help on Discord, either in the appropriate language channel or in the #framework-dev channel. There is also a \"v5\" tag in #rlbot-help.
    • If you have feedback/request for v5, please let us know on Github in the #framework-dev channel.

    In the remainder of this document we will cover:

    • Our reasoning for creating v5 and an overview of its architecture,
    • A list of features completed/reworked/todo/removed in v5 (beta),
    • A guide on how to transition from v4 to v5,
    • Links to v5 language interfaces and more.
    "},{"location":"framework/v5/#why-v5","title":"Why v5?","text":"

    RLBot v4 has been the most userfriendly and stable version of RLBot yet. It was made in 2018 when RLBot was still using DLL injection. Later, in 2019, the collaboration with Psyonix and the official API were revealed. Since then, there have only been minor changes and new features, which proves how well-designed v4 was. In fact, v5 is not that different from v4. It is primarily a rewrite and an opportunity fix the flaws of v4 that have been revealed over the years. So here are the main reasons we made v5:

    • The closed-sourced part of v4 is doing more than just communication with the Psyonix API. This has long prevented the community from fixing certain bugs themselves. Therefore we are extracting part of the closed-source part into the opens-source part of RLBot such that only the communication is closed-source.
    • The closed-sourced part of v4 is written in C++. By rewritting the backend of RLBot in C# we hope that more people feel comfortable contributing to it.
    • No more DLLs. You may not be aware, but most bots still uses a DLL to communicate directly to the RLBot backend. In v5, the transition to web sockets is finally complete and this allows the bot inferfaces to be improved (e.g. Python type hints are not a hack anymore).
    • All languages can start matches in v4, technically, but the logic for launching of Rocket League and bots was only implemented in Python (and partially Rust). This discourage us from writing match starters (GUI, autoleague, etc) in other languages than Python (even CleoPetra in Java uses a Python process to start matches). Therefore we move this logic to the backend for v5 such that more languages can benefit from it.
    • The Psyonix API made a few extra features availble to us, but we never integrated them in v4. They are integerated in v5.
    • Python is very slow. The rewrite in C# has made this clear.
    • The .cfg file format has no standard.

    So while the changes to the functionality and interface are minor, the architecture and the framework's interal code is very different. We hope these changes will make it enjoyable to work with and contribute to RLBot moving forward.

    "},{"location":"framework/v5/#features-of-v5","title":"Features of v5","text":"

    Legend: \u2705=done, \ud83d\udfe8=todo, \u2728=new, \ud83d\udee0=reworked/changed, \u26d4=removed

    • \u2705\ud83d\udee0 First-class Windows & Linux support
      • No current plans for MacOS, as there's no way to run Rocket League without a full VM
    • \u2705\ud83d\udee0 All bots connect to core directly via the sockets flatbuffer spec
      • As a consequence, adding new language support is much easier - if your language can write/read a TCP socket, it's possible! Bonus points if your language is one of the 14 that are currently supported by FlatBuffers
    • \u2705\ud83d\udee0 Any language can still start/stop/manage a match, but the logic for launching Rocket League and bots are now in RLBotServer.
    • \u2705\ud83d\udee0 All configs files now use the standard toml format. Example: necto/bot.toml
    • \u2705 Hiveminds
    • \u2705 Scripts
    • \u2705\ud83d\udee0 The bot configuration's python_file has been replaced with run_command and run_command_linux
      • \ud83d\udfe8 On Linux, if run_command_linux isn't specified, v5 will attempt to run run_command under Wine
    • \u2705\u2728 Multi-ball support for when there's more/less than 1 ball in a game
    • \u2705\u2728 New mutator options
      • A Knockout match can be started
      • Start with one, two, four, or six balls
      • Max 7 goals
      • Beach ball, anniversary ball, spooky cube, or the haunted dropshot ball
      • Curve ball or beach ball curve
      • Medium ball size
      • Reverse gravity
      • Tactical rumble (fyi we still can't read rumble items)
      • Boost strength 5x
      • Max time 11 minutes
    • \u2705\u2728 Freeplay matches. Useful if you want to use the Rocket League's freeplay-exclusive features
    • \u2705 Rendering
      • \ud83d\udfe8 Rendering can be toggled for individual bots
      • \u26d4 Keyboard shortcuts to toggle rendering. We plan to have buttons in the GUI instead!
      • \u2705\u2728 New RenderAnchors. Attach your rendering to the location and rotation of a car or ball plus both an absolute and local offset. No re-rendering is required and it is smooth. Example: video posted on Discord
    • \u2705 Game state manipulation (aka state setting)
    • \u2705 Updated ball prediction algorithm for better accuracy in all game modes that use a ball
    • \u2705\u2728 Support for Psyonix Beginner bots
    • \u2705\u2728 More customizable Psyonix bots
    • \u2705\u2728 Override a bot name/loadout (without editing the bot configuration)
      • Use cases include: Spawning specific Psyonix bots or give Nexto your in-game name to troll friends
    • \u2705\ud83d\udee0 Generated loadouts are now created by your bot instead of a separated loadout generator script
    • \ud83d\udfe8\u2728 Hot-swap your bot's loadout. Respawn your bot's car with a different loadout on command without restarting the match or interfering with the other bots
      • Only enabled when state setting is also enabled
    • \u2705\u2728 New data in GameTickPacket for every player:
      • Last known player input
      • If the player was the last player to be spectated in the match
      • Player accolades. A list of small awards/events by the player, e.g. EpicSave, Demolition, PoolShot, LowFive, etc. See full list here)
    • \u2705\ud83d\udee0 Match comms and quick chat have been combined into just MatchComms with an optional quick chat message such that both bots and humans can understand what is meant
      • \u26d4 Quick chat messages are no longer restricted to a set of hardcoded options
      • \u2705\ud83d\udee0 The team_only filtering finally works. No more spying on enemy chats
    • \u2705\ud83d\udee0 RLBot waits for all processes to fully boot before letting the match start
    • \u2705 Performance metrics (i.e. missed responses by bots)
      • \u26d4 Keyboard shortcuts to toggle the performance graph. We plan to have buttons in the GUI instead! Currently, the performance percentages will be shown anytime either RLBot itself or a bot is running below 100%.
    • \u26d4 Non-standard Tick Rates (standard is 120hz)
      • All bots are now expected to run at 120hz. If you need more time to process inputs, it's advisable to engineer your bot around this by, for example, using an extra asynchronous thread running complex algorithms.
    • \u26d4 DropshotTileInfo
      • This functionality was lost with the introduction of the Psyonix API and is removed v5. But it might return.

    On top of all that, the framework is also simply significantly faster.

    "},{"location":"framework/v5/#breaking-changes-migration","title":"Breaking Changes / Migration","text":"

    Many things will feel familiar in v5, but there's several breaking changes that have been made:

    • RLBot.exe has been renamed to RLBotServer.exe.
      • Instead of the entire binary being closed-source, as much of the code as possible is now open-source in RLBot/core.
      • Anyone can build RLBotServer.exe after making changes to the code due to Bridge.dll - this binary is closed-source due to legal restrictions around the Psyonix API, but this knew binary was built to be as minimal as possible while adhering to those restrictions.
    • All bots are now expected to run at 120hz. If you need more time to process inputs, it's advisable to engineer your bot around this by, for example, using an extra asynchronous thread running complex algorithms.
    • Config files have changed

      • Instead of the arbitrary cfg file format, we now use toml files. This is a standardized format that is easier to read and write and has better support over different languages. Many IDEs also support syntax highlighting for toml files.
      • Bots config files must end in bot.toml. This includes hiveminds. Example valid file names include:
        • bot.toml
        • super_bot.bot.toml
        • super_ultra.bot.toml
      • Script config files must end in script.toml. Example valid file names include:
        • script.toml
        • super_script.script.toml
        • super_ultra.script.toml
      • Other config files have no defined naming convention.
      • Bot/Script/Hivemind config file format:

        • [Locations] has been renamed to [settings]
        • hivemind must be set to true instead of [settings] if the bot is a hivemind
        • python_file, requirements_file, supports_standalone, and use_virtual_environment have been replaced with a different concept: run_command and run_command_linux are ran in a shell to start the bot.
          • Note: Bots submitted to the v5 botpack (TODO) will be expected to be packagable in a self-contained executable that is built from source by an automated deployment pipeline. This includes Python bots.
        • New optional value location - will set the working directory to something other than the directory that the config file is currently located in.
        • maximum_tick_rate_preference has been removed, every bot is expected to run at 120hz
        • supports_early_start has been removed, as all bots are booted as soon as possible. Bots no longer know their index when booting, but they do know their name & team.
        • looks_config and loadout_generator have been replaced with loadout_config
          • If loadout_config is not set, then your bot can send a SetLoadout message during boot-up. This is a direct replacement for the old loadout generator script.
        • [Details] has been renamed to [details]
        • github has been renamed to source_link
        • Example of a bot config file in v4 and v5:

        v4:

        [Locations]\nname = Necto\nlogo_file = ./necto_logo.png\nlooks_config = ./appearance.cfg\npython_file = ./bot.py\nrequirements_file = ./requirements.txt\nmaximum_tick_rate_preference = 120\n\n[Details]\ndeveloper = Rolv, Soren, and several contributors\ndescription = Necto is the official RLGym community bot, trained using PPO with workers run by people all around the world.\nfun_fact = Necto uses an attention mechanism, commonly used for text understanding, to support any number of players\ngithub = https://github.com/Rolv-Arild/Necto\nlanguage = rlgym\ntags = 1v1, teamplay\n

        v5:

        [settings]\nname = \"Necto\"\nlogo_file = \"necto_logo.png\"\nloadout_config = \"loadout.toml\"\nrun_command = \".\\\\venv\\\\Scripts\\\\python bot.py\"\nrun_command_linux = \"./venv/bin/python bot.py\"\n\n[details]\ndeveloper = \"Rolv, Soren, and several contributors\"\ndescription = \"Necto is the official RLGym community bot, trained using PPO with workers run by people all around the world.\"\nfun_fact = \"Necto uses an attention mechanism, commonly used for text understanding, to support any number of players\"\nsource_link = \"https://github.com/Rolv-Arild/Necto\"\nlanguage = \"rlgym\"\ntags = [\"1v1\", \"teamplay\"]\n
    • All processes (bot, script & hivemind) are now similar to v4's concept of a StandaloneBot

      • This means that the only way to interface with RLBotServer.exe is by communicating via FlatBuffers over a TCP socket. By default, the server listens to 0.0.0.0:23234. The port can be changed by passing in the desired port as the first argument when starting the binary, for example RLBotServer.exe 54315.
      • In Python specifically, there is no longer a BaseAgent class. Instead, you must implement the Bot class.
      • Must read the environment variable RLBOT_SERVER_PORT to know what port they can connect to the server on.
      • Must read the environment variable RLBOT_SPAWN_IDS. It will be a single integer for bots and scripts, but for hiveminds it will be a comma separated list of integers.
    • Various changes have been made to the GameTickPacket
      • Removed num_cars/num_pads as the list of cars/pads is now only as long as the actual number of cars/pads
      • Renamed cars to players
      • Replaced ball with balls which is now a list of balls in the game
      • Note: This list can have a length of zero in a normal match. It's recommended to check the length of the list before assuming there's a ball in the game.
      • In PlayerInfo:

        • Replaced is_demolished with demolished_timeout: demolished_timeout is a float representing the time until the player respawns after being demolished. It is zero if the player is not demolished.
        • Added dodge_timeout: A float representing the time the player has left before they can no longer dodge. -1 if the player cannot dodge (e.g. because they're on the ground or the dodge time window expired).
        • Replaced has_wheel_contact with a new concept, AirState. AirState is defined as:
        enum AirState: ubyte {\n  /// All wheels are on the ground\n  OnGround,\n  /// When the bot is jumping,\n  /// then InAir right after\n  Jumping,\n  /// When the bot is double jumping,\n  /// then InAir right after\n  DoubleJumping,\n  /// When the bot is dodging,\n  /// then InAir right after\n  Dodging,\n  InAir,\n}\n
        • Removed jumped and double_jumped

    The above list may be incomplete.

    "},{"location":"framework/v5/#links-and-resources","title":"Links and Resources","text":"

    Below we list where to find the implementation of RLBot v5, the language interfaces, and related documentation. This wiki will also be updated as things stabilize.

    RLBot v5 framework:

    • RLBotServer.exe:
      • RLBot/core
      • RLBot/bridge (closed-source)
    • RLBot/flatbuffer-schema

    Language interfaces (unstable):

    • VirxEC/Python
      • Video
      • Migration details
    • swz/Go
    • swz/Rust
    • Kipje13/C++
    "},{"location":"miscellaneous/extracting-map-meshes/","title":"Extracting map meshes","text":""},{"location":"miscellaneous/extracting-map-meshes/#prerequisites","title":"Prerequisites","text":"
    • 64-bit Windows
    • Rocket League
    • U-Model
    • Blender 2.9+
    • Blender .psk addon
    "},{"location":"miscellaneous/extracting-map-meshes/#additional-notes-before-getting-started","title":"Additional notes before getting started","text":"

    This tutorial was tested on Blender 3.1.

    Python knowledge is preferred for this tutorial, but you can get by without it.

    Python does not need to be installed for this to work.

    The resulting .bin files can be imported into any language that can read binary numbers from a file. The id files are a chain of 32-bit integers in little-endian format, and the vertices are stored at 3 32-bit floats in a row (x, y, z), also stored in little-endian format. Each ID in ids corresponds to the index of the vertex if you parsed the vertices in the order that they appear in the file. (By default.)

    "},{"location":"miscellaneous/extracting-map-meshes/#overview","title":"Overview","text":"
    1. Opening U-Model the right way
    2. How to identify a map
    3. Extracting a map
    4. Identifying collision files
    5. Importing to Blender
    6. Converting object to binary data
    "},{"location":"miscellaneous/extracting-map-meshes/#opening-u-model-the-right-way","title":"Opening U-Model the right way","text":"

    Create a bat file called umodel.bat, and save this to it:

    umodel.exe -game=rocketleague -path=\"C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole\"\n

    Depending on where you saved U-Model, you may have to use cd before that to get to it:

    cd C:\\Program Files (x86)\\umodel_win32\numodel.exe -game=rocketleague -path=\"C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole\"\n

    Use this bat file that you create to launch U-Model whenever you need to use it.

    If you have Rocket League install through Epic Games, use this path instead: C:\\Program Files\\Epic Games\\rocketleague\\TAGame\\CookedPCConsole

    WARNING: Be sure to use the 32-bit version of U-Model! You're safe as long as you don't change umodel.exe to umodel_64.exe. Some assets will refuse to load, if you do.

    "},{"location":"miscellaneous/extracting-map-meshes/#how-to-identify-a-map","title":"How to identify a map","text":"

    In the top-left-ish corner, there's space for you to filter all the files. If you type in _P.upk, you will get a list of all of the maps.

    If you're looking for a map, filter by MapImage. You can double-click on a file to view a preview of the map with a similar name. Press the key O (or go top left -> File -> Open package) to get back to the menu with all of the files.

    "},{"location":"miscellaneous/extracting-map-meshes/#extracting-a-map","title":"Extracting a map","text":"

    In this example, I will be using Stadium_P.upk - otherwise known as DFH Stadium.

    Right-click on the map you want to export, click Export, and all of the map data will be extracted for you.

    All files are extracted to the UmodelExport folder in whatever folder you saved U-Model to. For me, this is C:\\Program Files (x86)\\umodel_win32\\UmodelExport.

    "},{"location":"miscellaneous/extracting-map-meshes/#identifying-collision-files","title":"Identifying collision files","text":"

    Inside the folder of the map you extracted, there should be 5 more folders - the one that you want is called StaticMesh3. In this folder, simply look for any .pskx files that have the word collision in them. For DFH Stadium, there are 4 files:

    • Goal_STD_Collision.pskx
    • Field_STD_Collision_Corner.pskx
    • Field_STD_Collision_SideTop.pskx
    • Field_STD_Collision_SideBot.pskx

    These files contain all of the available field collision information.

    "},{"location":"miscellaneous/extracting-map-meshes/#importing-to-blender","title":"Importing to Blender","text":"

    Open Blender, and select \"General.\" This will load a default 3D scene, with a cube, light source, and camera.

    Next, in the top right, delete all three of these things. (Right-click -> Delete)

    Now, we import ONE of our objects. This is important - we can only convert one at a time unless changes are made to the script in the next section. When you want to convert another object, delete the only one in the scene first. The process is the same as deleting the cube, as we did previously.

    To import an object, go to the top right -> Files -> Import -> Skeleton Mesh (.psk). Use this to import one of the .pskx collision files that we got earlier.

    For this, I have imported DFH Stadium's Field_STD_Collision_Corner.pskx.

    "},{"location":"miscellaneous/extracting-map-meshes/#converting-the-object-to-binary-data","title":"Converting the object to binary data","text":"

    At the top of Blender, select the Scripting tab.

    In the top middle, select New.

    Copy & paste the below Python script:

    import bpy\n\n# Blender Python API Documentation\n# https://docs.blender.org/api/current/index.html\n\nprint()\n\nif len(bpy.context.scene.objects) != 1:\n    print(\"MORE THAN ONE OBJECT EXISTS!\")\n    exit()\n\nobj_name = \"soccar_corner\"\n\ndata = bpy.context.scene.objects[0].data\n\nids = []\nverts = []\n\nfor tri in data.polygons:\n    for id in tri.vertices:\n        ids.append(id)\n\nfor vert in data.vertices:\n    for coord in vert.co:\n        verts.append(coord)\n\nprint(f\"Number of ids: {len(ids)}\")\nprint(f\"Number of triangles: {len(ids) / 3}\")\nprint(f\"Number of coordinates: {len(verts)}\")\nprint(f\"Number of vertices: {len(verts) / 3}\")\n\nimport os\nfrom pathlib import Path\n\nos.chdir(Path.home() / \"Documents\")\n\n#import json\n\n#with open(obj_name + \"_ids.json\", \"w\") as f:\n#    json.dump(ids, f)\n\n#print(\"Wrote json ids\")\n\n#with open(obj_name + \"_vertices.json\", \"w\") as f:\n#    json.dump(verts, f)\n#    \n#print(\"Wrote json vertices\")\n\nimport struct\n\nwith open(obj_name + \"_ids.bin\", \"wb\") as f:\n    f.write(struct.pack(\"<\" + \"i\" * len(ids), *ids))\n\nprint(\"Wrote binary ids\")\n\nwith open(obj_name + \"_vertices.bin\", \"wb\") as f:\n    f.write(struct.pack(\"<\" + \"f\" * len(verts), *verts))\n\nprint(\"Wrote binary vertices\")\n

    You can edit the line obj_name = \"soccar_corner\" near the top to adjust the name of the outputted file, and os.chdir(Path.home() / \"Documents\") to edit the output folder.

    Click on the Play/Run button in the top middle to run the script.

    This creates the two bin files containing the ids and vertices from the object.

    If you want an example of using collision data and compiling them into a mesh to run collision queries on, check out the rl_ball_sym Rust project:

    • Reading into a mesh
    • Compiling all collision data into a big mesh, then triangles and a BVH
    "},{"location":"miscellaneous/lan-setup/","title":"Lan setup","text":""},{"location":"miscellaneous/lan-setup/#option-1-online-private-match-steam-or-epic","title":"Option 1 - online private match (Steam or Epic)","text":""},{"location":"miscellaneous/lan-setup/#requirements","title":"Requirements","text":"
    • Hamachi
    • BakkesMod
    • Rocket Plugin installed in Bakkesmod
    • RLBotGUI (only needed for the host)

    Quick Note: If the host can forward port 7777 / configure their firewall, then neither the host nor the clients need to use Hamachi. Then the host only has to provide their IP address to the clients who enter it into Rocket Plugin to connect. This allows more connections than the free version of Hamachi.

    "},{"location":"miscellaneous/lan-setup/#instructions-for-host","title":"Instructions for Host","text":"

    Only the host can load bots into the game!

    1. Create a network in Hamachi and note the network ID (tutorials can be found online).
    2. Make sure that BakkesMod is running.
    3. Start Rocket League with RLBotGUI (start a match, then quit the match to the menu).
    4. Use the Rocket Plugin to host a LAN match
    5. Press the \"Home\" key to open the Rocket Plugin menu.
    6. Setting a large team size helps, otherwise bots may de-spawn after demos.
    7. Click Host after setting the game options (and password if desired).
    8. Tell your friends to join the match via Hamachi + Rocket Plugin (see below for details).
    9. If they get a message saying that they could not connect to the host, make sure that you're using the same password for the match as your password for private matches or delete your private match password. See this post for details.
    10. In RLBotGUI, set Extra -> Existing Match Behaviour -> Continue And Spawn.
    11. Drag desired bots onto teams in RLBotGUI.
    12. Don't worry about adding Human players in RLBotGUI. Human players can simply join ingame.
    13. Click Start Match in RLBotGUI. Expect the bots to join the teams.

    The setup is basically the same as playing custom maps. If the instructions above are not clear enough, see this video tutorial by Lethamyr.

    "},{"location":"miscellaneous/lan-setup/#instructions-for-clients","title":"Instructions for Clients","text":"

    Use the standard procedure for joining a LAN match via Rocket Plugin. You can find more detailed tutorials elsewhere, here's a short summary:

    1. Open Hamachi and join the host's network via the network ID they tell you.
    2. Right-click on the host and click \"Copy IPv4 Address\".
    3. Open Rocket League
    4. Open the Rocket Plugin menu with the \"Home\" key.
    5. Under the Multiplayer tab in the \"Join a local game\" section, paste the host's address into the IP Address field and click Join.
    6. The port can be left at its default of 7777.
    "},{"location":"miscellaneous/lan-setup/#option-2-online-splitscreen-steam-or-epic","title":"Option 2 - online splitscreen (Steam or Epic)","text":""},{"location":"miscellaneous/lan-setup/#requirements_1","title":"Requirements","text":"
    • Parsec
    "},{"location":"miscellaneous/lan-setup/#instructions-for-host_1","title":"Instructions for Host","text":"

    Only the host can loads bots into the game!

    1. Start Rocket League with RLBotGUI (launch a match, then quit the match to the lobby).
    2. Create a Parsec room and have your friends join
    3. Start new match with bots and players
    4. Have friends join appropriate team
    "},{"location":"miscellaneous/lan-setup/#instructions-for-clients_1","title":"Instructions for Clients","text":"
    1. Join Parsec room
    2. Press Start to join local Rocket League lobby
    3. Join appropriate team
    "},{"location":"miscellaneous/missing-pages/","title":"Missing pages","text":"

    The following wiki pages are not moved yet:

    • Deploying Changes (maybe this should stay on the github wiki?)
    • Remote RLBot (isn't this very outdated?)
    • Setup Instructions (current) (self-explanatory)
    "},{"location":"miscellaneous/rlbot-specific-game-settings/","title":"Rlbot specific game settings","text":"

    RLBot has the ability to change game settings only when RLBot is active. This can be useful when a different environment is desired for developing or running bots compared to playing the game yourself.

    This is achieved by briefly altering TASystemSettings.ini as RLBot starts up Rocket League. This feature is currently only available on windows, and for the default TASystemSettings.ini location of %USERPROFILE%\\Documents\\My Games\\Rocket League\\TAGame\\Config.

    To have settings that only apply when using RLBot, a TASystemSettings.RLBot.ini file has to be created in the same folder as TASystemSettings.ini. This file does not need to be a full copy of TASystemSettings.ini, but should only contain the differences with TASystemSettings.ini to improve compatibility with Rocket League updates. When RLBot starts up, the changes found in TASystemSettings.RLBot.ini will be temporarily applied to TASystemSettings.ini.

    The remainder of this page contains some example use cases.

    "},{"location":"miscellaneous/rlbot-specific-game-settings/#cap-the-in-game-fps-to-120-for-rlbot-uncap-the-fps-during-normal-play","title":"Cap the in game FPS to 120 for RLBot, uncap the FPS during normal play","text":"

    This is useful to create the most consistent environment for RLBot. See Tick Rate for more info.

    • The FPS will have to be uncapped during normal play. This is achieved by setting AllowPerFrameSleep=False in TASystemSettings.ini.
    • In the game pause screen, the fps cap has to be set to 120 exactly.
    • TASystemSettings.RLBot.ini should contain the following configuration to turn the FPS cap back on for RLBot:
    [SystemSettings]\nAllowPerFrameSleep=True\n
    "},{"location":"miscellaneous/rlbot-specific-game-settings/#other-useful-settings-for-bot-testing","title":"Other Useful Settings For Bot Testing","text":"

    in [SystemSettings]:

    • ResX=1280 (Change the x value of your resolution)
    • ResY=720 (Change the y value of your resolution)
    • Fullscreen=False (False for window mode, True for fullscreen)
    • Borderless=True (enable borderless for windowed mode aka Fullscreen=False)
    "},{"location":"miscellaneous/workshop-custom-maps/","title":"Workshop custom maps","text":""},{"location":"miscellaneous/workshop-custom-maps/#automated-solution","title":"Automated Solution","text":"

    RLBot has built in support for custom maps. It allows you to select a folder that has custom map (`*.upk) files anywhere in the directory. Once added, you can select any of the custom maps in the directory and play with bots on that map.

    "},{"location":"miscellaneous/workshop-custom-maps/#steps","title":"Steps","text":"
    1. Run RLBot. Add -> Load Folder and select a directory with custom maps
    2. In Match Settings, click on the \"Map\" dropdown and you should see all the *.upk files listed there.
    3. Select and press \"Start Match\"
    "},{"location":"miscellaneous/workshop-custom-maps/#manual-solution","title":"Manual Solution","text":"
    1. Find the workshop map you want to use. It will be located at \\Steam\\steamapps\\workshop\\content\\252950 Find the map you want inside one of those folders. The map has a .udk extension.

    2. Change the map name to Labs_Underpass_P.upk. Be sure to change the extension as well.

    3. Copy the map to C:\\Program Files (x86)\\Steam\\steamapps\\common\\rocketleague\\TAGame\\CookedPCConsole. It will replace the Underpass map.

    4. On RLBotGui select Underpass to play the custom map.

    "},{"location":"troubleshooting/antivirus-notes/","title":"Antivirus notes","text":"

    If RLBotGUI can't open, won't start a match, or acts in other strange ways it may be related to your antivirus software. Do not disable your antivirus.

    "},{"location":"troubleshooting/antivirus-notes/#if-you-suspect-your-antivirus-has-broken-rlbot","title":"If you suspect your antivirus has broken RLBot:","text":"
    1. Press Windows + R, and type in %localappdata%\\RLBotGUIX and then press Enter
    2. Delete the folders Python37 and venv
    3. Redownload RLBotGUI if necessary
    4. Create an exception for RLBotGUI in your antivirus software. The executable is located at C:\\Program Files\\RLBot
    5. Launch RLBotGUI

    You might also be having a problem with your firewall. Windows Defender Firewall has been known to wrongly block RLBotGUI.exe in the past. To fix this problem:

    1. Go to Control Panel
    2. System and Security
    3. Under Windows Defender Firewall, click \"Allow an app through Windows Firewall\"
    4. Click \"Change settings\" (In the top-left-ish)
    5. Click \"Allow another app\" (In the bottom-left-ish)
    6. Navigate to RLBotGUI and select it.
    7. Click \"Network types...\"
    8. Make sure that both Private and Public networks are checked
    9. Click \"OK\"
    10. Click \"Add\"
    11. Click \"OK\"

    You're done!

    "},{"location":"troubleshooting/installation-errors/","title":"Installation errors","text":""},{"location":"troubleshooting/installation-errors/#you-are-using-a-third-party-antivirus","title":"You are using a third-party antivirus","text":"

    RLBotGUI may open for a second before closing, it may install but fail to work, or produce other weird behavior. A list of known antivirus-related error messages is listed down below under Miscellaneous Issues

    1. Check out our other wiki page: Antivirus Notes
    "},{"location":"troubleshooting/installation-errors/#rlbotgui-gets-stuck-updatingcollecting-packages-during-installation","title":"RLBotGUI gets stuck updating/collecting packages during installation","text":"

    This usually happens because of:

    1. slow internet (try giving it 5 minutes)
    2. pip (python's package installer) broke

    If you've given it time and nothing's happened:

    1. Restart your computer and try again
    2. If that doesn't work, delete pip's cache folder located in %localappdata%/pip and try again
    "},{"location":"troubleshooting/installation-errors/#problems-starting-a-match","title":"Problems starting a match","text":"

    Check the console window for any error messages.

    "},{"location":"troubleshooting/installation-errors/#encountered-a-std-exception-listen","title":"Encountered a std Exception: listen","text":"

    Another program is preventing RLBot from talking to Rocket League.

    1. Restart your computer
    "},{"location":"troubleshooting/installation-errors/#encountered-a-std-exception-unknown-error","title":"Encountered a std Exception: Unknown Error","text":"

    A Bakkesmod plugin that you are using isn't compatible with RLBot.

    1. Disable Bakkesmod
    2. Restart Rocket League and RLBotGUI
    "},{"location":"troubleshooting/installation-errors/#the-game-is-open-but-no-match-started","title":"The game is open but no match started","text":"
    1. Ensure you started with Rocket League closed. RLBotGUI has to launch it for you
    2. Check for the above errors in the console
    3. Check your antivirus to ensure it didn't delete RLBot's files
    "},{"location":"troubleshooting/installation-errors/#the-game-doesnt-launch-and-theres-no-error-in-the-console","title":"The game doesn't launch and there's no error in the console","text":"
    1. Ensure you set RLBotGUI to launch from the correct (Steam/Epic) platform.
    "},{"location":"troubleshooting/installation-errors/#javalangruntimeexception-javaniocharsetmalformedinputexception-input-length-1","title":"java.lang.RuntimeException: java.nio.charset.MalformedInputException: Input length = 1","text":"

    This currently happens to people with strange letters/characters in their Steam username.

    1. Change your steam username
    "},{"location":"troubleshooting/installation-errors/#miscellaneous-issues","title":"Miscellaneous Issues","text":""},{"location":"troubleshooting/installation-errors/#common-antivirus-related-error-messages","title":"Common Antivirus-related error messages","text":"
    • FileNotFoundError [WinError 2]: The system cannot find the file specified
    • Please check that the file exists and your antivirus is not removing it
    • Windows: OSError: [WinError 1450] Insufficient system resources exist to complete the requested service
    • Encountered exception: [WinError 5] Access is denied
    • [WinError 225] Operation did not complete successfully because the file contains a virus or potentially unwanted software

    For all of the above:

    1. Check out our other wiki page for this issue: Antivirus Notes
    "},{"location":"troubleshooting/installation-errors/#cannot-proceed-because-vcruntime140dll-was-not-found","title":"Cannot proceed because VCRUNTIME140.dll was not found","text":"

    Your computer may be missing some important files, which you can download from here:

    • https://go.microsoft.com/fwlink/?LinkId=746572
    • https://go.microsoft.com/fwlink/?LinkId=746571
    "},{"location":"troubleshooting/installation-errors/#application-error-the-application-was-unable-to-start-correctly-0xc000007b","title":"Application Error: The application was unable to start correctly (0xc000007b).","text":"
    1. Restart your computer
    "},{"location":"troubleshooting/installation-errors/#frame-stuttering-when-using-rlbot","title":"Frame stuttering when using RLBot","text":"
    1. Restart your computer
    2. Close or disable DropBox if it is running
    "},{"location":"troubleshooting/installation-errors/#bot-development-issues","title":"Bot development Issues","text":""},{"location":"troubleshooting/installation-errors/#python-acting-super-weird","title":"Python Acting Super Weird","text":"

    Sometimes on Windows 10, ~\\AppData\\Local\\Microsoft\\WindowsApps will end up on your system path, which supplies a fake python.exe taking you to the Microsoft Store. This causes bizarre things to happen, e.g. nothing at all being printed when you run python --version.

    You can confirm whether this is happening to you by opening a command prompt and running where.exe like this:

    >where.exe python\nC:\\Users\\tareh\\AppData\\Local\\Microsoft\\WindowsApps\\python.exe\n

    If it shows the Microsoft\\WindowsApps\\python.exe one at the top, you need to fix it. You can try this

    "},{"location":"troubleshooting/installation-errors/#javalangunsatisfiedlinkerror-a-dynamic-link-library-dll-initialization-routine-failed","title":"java.lang.UnsatisfiedLinkError: A dynamic link library (DLL) initialization routine failed.","text":"
    1. Run your .bat files as administrator to get past this error.
    "},{"location":"troubleshooting/installation-errors/#could-not-locate-a-suitable-bot-class-in-module","title":"Could not locate a suitable bot class in module","text":"

    This means that your bot's python file was found, but there's something messed up in it.

    1. Ensure you saved the file
    2. Check to make sure your bot extends the framework's agent class
    "},{"location":"troubleshooting/installation-errors/#could-not-find-a-version-that-satisfies-the-requirement-pyqt5","title":"Could not find a version that satisfies the requirement PyQt5","text":"

    Your system might be using python 2 instead of python 3. This can happen even if you successfully installed python 3 and added it to your path. Verify whether this is the case by running python --version. If it says python 2, try these:

    1. Make sure you've installed python 3 and chosen \"Add to PATH\" during the installation.
    2. Open the windows \"environment variables\" dialog and make sure that python 3 is listed before python 2.
    "},{"location":"troubleshooting/installation-errors/#scratch-the-project-file-that-was-selected-failed-to-load","title":"Scratch: The project file that was selected failed to load.","text":"

    We're using Scratch 3.0 which is pre-release and a bit buggy. Sometimes the save gets corrupted. Here's how to avoid that, and recover your file if it does get corrupted:

    • If you save a vector in a variable then save your project, it will be broken.
    • If you somehow insert null values into a list then save your project, it will be broken.

    General strategy for recovering the file:

    1. Hit F12 in your browser to view the javascript console and read the error that appears when you try to upload the broken file. It will look something like this:
    gui {\"validationError\":\"Could not parse as a valid SB2 or SB3 project.\",\"sb2Errors\":[{\"keyword\":\"required\",\"dataPath\":\"\",\"schemaPath\":\"#/required\",\"params\":{\"missingProperty\":\"objName\"},\"message\":\"should have required property 'objName'\"}],\"sb3Errors\":[{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf/0/type\",\"params\":{\"type\":\"string\"},\"message\":\"should be string\"},{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf/1/type\",\"params\":{\"type\":\"number\"},\"message\":\"should be number\"},{\"keyword\":\"oneOf\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/definitions/stringOrNumber/oneOf\",\"params\":{\"passingSchemas\":null},\"message\":\"should match exactly one schema in oneOf\"},{\"keyword\":\"type\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/oneOf/1/type\",\"params\":{\"type\":\"boolean\"},\"message\":\"should be boolean\"},{\"keyword\":\"oneOf\",\"dataPath\":\".targets[0].lists['g*`|xWn5EppiH.9NKPVF'][1][0]\",\"schemaPath\":\"#/oneOf\",\"params\":{\"passingSchemas\":null},\"message\":\"should match exactly one schema in oneOf\"}]}\n
    1. Your sb3 is really a zip file, so unzip it and look inside project.json.
    2. Search for xWn5EppiH.9NKPVF and see if there's anything funky saved in it, and manually make a fix. For a list, you could delete the list items. For a variable, you could set it to \"\".
    3. Then put the fixed version of project.json back in the zip and try uploading again.
    "},{"location":"troubleshooting/installation-errors/#import-errors","title":"Import errors:","text":"

    If you run into an import error that works fine when testing outside of rlbot but crashes when loading your agent, it can most often be solved by simply moving the import statement to your agent's init method. This is helpful for libraries such as tensorflow and rlutilities

    "},{"location":"troubleshooting/installation-errors/#old-issues-that-are-probably-irrelevant","title":"Old issues that are probably irrelevant","text":""},{"location":"troubleshooting/installation-errors/#pip-is-not-recognized-as-an-internal-or-external-command","title":"'pip 'is not recognized as an internal or external command","text":"

    Something blocked RLBotGUI from installing Python on the first try, and you have to reinstall by following these steps:

    1. Press Windows + R, and type in %localappdata%\\RLBotGUIX and then press Enter
    2. Delete the folders Python37 and venv
    3. Relaunch RLBotGUI.exe
    "},{"location":"troubleshooting/installation-errors/#the-term-expand-archive-is-not-recognized-as-the-name-of-a-cmdlet","title":"The term 'Expand-Archive' is not recognized as the name of a cmdlet","text":"

    You are using an older version of Windows and must manually perform some of the installation with the following steps:

    1. Download our copy of Python from here
    2. Press Windows + R, type in %localappdata%\\RLBotGUIX and then press Enter
    3. Create a new folder called Python37 and open the folder
    4. Find the zip file of Python you downloaded and double click it
    5. Drag the contents from the zip file into the folder Python37
    "}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index dcbbae6..a2cf469 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ diff --git a/troubleshooting/antivirus-notes/index.html b/troubleshooting/antivirus-notes/index.html index 70dca78..1730660 100644 --- a/troubleshooting/antivirus-notes/index.html +++ b/troubleshooting/antivirus-notes/index.html @@ -921,6 +921,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + + diff --git a/troubleshooting/installation-errors/index.html b/troubleshooting/installation-errors/index.html index 6e9f596..e694854 100644 --- a/troubleshooting/installation-errors/index.html +++ b/troubleshooting/installation-errors/index.html @@ -919,6 +919,26 @@ + + + + + +
  • + + + + + RLBot v5 (Beta) Overview + + + + +
  • + + + +