What’s MMTools?
MMTools is a collection of helpers and systems used by most, if not all, MoreMountains assets.
They’re included in Feel, and you’re free to use them in any project you want. Don’t hesitate to explore and experiment with them, they’re all commented, and documented in details in the API documentation. This page gives you an overview of everything that’s in there, module by module, with links to dedicated pages when they exist.
This video should give you a first tour of some of its contents:
How MMTools is organized
Everything lives under Feel/MMTools, in the MoreMountains.Tools namespace, split in 4 folders:
- Core: the systems the rest of Feel relies on (events, tweens, attributes, sound manager, scene loading, etc). Keep it.
- Accessories: standalone helper components (cameras, movement, GUI, particles, debug menu, etc). Nothing in feedbacks depends on them, you can remove that folder if you don’t need it.
- Foundation: bigger, more game-oriented building blocks (AI, achievements, loot, touch controls). Same as Accessories, you can remove it if you don’t need it.
- Demos: demo scenes for many of these tools, safe to remove.
See the contents page for more on what you can safely remove.
Core
MMAttributes
A set of attributes to make your inspectors nicer and safer. Learn more about inspector attributes.
- MMCondition / MMEnumCondition: show or hide fields based on a bool or an enum
- MMInspectorButton: add a button that calls a method
- MMInspectorGroup: group fields under foldable sections
- MMReadOnly: display a field without letting it be edited
- MMInformation: display an information box
- MMDropdown: pick a value from a predefined list
- MMLayer: pick a layer
- and more
MMAudio
Everything audio:
- MMSoundManager: a complete sound manager, with its playlist manager
- MMAudioAnalyzer: drive values from music or sound in real time
- MMPlaylist: the legacy playlist
- MMAudioListener: put it on all your audio listeners, and it gets rid of the “There are two audio listeners in the scene” warning
MMEvents
A decoupled event system used throughout Feel. Learn more about events.
- MMEventManager: a type safe, struct based event system
- MMGameEvent: a general purpose, string based event
- MMGameEventListener: a component that triggers UnityEvents when a MMGameEvent of the specified name is caught
MMExtensions
Extension methods and helpers for many Unity types:
- Animator: UpdateAnimatorBool, UpdateAnimatorFloatIfExists and other safe parameter setters
- Lists: MMShuffle, MMSwap…
- Transforms: MMFindDeepChildBreadthFirst, MMDestroyAllChildren, etc
- Vectors: MMSetX/Y/Z, MMInvert, MMRound, MMProject…
- And more: arrays, bounds, cameras, colors, dictionaries, floats, game objects, layer masks, rects, RectTransforms, renderers and scroll rects
MMHelpers
Static helper classes for everyday tasks, and a few data structures. Learn more about helpers.
- MMMaths: remaps, rounding, random helpers, distance checks…
- MMDebug: logs, debug draws, on screen console
- MMColors: a big palette of named colors
- MMGeometry, MMScene, MMString, MMTime, MMFade, MMImage, MMInput: helpers for their respective domains
- MMShufflebag: controlled randomness, picking items without putting them back
- MMCircularList: a list that loops around when you go past its ends
- MMSerializableDictionary: a dictionary Unity can serialize
MMObjectPool
A simple yet flexible object pooling system. Learn more about object pooling.
- MMSimpleObjectPooler: pools one type of object
- MMMultipleObjectPooler: pools many types of objects, picked in order or at random
- MMPoolableObject: a component for the pooled objects themselves
MMObservable
A tiny struct that wraps a value, and lets other classes subscribe to its changes. Learn more about MMObservable.
MMPropertyControllers
Components that drive values over time on their own, or when piloted by feedbacks. See the Float Controller and Shader Controller feedbacks.
- FloatController: drives any float on any component
- ShaderController: drives any shader property
- LightController: drives a light’s intensity
- TransformController: drives a transform’s properties
How to setup a shader controller and pilot it with a feedback?
Note: these steps use BiRP’s PostProcessing stack, if you’re using URP or HDRP, adapt these to use Volumes instead.
Setting up our scene so that emission is visible
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- create a new, empty scene, add a Cube to it, position it at 0,0,0
- create a new empty object, name it Volume, add a PostProcessVolume to it, set IsGlobal:true, add a new profile to it, and add a Bloom effect override, set its Intensity to 1
- on your scene’s main camera, add a PostProcessLayer, Layer:Everything
- set the Cube’s MeshRenderer to FeedbacksDemoBurger. Notice that this material’s shader exposes an _EmissionForce float property, that controls (you guessed it) the strength of its emission
Adding a shader controller
- add a ShaderController component on the Cube, drag the MeshRenderer into its TargetRenderer slot, TargetPropertyName:_EmissionForce
- press play in the editor, notice that the cube’s emission is now pulsating, as the shader controller is in PingPong mode by default
Controlling the shader controller via a feedback
- exit play mode, set the ShaderController’s ControlMode to OneTime
- create a new empty object, add a MMF Player to it, then add a Renderer > ShaderController feedback to it, drag the Cube into its TargetShaderController slot, OneTimeRemapMax:10
- press play in the editor, then press the green Play button on your MMF Player, the cube will glow and get back to its normal emission over 1s
MMRadio
A system that lets you read any value on any component, and broadcast it to drive any value on any other component, without code. Also includes MMRadioSignals, signal generators you can use as sources. Learn more about MMRadio.
MMReorderableList
An inspector helper to display reorderable arrays, used by many MoreMountains classes.
MMSaveLoad
Save and load data to files. Learn more about saving and loading.
- MMSaveLoadManager: saves any serializable object to a file (binary, json, encrypted or not)
- MMPersistenceManager: saves and restores the state of objects in your scenes
MMSceneLoading
Scene loading with loading screens, either sequential or additive, with transitions, progress bars, and an editor mode. Learn more about scene loading.
MMSingletons
Base classes to quickly turn any component into a singleton. Learn more about singletons.
- MMSingleton: a regular singleton
- MMPersistentSingleton: survives scene loads
- MMPersistentHumbleSingleton: survives scene loads, and a newer instance replaces older ones
MMStateMachine
A simple, generic state machine you can use for your characters, game managers, or anything that has states. Learn more about MMStateMachine.
MMTimeManager
A timescale manager, keeping a stack of timescale modifications, used by all time related feedbacks. Learn more about MMTimeManager.
MMTween
Tweening and interpolation tools. Learn more about tweens.
- MMTween: the tween library, to tween values, transforms and more, along dozens of curves
- MMTweenType: the curve picker you see in many feedbacks
- MMSignal: basic signal curves
- MMFollowTarget: have an object follow another, with lots of interpolation options
- MMAnimationCurveGenerator: generates a curves asset from the MMTween library
How to setup a MMFollowTarget component to have it follow a target?
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- open FeelSquashAndStretch demo scene
- add a Cube at 0,0,-2
- add a MMFollowTarget component to it, set its Target to PlayerCar, FollowPositionSpeed:0.05
- press play, use the keyboard arrows to drive around
MMUI
UI building blocks, used by the Fade feedback and the scene loading transitions:
- MMProgressBar: a versatile progress bar
- MMFader, MMFaderRound, MMFaderDirectional: full screen fades, regular, round and directional
How to setup a MMFader and fade feedback?
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- create a new, empty scene
Option 1: automatic shaker setup
- in the scene, create a new empty object, add a MMF Player to it, add a Camera > Fade feedback to it
- unfold its Automatic Setup foldout, press the Automatic Shaker Setup button
- press play in the editor, then the green Play button on your MMF Player
Option 2: manual setup
- add a UI Image to your scene, set its RectTransform so that it covers the entire screen (usually full stretch and 0 on all left/right/top/bottom, set its Image color to black
- add a MMFader component to it, this will add a CanvasGroup, set its Alpha to 0
- in the scene, create a new empty object, add a MMF Player to it, add a Camera > Fade feedback to it
- press play, play the Feedback, it will “fade in” the fader (fading the screen to black), change its FadeType to Fade Out, it will fade it out back to normal. The Fade feedback’s inspector will let you tweak settings to your liking (duration, curve, etc). If you have more than one fader, make sure the Channel ID on both your fader and feedbacks match.
Accessories
MMActivation
Components that turn things on and off without code:
- MMActivationOnStart: enables or disables objects on Start or Awake
- MMTimedActivation: enables, disables or destroys objects after a delay (in seconds or frames), starting on Awake, Start, Enable, a trigger, or from script
- MMTimedDestruction: destroys an object after a delay
- MMPlatformActivation / MMApplicationPlatformActivation: enable or disable objects based on the platform
- MMConditionalActivation: enables target monos once all other targets have been disabled
- MMToggleActive: toggles an object active or inactive
- MMDontDestroyOnLoad: makes an object persist across scenes
- MMParentingOnStart: parents an object to a target on Awake or Start
- MMPeriodicExecution: fires events at random intervals
- MMInputExecution: binds keys to UnityEvents
- MMAutoExecution: fires UnityEvents automatically on Awake, Start, Enable, Disable, etc
- MMOnMouse: mouse events on colliders
- MMTriggerAndCollision: UnityEvents on trigger and collision enter/stay/exit, with layer filters
MMCamera
- MMOrbitalCamera: orbits a camera around a target, with mouse or touch
- MMBillboard: has an object always face the camera
- MMCameraAspectRatio: forces an aspect ratio
- MMAspectRatioSafeZones: visualizes safe zones for multiple ratios in the scene view
- MMCameraFog: per camera fog settings
- MMViewportEdgeTeleporter: asteroids style screen wrapping
MMCinemachine
- MMCinemachineZone: 2D and 3D zones that enable a Cinemachine camera when entered, handling all the boilerplate setup
- MMGyroParallax: gyroscope driven parallax for cameras
MMCurves
- MMPlotter: draws graphs of curves in your scene
- MMPlotterGenerator: generates one for every MMTween curve, handy to compare them
MMDebugMenu
A mobile friendly, runtime debug menu, with tabs, buttons, checkboxes, sliders, choices and values, a log console, and a command line. Learn more about the debug menu.
MMGizmos
MMGizmo, a component that displays gizmos (shapes, colliders, position, names) for objects in the scene view, very useful to visualize spawn points, waypoints or triggers.
MMGUI
UI helpers:
- MMHealthBar: draws health bars above objects, see recipe below
- MMParallaxUI: UI layers moving with the mouse or gyroscope
- MMRadialProgressBar: legacy, prefer MMProgressBar
- MMCountdown: ascending or descending timers, with formatting, floors and events
- MMSliderStep: events when a slider moves past certain steps
- MMTwoSidedUI: flips a two sided UI element on an axis
- MMUIFollowMouse: has a UI object follow the mouse
- MMOnPointer: pointer events to UnityEvents
- MMRaycastTarget: a raycast target without an Image
- MMCursorVisible: forces the cursor visible or invisible
- MMGetFocusOnEnable: sets focus on an object when it gets enabled
- MMSceneName: displays the current scene’s name in a Text
- MMSelectionBase: always selects that object in the scene view, even when clicking one of its children
- MMPSBToUIConverter: converts an imported PSB (Photoshop) file’s sprite renderers into UI Images on a target canvas
How to use the MMHealthBar component to automatically draw health bars?
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- create a new, empty scene
- create a cube, position it at 0,0,0
- add a MMHealthBar component to it
- press play, you’ll notice the healthbar gets drawn above your cube
- if you now want to interact with your MMHealthBar and update it, you’ll need to pass it data to update it. We’ll use a script to do so.
- create a new C# class, call it TestMMHealthBar, and paste the following in it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MoreMountains.Tools;
/// <summary>
/// A simple class used to interact with a MMHealthBar component and test it
/// To use it, add it to an object with a MMHealthBar, and at runtime, move its CurrentHealth slider, and press the Test button to update the bar
/// </summary>
public class TestMMHealthBar : MonoBehaviour
{
[Range(0f, 100f)]
public float CurrentHealth = 50f;
protected float _minimumHealth = 0f;
protected float _maximumHealth = 100f;
protected MMHealthBar _targetHealthBar;
[MMInspectorButton("Test")] public bool TestButton;
protected virtual void Awake()
{
_targetHealthBar = this.gameObject.GetComponent<MMHealthBar>();
}
public virtual void Test()
{
if (_targetHealthBar != null)
{
_targetHealthBar.UpdateBar(CurrentHealth, _minimumHealth, _maximumHealth, true);
}
}
}
- add this component to your Cube, press play, and at runtime, move its CurrentHealth slider in its inspector. Every time you press the Test button, the health bar will update.
MMGyroscope
MMGyroscope, a static class exposing gyroscope values (and simulating them in the editor), used by MMParallaxUI and MMGyroParallax.
MMInput
MMAutoInputModule, which adds the right UI input module to your EventSystem, whether you’re using the old or new input system.
MMInstantiation
- MMRandomInstantiator: instantiates a random prefab from a list
- MMRandomBoundsInstantiator: spawns objects at random positions within a collider’s bounds
- MMSpawnAround: a static helper that randomizes the position (within a sphere or cube, optionally constrained to a plane), rotation and scale of objects you spawn
MMMovement
- MMAutoRotate: rotates an object on itself, or has it orbit around a point
- MMPathMovement: moves along a path defined in the inspector
- MMFaceDirection: has a transform face its movement direction or a target
- MMAim: aim with input, mouse or script, with angle limits
- MMPositionRecorder: records a transform’s position periodically
- MMPreventPassingThrough: 2D and 3D, prevents fast objects from going through colliders
- MMSquashAndStretch: automatic squash and stretch based on movement
- MMStayInPlace: forces a transform to stay at a fixed position, rotation and/or scale
MMParticles
- MMAutoDestroyParticleSystem: destroys a particle system once it’s done emitting
- MMDelayParticles: delays particle systems
- MMRuntimeParticleControl: play/pause/stop buttons in the inspector
- MMVisibleParticle, MMRendererSortingLayer, MMTrailRendererSortingLayer: force sorting layers
- MMChangeFogColor: changes a global fog’s color
MMPerformance
- MMFPSCounter: displays the current framerate in a Text
- MMFPSUnlock: sets the target framerate and vsync
- MMSpeedTest: quickly measures the execution time of a piece of code
MMPhysics
- MMRigidbodyCenterOfMass: edit a rigidbody’s center of mass from the inspector
- MMRigidbodyInterface: one API for both Rigidbody and Rigidbody2D
MMProcedural
MMTilemapGenerator, a layered procedural tilemap generator, with grid generators you can combine:
- Full: a grid entirely full or empty
- Random: random points
- Perlin noise: based on a seeded perlin noise
- Perlin noise ground: a ground floor based on perlin noise
- Path: a path in the specified direction
- Random walk: a path carved by a drunkard walk algorithm
- Random walk avoider: a random walk avoiding another grid’s walls
- Random walk ground: a ground with controlled elevation
MMPrototypeTextures and MMShaders
A set of prototyping textures and materials, and a few shaders used in demos. They should all be straightforward to use, with one exception: the MMRipple shader in URP requires that you select your Universal Renderer Data asset, and from its inspector, via the “Add Renderer Feature”, you pick MMRippleGrabPass. That’s it, you’re all set!
MMSprites
- MMBezierLineRenderer: turns a line renderer into a bezier curve with control points
- MMLineRendererDriver: binds a line renderer’s points to transforms
- MMLineRendererCircle: draws circles and ellipses with a line renderer
- MMAutoOrderInLayer: picks a unique order in layer on start
MMTilemaps
- MMTilemap: helper methods for tilemaps
- MMTilemapShadow: a tilemap copying another, for wall shadows for example
- MMTilemapCleaner: a button to remove all tiles
- MMTilemapBoolean: removes from a tilemap the tiles present on another
- MMTilemapGridRenderer: renders a grid on a tilemap
MMUtilities
- MMDebugController: toggles logs and debug draws
- MMScreenshot: takes screenshots from the editor, via a shortcut or a button
- MMSceneRestarter: restarts the scene with a key
- MMTransformRandomizer: randomizes position, rotation and scale
- MMSceneViewIcon: displays an object’s name in the scene view
- MMOpenURL: opens a URL
- MMApplicationQuit: quits the application
- MMLayer: a serializable layer, with its index and mask
MMVFX
MMPanningTexture, to scroll a texture on a sprite or mesh.
MMVision
MMConeOfVision and MMConeOfVision2D, which detect targets within an angle and distance (with obstacles), and draw the corresponding cone mesh.
Foundation
MMAchievements
A complete achievements system, with simple or progress based achievements, saved to file:
- MMAchievementList: an asset where you define your achievements
- MMAchievementRules: extend it to unlock achievements based on your game’s events
- MMAchievementDisplayer: displays achievements on screen as they get unlocked
- MMAchievementManager: stores, unlocks and saves achievements
MMAI
A modular AI system. You extend AIAction and AIDecision to create your own behaviours.
- AIBrain: switches between states
- AIAction: describes what to do in a state
- AITransition: evaluates decisions to change state
- AIDecision: returns true or false, to tell transitions when to change state
MMAnimation
- MMRagdoller: switches a character between animated and ragdoll states, blending back to animation
- MMStopMotionAnimation: plays animations at a lower framerate, for a stop motion look
- MMAnimatorMirror: mirrors an animator’s parameters on another
- MMOffsetAnimation: randomizes an animation’s start
- MMAnimationModifier: controls an animation’s start position and speed
- MMAnimationParameter: hashes an animation parameter and updates it on demand
MMControls
Mobile touch controls. Check out the MMControls demo.
- MMTouchJoystick: a joystick, with its repositionable and follower variants
- MMTouchButton: a button, with pressed down, pressed continually and released events
- MMTouchAxis: an axis
- MMSwipeZone: detects swipes
- MMTouchControls: switches between touch controls and desktop input, with automatic mobile detection
MMGhostCamera
A free flying camera you can activate at runtime to explore your scene, with an activation button, a run button, and an option to slow down time (requires a MMTimeManager).
How to setup billboarding and a ghost camera?
Billboarding lets an object always face the camera. In these steps we set that up in a simple click, and also setup an easy to move ghost camera to try it out.
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- create a new, empty scene
- add a sprite renderer to it, position it at 0,0,0, set its Sprite to button-A
- add a MMBillboard component to it
- on your scene’s MainCamera, add a MMGhostCamera component
- press play, use WASD, space and C to move around, notice the A circle keeps facing your camera
MMLoot
MMLootTable, a weighted random picker for any type of object, also available as a ScriptableObject. Learn more about loot tables.
MMTime
MMCooldown, a class that handles a consumable cooldown (consume, pause on empty, refill), perfect for dashes, sprints or shields. Learn more about MMCooldown.
More recipes
The MMWiggle component lives in Feel’s feedbacks folder, but it’s a nice standalone helper too:
How to make an object wiggle in your scene?
- in Unity 6000.5.0f1 (or higher), create a new project and import Feel v6.3 via the Package Manager
- in a new scene, create a cube
- add a MMWiggle component to it
- check the Position checkbox, set its Wiggle Type to Noise, press play, you now have a wiggling cube
- you can now increase the frequency, amplitude, or add a shift (useful if you have more than one of these), and play with all the other options
Demos
In the MMTools/Demos folder, you’ll find demo scenes for the following tools. They’re a great way to see them in action.
- MMBezierLineRenderer
- MMControls
- MMDebugMenu
- MMFollowTarget
- MMGhostCamera
- MMGizmos
- MMGyroscope
- MMObservable
- MMOrbitalCamera
- MMPrototypeTextures
- MMRadio
- MMSceneLoading
- MMTween