After testing dozens of community scripts and compiling user feedback from GameBanana and GitHub, here are the three best scripts for a "basically FNF" experience.
Not every script on GameBanana or GitHub is quality. Here is the checklist for the best basically FNF script: basically fnf script best
| Type | File Extension | Folder | Use |
|------|---------------|--------|-----|
| HScript | .hx | mods/scripts/ | Full Haxe, best for complex logic |
| HScript (custom) | .hx | mods/scripts/custom/ | Custom states/substates |
| Lua | .lua | mods/scripts/ | Simpler, less performant | After testing dozens of community scripts and compiling
Psych Engine loads scripts/ folder automatically. Name your script MyScript.hx. Below is a pseudo-code representation of a highly
Below is a pseudo-code representation of a highly optimized input and scoring loop, commonly found in custom FNF engines. This represents the "best" structural approach.
// Pseudo-Haxe: Core Update Loop Logic
function update(elapsed:Float):Void
// 1. Update Song Position (Crucial for Sync)
Conductor.songPosition += elapsed * 1000;
// 2. Manage Note Spawning
// Spawn notes slightly before they appear on screen to prevent pop-in
var spawnTime = 2000; // ms before note appears
for (note in unspawnNotes)
if (note.strumTime - Conductor.songPosition < spawnTime)
spawnNote(note);
// 3. Input Handling (The "Best" Logic)
if (playerControlled)
// Check for key presses
if (inputPressed("left"))
checkNoteHit("left");
function checkNoteHit(direction:String):Void
// Find the closest note that hasn't been hit
var closestNote = getClosestNote(direction);
if (closestNote != null)
// Calculate time difference
var hitDiff = Math.abs(closestNote.strumTime - Conductor.songPosition);
// Judgment System
if (hitDiff < 45) rating = "Sick"; score += 350;
else if (hitDiff < 90) rating = "Good"; score += 200;
else if (hitDiff < 135) rating = "Bad"; score += 50;
else rating = "Shit"; health -= 0.05;
// Visual Feedback
spawnPopUp(rating);
characterPlayAnim("sing" + direction);