The base code of a Unity Pong game to be used for Reinforcement Learning with Unity ML-Agents.
- Make sure you have Git installed on your machine and are signed into GitHub with your Git client
- Fork this repository
- In your designated project folder, open Git Bash (or your terminal) and type
git init -b main
. It should create a new local repository - Then type:
git remote add origin <GITHUB REPO URL>
. You can find the repo URL from hitting the green "Code" at the top right of the repository on GitHub. It will probably be something along the lines ofhttps://github.com/<USERNAME>/Pong-Base.git
- Now do
git pull origin main
. If all has went well, you now have the code (and this file!) in your local repository on your machine!
Directory: Assets/Source/Scripts/Pong/
(contains all the relevant game logic)
In order for us to sufficiently implement RL to this game, we need to know how the game works. Some things to note:
- This will be for an RL project, so not all of the scripts in this directory are important for our purposes!
- Ignore any files ending in
.meta
. They are auto-generated by Unity - You might come across a class called
ControlledGameObject
that pops up over and over again. It is just a single wrapper class for aGameObject
and a designated controller, but if you are curious, you can find it inAssets/Source/Scripts/UnityUtils/
(which contains a single wrapper class) - The point is to dip your toes in the water and explore what happens! Have Fun!
Note: Assume the parent directory is Assets/Source/Scripts/
, so if I mention Pong/
, I really mean Assets/Source/Scripts/Pong/
.
- Namespaces: I won't go into detail on the specifics, but if a script contains a declaration with namespace
Pong
, then everything within that declaration is known asPong.<INSERT NAME OF FUNCTION, VARIABLE, CLASS, ETC.>
. Then, other files may have to specifyusing Pong;
to gain access to everything within the namespace. If you know packages and imports from other languages, this is essentially the same thing. It is a great way to stay organized. - Partial Classes: In a namespace (or none), you can define a
partial class
and only partially define the class, so you can define the rest of it in some other file. This is usually not a good practice, but in this project, the way it is used keeps everything organized as you will see.
- Viewport: Viewport essentially means something you can see inside; a "view" that can be "ported". Within the context of this project, the viewport is essentially the whole screen view itself. Within the code, if certain things mention "viewport" and are dealing with numerical values, those numerical values correspond to percentages of the viewport size (width and height). So for example,
Vector2(0.25f, 0.5f)
would correspond to 25% of the horizontal screen size and 50% of the vertical screen size. - Vectors:
Vector2(...)
= 2D vector,Vector3(...)
= 3D vector
The code has been formatted in a very specific way to be more readable. This is NOT a C# convention, but for the purposes of our project, it is what we call a "business rule". Here's how it works:
- From
Pong/
and all of its subfolders, they each correspond to anamespace
. Examples:Pong/
corresponds to the namespacePong
,Pong/Ball/
corresponds to the namespacePong.Ball
,Pong/GamePlayer/
corresponds to the namespacePong.GamePlayer
,Pong/GamePlayer/Force/
corresponds toPong.GamePlayer.Force
, etc. - "Header" Files: In
Pong/
and all of its subfolders, there will be a C# file called_<NAMESPACE-NAME>.cs
. It starts with an underscore (_
) and what follows is the namespace name, but having periods (.
) replaced with dashes (-
). Examples:Pong/_Pong.cs
,Pong/GamePlayer/Pong-GamePlayer.cs
,Pong/Ball/Pong-Ball.cs
,Pong/GamePlayer/Force/Pong-GamePlayer-Force.cs
, etc. These are what I call "Header" Files. If you know C/C++, a bell might ring in your head. Yes, this is the same idea. Basically, what goes into the header file is all the important class declarations to be used later on, in order to give a "bird's eye view" of everything important in the namespace. This typically just corresponds to seeing the files in the same directory. I encourage you to explore these when you ge the chance
- All header files are important
Pong/_Pong.cs
: Contains all constants, cached global variables, and a few helper functionsPong/GameManager.cs
: Runs the whole game logic. Starts up the game invoid Start()
and you can also adjust the default cached variable values from itspublic
fieldsPong/GamePlayer/Player.cs
: Centralized control of the Player and everything closely associatedPong/GamePlayer/PlayerController.cs
: contains movement controls for a playerPong/GamePlayer/PlayerData.cs
: Not important right now, but just know that this will be where data is fed into our RL agentPong/Ball/PongBall.cs
: Behavior for the PongBall 🏀Pong/Ball/PongBallController.cs
: movement for the ball. Also communicates withPongBall.cs
Pong/Physics/RectangularBodyFrame.cs
: manual collision detection. Not THAT important for our purposes, but you should know that it is therePong/RL/DataUnit.cs
: Not important right now, but just know that this will be what is fed into our RL agent
This README will cover these more in-depth soon, but here is a high-level overview of what you'll be doing:
- Code Exploration: Exploring the code and trying to form a theory on how it works
- Testing: Brief explanation of what happened when you modified/added an aspect of the program. Can't explore without testing what happened!
- Documentation: C#-styled XML docs on something of your choice after you have done the previous 2
- Pushing: Push to your forked repository Your brief writeup will include experiences you've had in these aspects (will be mentioned as we go more in-depth).
In your submissions, you will have to show proof that you explored a portion of the code, at least at a high-level. Here's what you're gonna do:
- Make sure you have already looked through all the important sections of the codebase, even if you skimmed it
- Choose 3 non-header files from the list above that you think are very important to the overall flow of logic to briefly write about. In addition, you are required to do this for the header files
Pong/_Pong.cs
,Pong/GamePlayer/_Pong-GamePlayer.cs
, andPong/Ball/Pong-Ball.cs
. - Briefly (3 sentences max) explain the purpose of each of these files and why you think they are so important to the overall game logic. For each file, also include:
- If the file is not a header file (so just a class definition), write the names of what you think the most important variables and methods are that illustrate why the class is so important, accompanied by a single phrase that describes what they do. Example of doing that with an important method in
PongBall.cs
:Serve()
, which serves the ball at a slightly random angle - If the file is a header file, then do the same as the previous bullet point, but instead of methods and variables, do classes and variables
In order to explore the codebase, you need to test it and see what happens when you do something. By interacting with it, you get a better idea on how it works. Your writeup should include at least 3 examples of:
- how/where you modified/added an aspect of the program
- the effect/what changed
- (optional) anything you've learned from it about how the program works So basically: "What did you do and what happened as a result?"
Documentation is one of the most important portions of collaborative programming. This is a vital step for our future level 2 projects. We will be using the .NET XML docs (similar to javadocs) Task: Choose 3 non-header files and 3 header files (they can be the same as in your code exploration). For non-header files:
- Choose a few methods within the class (they can be the same as in your code exploration) and annotate them within the code by writing in this .NET XML format above the method as follows (short summary of what the method does, and what it returns):
/// <summary>
/// An example method that returns 1
/// </summary>
/// <returns>A 32-bit integer. Has no real meaning, as this is just an example.</returns>
public int exampleMethod() { return 1; }
For header files:
- For all the classes in the header file, put this above it
/// <summary>
/// Write a short summary of the class here
/// </summary>
public partial class ExampleClass {}
Let's push your changes to the remote repository. Open up your git client in the project directory and:
git status
to check what has changedgit add .
to stage all the changesgit commit -m "<YOUR MESSAGE>"
to commit. Write a commit message that makes sense and not just "Taco Bell is mid".git push origin main
to push changes to the remote repository
You are going to open up a Pull Request to THIS repository (the CSAI one, not your fork). To do this:
- Go to the GitHub page where your fork of this repo is stored
- On top, it will say something like "X commits ahead of calpoly-csai:main"
- Now click 'Open pull request'
- The rest of this is like an email:
- Make the 'subject' in the format
FirstName_LastName: PongRL Week 1
- Make the 'content' of it your writeup. It should include Code Exploration, Testing, and Labeling which files and methods you documented (for header files, you only have to include which file it was). See WriteupTemplate.md in this repo and use it as a template
It's OK if you are confused. It is only by pushing through adversity that we learned. If it was really that easy, is there any learning being done at all by staying in your comfort zone?
A few resources:
- The
#projects
channel on our Discord. The main way you can ask questions is there. - LLMs like ChatGPT, Bing Chat, GPT-4, Bard, MPT, Falcon, Character.AI, RedPajama
- Search Engines like Google, Bing, Brave, phind.com (AI search engine for developers)
- Stack Overflow (the website)
- YouTube
- This README document itself contains quite the gold mine of info