Skip to content

FAQ & Common Issues

Alex Neargarder edited this page Aug 10, 2025 · 15 revisions

Table of Contents

Sections


General

How do I save settings between game sessions?

BroMaker provides the [SaveableSetting] attribute which you can set on any serializable static variable in a class that inherits from CustomHero. Variables with this attribute will automatically be loaded when the mod starts up, and automatically saved when you press "Save" in the Unity Mod Manager window or when the game shutdowns. If you force close the game the settings may not be saved however.

If you want to display these options and allow users to change them, you can use the UIOptions() method

Example:

[SaveableSetting]
public static bool doubleTapSwitch = true;

How do I get Visual Studio IntelliSense to show the description of members?

Visual Studio has the ability to show descriptions of methods when you're hovering over them or typing them out and looking at them in autocomplete:

image

In order for these to show up, you'll need to make sure that you have the .xml files for whichever assembly contains the given member. So for methods provided by BroMaker, you'll need the BroMakerLib.xml file, which you can find here.

You'll want to download that file and place it next to your BroMakerLib.dll. You need to make sure that it's the same .dll that you added to your solution's references though, as you may have some of these .dlls in multiple locations.

I'd recommend making sure you have all of the following .xml files from here, as well as BroMakerLib.xml, and RocketLib.xml


How do I check if my bro is attached to a helicopter?

You can check the isOnHelicopter variable to see if your bro is attached to a helicopter. It's a good idea to check this if you have some continuous visual / audio effect that you need to cancel when your bro gets on a helicopter.

Example:

// Stop proton gun when getting on helicopter
if ( this.isOnHelicopter )
{
    this.StopProtonGun();
    this.protonAudio.enabled = false;
}

Sprites

How do I set my bro's avatar or special icons

Use the parameters section in your JSON file to set these sprites:

{
  "parameters": {
    "Avatar": "avatar.png",
    "SpecialIcons": "special_icons.png"
  }
}

See Parameters for all available sprite parameters.


How do I have multiple variants of my bro?

Provide arrays instead of single values in your parameters to create variants that are randomly selected on spawn:

{
  "parameters": {
    "Sprite": ["sprite1.png", "sprite2.png", "sprite3.png"],
    "Avatar": ["avatar1.png", "avatar2.png", "avatar3.png"]
  }
}

See this page for detailed information on variants.

Audio

How do I play an audio clip continuously?

To play audio continuously (like for a proton gun, flamethrower, or other sustained effects), you need to add an AudioSource component to your bro or projectile and configure it for looping playback. Here's the typical pattern:

1. Add and configure the AudioSource:

// Declare as public field in your bro class (required for prefab serialization)
public AudioSource continuousAudio;

// In your bro's AfterPrefabSetup() method
this.continuousAudio = base.gameObject.AddComponent<AudioSource>();
this.continuousAudio.rolloffMode = AudioRolloffMode.Linear;
this.continuousAudio.minDistance = 200f;
this.continuousAudio.maxDistance = 500f;
this.continuousAudio.spatialBlend = 1f;
this.continuousAudio.volume = 0.33f;

2. Start the continuous loop:

// When starting your effect
if (!this.continuousAudio.isPlaying)
{
    this.continuousAudio.clip = myLoopSound;
    this.continuousAudio.loop = true; 
    this.continuousAudio.Play();
}

3. Stop audio when dying / level ending:

// In your Update() method
if (this.isOnHelicopter || this.actionState == ActionState.Dead)
{
    this.continuousAudio.enabled = false;
}

Transition from Startup to Loop:

// For effects with startup and loop sounds (like Brostbuster's proton gun)
if (!this.continuousAudio.isPlaying)
{
    this.continuousAudio.clip = loopSound;
    this.continuousAudio.loop = true;
    this.continuousAudio.Play();
}

Projectiles

How do I set the hitbox for a projectile?

The primary way to set a projectile's hitbox is through the projectileSize property, which defines the collision radius. This value is used for both horizontal and vertical collision detection by default.

Basic Configuration:

// In your projectile's Awake() method
this.projectileSize = 10f;  // Sets collision radius to 10 pixels

Additional Properties:

  • horizontalProjectile (default: true) - Controls wall collision detection method:

    • true: Raycasts from 2×projectileSize behind (X-offset only) in the velocity direction
    • false: Raycasts from projectile center in the velocity direction
  • isWideProjectile (default: false) - Only affects horizontal projectiles:

    • true: Performs dual collision checks above and below center (for very wide projectiles)
    • false: Single collision check at center

Important Notes:

  • Broforce's collision system assumes roughly circular/square hitboxes
  • Very large projectiles (>20 units) may need custom collision code as the default system wasn't designed for them
  • For complex shapes or very large projectiles, you'll need to override collision methods
  • The visual sprite size doesn't need to match projectileSize - they're independent

How do I make my projectile obey gravity?

Projectiles don't have gravity by default. You have two options:

Option 1: Inherit from CustomGrenade instead of CustomProjectile Grenades have gravity built-in, so if your projectile should arc and bounce, consider making it a grenade.

Option 2: Apply gravity manually in Update()

protected virtual void ApplyGravity()
{
    this.yI -= 500f * this.t;  // 500 is gravity strength
}

protected override void Update()
{
    this.ApplyGravity();
    base.Update();
}

The gravity value of 500 is typical for normal falling speed. Adjust higher for faster falling or lower for floatier projectiles.

Melee

How do I prevent flexing from resetting my melee animation?

Flexing and other gesture animations can reset the frame counter during melee attacks. To prevent this, override SetGestureAnimation and check if the melee is active:

public override void SetGestureAnimation(GestureElement.Gestures gesture)
{
    if (this.doingMelee)
    {
        return;  // Don't allow gestures during melee
    }
    base.SetGestureAnimation(gesture);
}

Special

How do I prevent wall jumping from resetting my special animation?

Wall jumping and climbing reset the base frame counter, which can reset special animations. The easiest solution is to track special frames separately:

// Declare a separate frame counter for specials
protected int usingSpecialFrame = 0;

// Override IncreaseFrame to increment it
protected override void IncreaseFrame()
{
    base.IncreaseFrame();
    if (this.usingSpecial)
    {
        ++this.usingSpecialFrame;
    }
}

// Use the separate counter in AnimateSpecial instead of base.frame
protected override void AnimateSpecial()
Clone this wiki locally