By now you have built real things while working through this curriculum: data structures, small gameplay systems, maybe a shader or a tool. None of that work does anything for you in a hiring process unless someone outside your own head can see it, understand what you built, and judge whether you could do it again on their team. That is the entire job of a portfolio (a curated public collection of your work, built to be judged by strangers on a deadline). This section covers what a hiring team is actually checking for when they open your portfolio, why quality beats quantity by a wide margin, what a strong piece looks like for each of the main programming and art tracks, why presentation carries roughly half the score, how to write about a project so a stranger understands it in under a minute, how to make your code and your README readable by someone who has never seen your codebase before, where to actually put this work online, and a realistic plan for building your first portfolio once you finish this curriculum.
A resume line that says "worked with Unity, C#, git" tells a hiring team nothing they can verify. Anyone can type that sentence whether or not it is true. A portfolio piece is different: it is a link they can open, right now, and check for themselves. That difference is the whole reason a portfolio matters more than a list of claims.
When a reviewer opens your portfolio, they are really checking two things, and almost everything else in this section exists to help you prove both of them.
There is a third, quieter thing being checked at the same time: how much of your own time you are willing to spend making something easy for someone else to evaluate. A reviewer with a stack of applications does not owe you the effort of digging through a messy repository to find the interesting part. Section 8 and Section 10 come back to this directly, but it starts here, with a fact worth sitting with: a typical reviewer spends somewhere between thirty seconds and two minutes deciding whether to look closer at any one portfolio.
Nothing about that timeline is unfair or lazy on the reviewer's part. A studio hiring for one open role can receive hundreds of applications. The thirty-second skim is not a rejection of your effort — it is a filter, and your job is to make sure the first thirty seconds of your portfolio survive it.
Open the GitHub profile of almost any beginner and you will see a familiar pattern: twelve to twenty repositories, most named something like Unity-Tutorial-Follow-Along, MyGame, or MyGame2-final-FINAL. The commit history usually tells the real story: a burst of commits on day one and day two, then nothing. No README, or a README that still says "TODO: write description." No video, no screenshot, sometimes no way to even run the project without already knowing which scene to open.
This is not a character flaw. It happens because following a tutorial feels productive — you are typing code, the video is always making visible progress, and at the end of each session you have more lines than you started with. But following a tutorial is a different skill from building something from a blank file and making your own decisions when it breaks in a way the tutorial never covered. A tutorial, even completed exactly as shown, mostly proves you can follow instructions. It does not prove you can debug your own design choices, and debugging your own design choices is what the job actually is, every day.
None of this means tutorials are a waste of time. They are one of the fastest ways to learn a new technique, and this curriculum itself has used plenty of small guided examples for exactly that reason. The mistake is treating a finished tutorial as a portfolio piece. It becomes one only if you take it much further than the tutorial went: change the mechanic, add a system the tutorial never covered, rebuild a core piece your own way, and then be honest in the writeup about which parts were guided and which parts were yours.
This is the single most important rule in this section, and it is worth explaining why it is true rather than just stating it. A reviewer's time is the scarce resource in this whole process, not your project count. Ten abandoned projects cost the reviewer ten clicks, and after the second one that does not run or shows nothing past day two, they stop clicking — not out of spite, but because nine failed clicks in a row is a completely reasonable reason to stop trusting the tenth link. Three finished, polished projects cost three clicks, and every single one of them rewards the click with something real to look at, play, or read. The second pattern builds trust with every click; the first destroys it.
There is a second reason quality wins, one that has nothing to do with the reviewer's patience. Finishing a project is what surfaces the hardest twenty percent of the work: the boring edge-case bugs, the moment where the mechanic technically works but feels wrong and you have to figure out why, the polish pass that turns "it runs" into "it does not embarrass you." Tutorials are structured to skip almost all of that twenty percent, because a tutorial's job is to get you to a working result on a schedule, not to make you sit with an ugly, half-working system until you understand why it is ugly. That twenty percent is exactly the part that separates a hobbyist from someone ready to sit on a team, and it only shows up if you push a project all the way to done.
A useful rule of thumb follows directly from this: if a project is not finished enough that a stranger could open it and understand what it does within about two minutes, without you standing next to them explaining it, it is not a portfolio piece yet. It is a work in progress, and Section 12 covers a different, lower bar that applies to those instead.
A gameplay programming piece is judged on two things at once: whether the mechanic feels good, and whether the code behind it is visible and reasoned about. A strong piece is almost never a whole game. It is one small, tight mechanic done really well — a jump, a dash, a dodge roll, a grapple hook, a gravity-flip. Trying to ship a whole game with five systems, each done at sixty percent quality, produces a weaker portfolio piece than one mechanic done at ninety-five percent, for the same reason a three-course meal where every dish is slightly undercooked is worse than one dish cooked perfectly.
"Feels good" is not vague marketing language here — it is a specific, learnable set of techniques, and naming them in your writeup is part of proving you understand what you built. Two of the most common ones for movement:
A strong write-up for a gameplay piece names the specific numbers you tuned, not just the fact that tuning happened: "coyote time started at 0.05 seconds and felt unresponsive in playtesting, I moved it to 0.12 seconds and it felt fair without letting the player cheat obvious late jumps." That single sentence proves iteration happened, which is worth more to a reviewer than a claim that the mechanic "feels great."
The code matters just as much as the feel, and it needs to be easy to find. Link straight to the one file that matters — for a jump mechanic, that might be a single PlayerController.cs or JumpSystem.cs — rather than making the reviewer dig through a whole repository during their thirty-second skim. Section 10 covers exactly how to make that one file readable once they open it.
A graphics piece is judged on whether you can explain a rendering technique in your own words, not just on whether the final image looks cool. A pretty screenshot alone proves almost nothing — anyone can download a shader from an asset store and take a screenshot of it. The proof of understanding comes from three things together: a clear before image, a clear after image, and a written explanation of the technique that shows you know why the after image looks the way it does.
Notice what that written explanation does not do: it does not just say "I added rim lighting." It describes the actual geometric idea (the angle between the surface normal and the view direction) and the actual visual result (brighter at grazing angles, fading straight on). That level of detail is what separates "I understand this technique" from "I followed a tutorial and it worked."
A strong graphics write-up also names the tradeoffs, not just the win. Why this approach over an alternative — for example, why a screen-space technique over a per-vertex one, or why you chose a cheaper approximation over a physically accurate one, and what that approximation costs you in edge cases. Naming a tradeoff on purpose is one of the clearest signals of real understanding a graphics reviewer can see in a short write-up.
Tools programming has a presentation problem the other tracks do not: the work is often invisible unless you go out of your way to demonstrate it. A gameplay reel or a before/after shader image speaks for itself. A level-editor extension, a batch-renaming script, or a build pipeline improvement does nothing visually interesting on its own — its entire value is a workflow it replaces, and a workflow is something you have to actually show happening, not something a screenshot can capture.
The strongest possible proof for a tools piece is a short screen-recorded video that shows the before and the after back to back: "here is this task done the manual, old way, taking this long — here is the same task done with my tool, taking this long." A concrete example: a tool that batch-renames and re-numbers a folder of level files so they sort correctly in the engine. Manually, a designer might spend fifteen minutes dragging and renaming forty files one at a time, prone to mistakes. With the tool, the same result takes one button press and a few seconds. That contrast, watched rather than described, is what makes a reviewer understand the value instantly.
A technical artist sits between art and code, and a strong piece has to show both halves of that bridge. Most artists show only the finished, pretty result. A technical artist portfolio piece needs to also show the how, because the whole point of the role is producing a technique that other artists on a team can reuse and adjust, not a one-off final image.
Two specific formats do this well. A breakdown is a step-by-step image sequence showing an effect being built up in layers — for example, a fire effect shown as a bare particle shape, then with color gradient added, then with distortion, then with the final glow pass — so a viewer can see exactly which layer contributes what. A node graph is the visual scripting graph itself (a shader graph, a material graph, a Blueprint-style graph), shown with your own annotations explaining what each node does and why it is connected the way it is.
An annotated graph like this does something a final render alone cannot: it lets a reviewer verify, node by node, that you understand what each piece of the graph is doing, rather than trusting that the pretty result was not assembled by trial and error until it happened to look right. Both are valid ways to build something, but only one of them proves you could rebuild it, tune it, or teach it to someone else — which is exactly what a technical art role asks you to do.
Two portfolio pieces with identical underlying quality can get completely different reactions depending on how they are presented, and it is worth being direct about why: a reviewer skimming dozens of applications in an afternoon cannot tell the difference between "no project" and "a good project explained badly." A wall of text with no visuals reads as a wall of text, regardless of how good the mechanic underneath it actually is. Presentation is not decoration on top of the real work — for the first thirty seconds of a reviewer's attention, presentation is the real work, because it is the only part they will actually see.
The recipe, in order, top to bottom on the page:
Video and GIFs come before text for a concrete reason, not just habit: a still screenshot of a movement or feel-based mechanic is nearly useless, because you cannot see feel in a still image. A shader needs to be seen changing under motion and lighting. A tool needs to be seen inside the actual workflow it speeds up. Video is the only medium on this list that can actually prove a claim like "it feels good" instead of just asserting it, which is exactly the kind of evidence Section 1 said a reviewer is looking for.
A project write-up has one job: let a stranger who has never seen your code understand, in under a minute, what you built, why you built it that way, and what you learned doing it. The four-part structure below does that job reliably, in roughly the same order a curious reviewer's questions would naturally come up.
Here is a write-up almost every beginner has written at some point. It is not wrong, exactly — it just says nothing a reviewer can use to judge anything.
This is a cool platformer game I made using Unity. It has jumping
and enemies. I used C# for the scripts. Check it out, link below!
Read that as a reviewer would: it does not say what problem the jump was solving, what made it hard, or what the writer would change. It could describe a five-hour weekend project or a five-month one — there is no way to tell, and a reviewer will not spend their own time guessing.
Same project, same code even, rewritten using the four-part structure from the diagram above:
Problem
I wanted a jump that felt as responsive as the platformers I grew up
playing, where a jump pressed slightly after leaving a ledge still works.
Approach
I built a custom CharacterController2D instead of using Unity's
built-in physics jump, so I could control exactly when a jump is
allowed. I added a 0.12-second "coyote time" window after leaving
a platform, and a 0.15-second input buffer so a jump pressed just
before landing still fires the moment you land.
What was hard
My first version buffered the input but did not clear it correctly,
so a single jump press could fire twice if the player landed and then
walked off a second ledge quickly. I found the bug by logging every
jump event with a timestamp and noticing two fired within one frame.
I fixed it by clearing the buffer the instant a jump is consumed,
instead of only clearing it after the buffer window expired.
What I would do differently
I would add a small automated test for the buffer-clearing logic.
I found the double-jump bug by manually playing the game for about
twenty minutes, which is not a reliable way to catch a timing bug
this specific, and I got lucky that I noticed it at all.
Nothing about the underlying project changed between the two versions — same jump, same bug, same fix. What changed is that the second version gives a reviewer four separate, concrete things to judge: a real design decision (coyote time and input buffering, named specifically), a real bug with a real cause, a real debugging method (logging with timestamps, not guessing), and real self-awareness about what a better process would have looked like. Each of those is worth more to a hiring decision than the sentence "it has jumping and enemies."
The "what was hard" section deserves special attention, because it is often the most convincing part of the whole write-up and the part beginners are most tempted to skip. Naming a real difficulty, honestly, is more convincing to an experienced reviewer than claiming everything went smoothly — because everyone who has shipped anything knows nothing ever goes perfectly smoothly, and a candidate who claims otherwise reads as either inexperienced or not fully honest about their own process. A specific, well-described bug is a stronger portfolio signal than a project that supposedly had none.
Your code has two different readers, and both of them need to succeed with almost no effort or the piece gets marked down regardless of how good the underlying mechanic is. The first reader skims your code for about sixty seconds without running it, just reading. The second reader clones the repository and actually tries to build and run it. Section 9 covers what to write about a project; this section covers making the project itself survive contact with both of those readers.
This compiles, works, and does exactly what the strong write-up in Section 9 describes. It is still a bad portfolio file, because nobody skimming it for sixty seconds can tell what it does.
public class GC : MonoBehaviour {
public float f = 9.8f;
bool g = false;
void Update(){
if(Input.GetKeyDown(KeyCode.Space)){
g=!g;
Physics.gravity = g ? new Vector3(0,f,0) : new Vector3(0,-f,0);
}
}
}
A reviewer looking at this has to reverse-engineer what GC and f and g mean before they can even start judging whether the logic is good. That reverse-engineering time comes directly out of the sixty seconds Section 1 said you have.
public class GravityController : MonoBehaviour
{
[SerializeField] float gravityStrength = 9.8f;
bool isFlipped = false;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
FlipGravity();
}
// Flips world gravity between pointing down (normal) and up (flipped).
void FlipGravity()
{
isFlipped = !isFlipped;
float direction = isFlipped ? 1f : -1f;
Physics.gravity = new Vector3(0f, gravityStrength * direction, 0f);
}
}
Same logic, same number of real ideas, but a reviewer can now read the class name, the field names, and the one comment, and understand what this file does before reading a single line of the method body carefully. Good names and one well-placed comment did almost all of the work here — the comment explains why the ternary picks a direction, which is not obvious from the code alone, rather than just restating what the line already says.
// set isFlipped to the opposite of isFlipped above the line isFlipped = !isFlipped;. That comment adds reading time without adding any information the code did not already give. Save comments for the parts that are not obvious from the code by itself — the "why," not the "what."A README is the file a repository shows first, and for a portfolio piece it should answer, in order: what is this, what does it look like, how do I play it or run it, and what did the author learn. A reviewer who clones your repository and finds no README, or one that only says the project's name, has no way to know whether the project even works without digging through source files themselves — and per Section 1, they will not.
# Gravity Snap
A small puzzle-platformer where the player flips gravity to solve
rooms. Built solo in three weeks with Unity 2022 (C#).
[ GIF of the gravity-flip mechanic goes here ]
## Play it
- Browser build: https://username.itch.io/gravity-snap
- Video walkthrough: https://youtube.com/watch?v=xxxxxxx
## What this project is
- 8 hand-built levels
- a custom gravity-flip controller, see Assets/Scripts/GravityController.cs
- a small level editor used to place gravity zones, see Assets/Editor/
## How to run it from source
1. Clone the repo
2. Open the project with Unity 2022.3 LTS
3. Open Scenes/MainMenu.unity and press Play
## What was hard
Making the gravity flip feel instant but not disorienting. See the
"What was hard" section of the itch.io writeup for the three
iterations I tried before landing on the current version.
## What I would change
The level editor works, but only I can use it comfortably. It needs
on-screen labels before anyone else could use it without me
explaining every button first.
Notice the README reuses the exact same four-part structure from Section 9 in its last two headings. That is deliberate, not a coincidence — once you have written the problem, approach, difficulty, and reflection once for the itch.io or website write-up, reusing the same structure in the README is nearly free, and it means the two most important surfaces of your project (the page a reviewer lands on, and the repository they click into) tell a consistent story.
Where you put a finished piece matters almost as much as finishing it, because the wrong host adds friction that stops a reviewer before they ever see the work. Three hosts cover nearly everything a beginner's portfolio needs.
GitHub still matters as the technical anchor — it is where a reviewer who is genuinely interested goes to actually read your code, per the 1:30 mark in Section 1's timeline. But notice where it sits in that timeline: after the video and the GIFs have already earned the reviewer's interest, not instead of them. A GitHub link with no playable build and no visuals attached is asking a reviewer to do all the imagining themselves, which most will not do.
The underlying reason a playable build or a video beats a wall of text is simple: it is proof by demonstration instead of proof by claim. Text can say "the movement feels responsive." A GIF just shows the movement and lets the reviewer judge for themselves whether that is true — which is both more convincing, because they formed the opinion themselves, and faster to evaluate, because judging a three-second clip takes less effort than parsing and trusting a paragraph of description.
Everything so far in this section has been about finished pieces. There is a second, complementary kind of evidence worth building alongside them: a public trail of devlogs (short, regularly posted updates showing a project while it is still being built), posted somewhere visible like an itch.io devlog page, a personal blog, or a social account.
A finished piece proves you can finish something. A devlog trail proves something a single finished piece cannot: that you can sustain effort over weeks, keep working through a mechanic that still feels wrong, and take in feedback along the way rather than only ever showing work after it is already polished. Those are exactly the behaviors a job asks for day to day, far more often than the single dramatic "ship it" moment a finished portfolio piece captures. A reviewer who sees both a finished piece and the messy weekly trail that led to it gets a more complete, and more convincing, picture than either one alone.
Everything above is a lot to hold at once, so here is one concrete order to actually do it in, built directly on the reasoning from the earlier sections.
This plan is deliberately scoped small at every step, on purpose. A beginner who tries to build one impressive, ambitious project as their entire portfolio is taking on exactly the risk Section 3 warned about: one unfinished ambitious project is worth less than three small finished ones, even though the ambitious one sounded better as an idea. Small and finished, three times over, with the same presentation recipe applied each time, is both a realistic plan on a beginner's schedule and, by the reasoning in this whole section, the stronger portfolio.
There is no single correct rewrite — the exercise is checking that the four parts appear, in order, each with specific and concrete content instead of vague claims. Here is one reasonable version:
Problem
Our level designer was spending about fifteen minutes per level manually
renaming and re-numbering exported level files so they would sort
correctly inside the engine, a pure copy-and-rename task with no
creative work in it at all.
Approach
I built an editor window in Unity that scans a folder of level files,
detects their current order from a data file, and renames and
re-numbers them all in one pass with a single button press. I chose
to read the intended order from a small JSON file instead of the
filenames themselves, so the designer could reorder levels without
ever touching a filename by hand.
What was hard
My first version renamed files in place one at a time, which
occasionally caused a naming collision partway through the batch --
for example, renaming file 3 to file 4 before file 4 had been moved
out of the way yet, silently overwriting it. I fixed it by renaming
every file to a temporary name first, then renaming all of them to
their final names in a second pass, so no two files ever collide.
What I would do differently
I would add a confirmation preview showing the old and new names
side by side before applying any rename, since the current version
has no undo and a mistake requires restoring from version control.
Compare this against the original one-sentence description: the rewrite gives a reviewer a real problem with a number attached (fifteen minutes per level), a real design decision with a reason (JSON order file instead of filenames), a real bug with a real cause and a real fix (the rename-collision bug), and a real piece of self-awareness (no undo yet). Any rewrite that hits those same four kinds of content, even with different invented details, satisfies the exercise.
1. Platformer tutorial follow-along, exact copy, unfinished
(stuck on enemy AI).
2. A dash mechanic with proper cancel windows, fully polished,
video recorded, code readable.
3. A Tetris clone, fully finished and bug-free, but no README,
no video, no screenshots -- just raw source code.
4. A shader experiment that compiles but looks identical to a
flat unlit material -- no visible technique to point to.
5. A level-loading tool, finished, with a 40-second demo video
showing the manual workflow next to the tool's workflow.
6. A multiplayer lobby system, about 70 percent done, still has
netcode bugs that must be fixed before it is usable.
7. A rim-light shader, finished, with before/after screenshots
and a written explanation of the technique.
8. A racing game clone, fully finished, but nearly identical to
its tutorial with only one small feature (a boost pad) added.
Keep #2 (the dash mechanic), #5 (the level-loading tool), and #7 (the rim-light shader).
All three share the property Section 3 asked for: finished, and finished with the full presentation recipe from Section 8 already applied or clearly applicable (video, before/after, a written explanation). Between them they also cover three different tracks from Sections 4 through 7, which shows range without diluting quality anywhere.
The other five are cut, each for a specific, nameable reason rather than just "not as good":
A reasonable variation could swap in #3 instead of one of the three if you are willing to spend an afternoon writing its README and recording a quick video first — the underlying project quality is there, it is only the presentation that is currently missing.
# Inventory System
A small inventory system for an RPG prototype: add and remove items,
automatically stack duplicate items into one slot with a count, and
display everything in a grid UI. Built with Unity 2022 (C#).
[ GIF of picking up items and seeing them stack goes here ]
## Play it
- Browser build: https://username.itch.io/inventory-demo
- Video walkthrough: https://youtube.com/watch?v=yyyyyyy
## What this project is
- add/remove items through a simple ItemDatabase, see
Assets/Scripts/Inventory.cs
- automatic stacking for duplicate item types, up to a max
stack size defined per item
- a grid UI that updates live as the inventory changes, see
Assets/Scripts/InventoryUI.cs
## How to run it from source
1. Clone the repo
2. Open the project with Unity 2022.3 LTS
3. Open Scenes/Demo.unity and press Play
4. Walk over the colored cubes to pick up sample items
## What was hard
Keeping the UI in sync with the data without rebuilding the whole
grid every frame. See the "What was hard" section of the itch.io
writeup for how I moved to an event-based update instead of a
per-frame refresh.
## What I would change
Item stacking currently has no per-item maximum stack size in the
data -- every item stacks to 99. I would move max stack size into
the ItemDatabase so different item types could have different limits.
A few things this answer is checking for, beyond just filling in the template: the one-line description at the top actually says what the system does (add/remove, stacking, grid UI) instead of just naming it; the "how to run it" section is specific enough that someone could actually follow it without guessing which scene to open; and "what I would change" names a real, specific limitation (no per-item max stack size) rather than a vague "could be better" — the same honesty Section 9 asked for in the full write-up carries over into the README.