Optic detection
About 15 minutes to read
Optic Detection recognizes the sight shown in your captured game HUD. It can then apply optional prediction, aim, flick, and recoil adjustments for that optic.
It does not change your weapon class. Weapon detection and optic detection serve different purposes and can run together.
#Contents
- Getting started
- Choosing a recognition method
- Search regions and multiple slots
- AI Optic Detection
- Template matching
- Text recognition: OCR
- How optic selection works
- Optic adjustments
- Size-based extra prediction lead
- Testing your setup
- Sharing and backing up
- Troubleshooting
#Getting started
- Start Moonlight capture and confirm the game image is current.
- Open Detection → Optic Detection and enable it.
- Choose AI Optic Detection or Template / OCR.
- Configure recognition and search regions using the relevant section below.
- Confirm the Active optic status changes correctly when you change sights.
- Only then configure any optional optic adjustments.
Start with recognition alone. You do not need to enable prediction or change aim settings to test whether an optic is recognized correctly.
The feature is experimental. A successful match or training run does not establish accuracy across every game, HUD layout, or capture setup.
#Choosing a recognition method
| Method | Best suited to | What you provide | Main limitation |
|---|---|---|---|
| AI Optic Detection | Several optics or setups with visual variation | Labeled samples, including Background, followed by training | Needs representative training data and testing |
| Template matching | A consistent, distinctive HUD icon | An image of the icon and regions to search | Changes in icon size or appearance can prevent matching |
| OCR | Clear, readable sight names or magnification text | Expected text and regions to read | Very short or small text can be confused |
Methods can coexist, but avoid creating competing rules for the same visible indicator. Two rules identifying different optics at once produce an ambiguous result.
An optic name such as 4x is a label. It does not automatically multiply aim, recoil, or prediction by four.
#Search regions and multiple slots
A search region is the part of the captured image Moonlight checks for an optic. Use the smallest practical region that contains the relevant indicator without cutting it off.
If the icon can appear in four different HUD slots, add all four regions to that optic. You do not need four separate optic rules.
#Add or edit regions
- Open the optic editor while capture is running.
- Draw a selection on the captured image.
- Click Add region to store it. Drawing alone does not add it.
- Repeat for other possible locations.
- Save the optic.
The region table shows X, Y, Width, and Height. Double-click a value to edit it precisely.
- Replace selected: redraw a selection, then replace the highlighted region.
- Duplicate region: copy its coordinates, then move or resize the copy.
- Remove region: delete the highlighted search region.
- Copy search regions from another optic: choose an existing optic and click Copy regions to reuse its layout.
There can be up to 16 optics across the recognition methods and 32 search regions per optic. Keep regions small; a single region has an area limit equivalent to 512 × 512 pixels.
#Choose regions that identify the active optic
Searching several slots works when the relevant icon can move between those slots. It does not tell Moonlight which optic is equipped if several different optic icons are visible simultaneously.
For example, an inventory showing both a 1x and a 4x is ambiguous unless your selected regions isolate the equipped sight or its active indicator. Recognition cannot infer that selection from identical-looking inventory slots.
Regions are saved relative to the capture, but different HUD positions, aspect ratios, and interface scales still need checking on each setup.
#AI Optic Detection
The AI workflow is: create a model, define optic labels and slots, collect examples, train, then test on new images.
#1. Create a model
- Open AI Optic Detection.
- Click New model.
- Enter a descriptive name, such as your game name.
- Select it in Model / dataset.
Use one model for the optics you want it to distinguish. Optic models and datasets are separate from weapon models and datasets.
The model dropdown selects what you are editing or training. It does not force that model's optic to become active or disable other configured recognition rules.
#2. Add optic labels
- Click Add optic label.
- Set an Optic name, such as
1x Holoor4x Scope. - Confirm the AI model / dataset.
- Give it a unique Training label within that model.
- Set Minimum confidence. The default is 80%.
- Add its search regions and save.
- Repeat for every optic the model should recognize.
The display name is what you see in Moonlight. The training label identifies the sample class. Changing the model name or training label in a rule does not move or rename existing dataset files.
Use Edit label / slots to change a rule. Duplicate label provides a starting point for another optic, but does not duplicate its training samples or optic adjustments. Remove label removes the rule, not its saved model or sample files.
#3. Capture samples
Select the model and click Capture samples. You do not need to select an individual row first, but the model needs at least one configured optic label and search slot.
In the capture window:
- Equip the optic you are collecting.
- Choose its Sample label.
- Choose the correct Capture slot.
- Check the crop preview carefully. This is the image that will be saved.
- Click Save sample, or enable Record samples.
Recording saves at the interval shown beside Every. The default is 200 ms, with a range of 100–2000 ms. Recording stops after 300 samples per burst, when capture becomes unavailable, or when you close the collector.
Only the selected slot is saved under the selected label. Other slots are not automatically labeled or collected. Stop recording before changing the label or slot.
Collect examples with variation that matters to your intended setup:
- Different backgrounds and lighting behind the HUD.
- Different slots where the icon can appear.
- Different sessions and HUD states.
- The HUD scales and capture appearances you intend to support.
Hundreds of nearly identical frames are not a substitute for representative examples. Do not record transitions under the wrong label.
#4. Collect Background samples
Select Background / no optic and capture examples the model should reject:
- Empty optic slots.
- Unrelated icons or HUD elements in the search region.
- Menus or other states that may occupy the same region.
- Unsupported sights that should not activate any configured optic.
Do not label a valid supported optic as Background. Conflicting labels make recognition less reliable.
Training requires at least 10 samples per class, including Background. This is only the minimum needed to run training, not a guarantee of a good model.
Use Open dataset to inspect your saved images. Stop recording and training before removing incorrectly labeled samples. Refresh or reopen the workspace afterward if its counts have not updated.
#5. Train the model
- Click Train model.
- Start with the defaults: 40 epochs, 128 input size.
- Click Start and follow the progress and training output.
- Wait for successful completion.
Training an existing dataset does not require live capture. Sample collection is unavailable while the training window is open.
Each optic training run starts fresh. Stop, or closing the training window, cancels the attempt. An interrupted or failed attempt does not replace the previous active model.
After successful training, the new model version activates automatically. There is no separate accept or apply step. Adding a new training label requires collecting its samples and retraining.
More epochs or a larger input size do not automatically make a model better. Fix mislabeled samples, poor crops, and missing examples before increasing training settings.
#6. Verify recognition
In the sample collector, enable Test trained model on this slot to see the live label and confidence for the selected crop. This is a diagnostic preview, not a way to force the active optic.
Then check Active optic in the main Optic Detection section while switching sights normally.
Test new scenes and sessions that were not used to collect the dataset. The training validation score is not proof that the model works on another user's setup. A high score with nearly identical training images can still produce poor real-world recognition.
Raise minimum confidence if weak matches are activating an optic. Lower it cautiously if correct examples consistently fall just below the threshold. A threshold cannot repair a mislabeled dataset or an incorrect search region.
#Template matching
Use templates when the icon is visually consistent and does not change size between setups.
- Open Template / OCR.
- Click Add optic from capture.
- Enter the optic name and select Template (icon).
- Draw a tight selection around the identifying icon.
- Click Capture template from selection.
- Draw the region where Moonlight should look for that icon and click Add region.
- Add any other possible slots.
- Set Minimum confidence and save. The default is 90%.
Capturing the template and adding search regions are separate actions. The template is the image to find; the search regions are the places to look for it.
Choose a distinctive icon crop, not a blank area or an entire HUD panel. Search regions must be large enough to contain the icon.
Use Edit selected to recapture a template or change regions. Duplicate selected is useful for starting another rule with similar settings; update its name and template before using it.
Template matching does not automatically adapt to a differently sized icon. If HUD scale or capture appearance changes, recapture the template and verify its regions. AI recognition with suitable examples may be more appropriate for varied setups.
#Text recognition: OCR
- Open Template / OCR.
- Click Add optic from capture.
- Enter the optic name and select Text (OCR).
- Enter the sight text in Exact visible text, such as the name or magnification shown on screen.
- Add tight regions around the readable text.
- Set Minimum text match and save.
At 100%, matching requires the expected text after basic normalization such as casing and spacing. Lower values allow fuzzy text matching.
Minimum text match is text similarity, not OCR confidence. Lowering it can help tolerate recognition mistakes, but also makes similar labels easier to confuse. Short strings such as 1x and 4x are especially sensitive to this.
Start at 100%. If text is too small, unclear, or frequently misread, use template matching or AI instead of accepting increasingly loose matches.
#How optic selection works
Moonlight confirms an optic using consecutive agreeing observations. A brief missed reading can retain the last confirmed optic for up to approximately 350 ms before it expires.
- The same optic found in several of its regions is still one optic.
- Different optics found at once are ambiguous. Moonlight does not simply choose the highest confidence score.
- Editing or highlighting an optic does not activate it.
- Once recognition is unknown or expired, that optic's adjustments no longer apply.
- Optic recognition does not switch the selected weapon class.
Use the active-optic status and available slot results to establish recognition before troubleshooting adjustment values.
#Optic adjustments
All optic-specific adjustments are configured under Detection → Optic Detection, not in the Prediction tab. While Optic Detection is enabled, Prediction → Distance Extra Lead (experimental) is hidden; use the optic's own size-based lead instead.
- For AI, select an optic and click Optic adjustments.
- For Template / OCR, select an optic and click Edit adjustments for selected optic.
These profiles belong to the current weapon class. The same optic can have different adjustments for different classes. Select the intended class before configuring its profile.
| Option | Effect |
|---|---|
| Aim response multiplier | Scales the class's aim response while this optic is active |
| Flick response multiplier | Scales the class's flick response while this optic is active |
| RCS strength multiplier | Scales built-in recoil compensation strength, not pattern timing |
| Prediction: size-based extra lead | Adds the optic's calibrated extra lead according to target box height |
| Apply optic adjustments only while ADS is held | Requires the configured ADS input to be held before applying the adjustments |
Each multiplier is independent, defaults to 1.00×, and supports 0.10–3.00×. Enable its checkbox to reveal and apply the value. An unchecked adjustment has no effect even if a value was previously saved.
These options modify existing behavior; they do not enable Aim, Flick, RCS, or Prediction by themselves, and they do not overwrite the class's saved base settings. RCS scaling does not apply to recoil generated by custom Lua scripts.
ADS-only activation uses your configured ADS binding. It does not visually determine whether the game is scoped. Confirm the binding and its held state if adjustments unexpectedly remain inactive.
Leave every adjustment unchecked for recognition only.
#Size-based extra prediction lead
This optional calibration lets different optics use different additional prediction lead at different apparent target sizes.
Box size alone is not distance. A nearby target through a 1x and a distant target through a 4x can appear equally large. Separate optic profiles let those situations use different calibration curves, provided their HUD indicators can be distinguished.
#Create a calibration
- Enable and configure the main prediction feature normally.
- Select the intended weapon class.
- Open the desired optic's adjustments.
- Enable Prediction: size-based extra lead.
- Equip that optic and verify it is currently detected.
- With a target being detected, click Snapshot target box.
- Double-click the new row's Additional lead (ms) value and enter the extra lead to test.
- Repeat at other target sizes if needed.
The snapshot records bounding-box height in capture/detection pixels. It does not measure world distance or automatically calculate a good lead value. New points start at 0 ms.
The table supports up to 8 points with different box heights. Edit either column directly or use Remove selected to delete a point. Additional lead can be 0–300 ms per point.
#How the curve behaves
- Between saved heights, the additional lead interpolates between their values.
- Below or above the saved size range, the nearest endpoint value is used.
- A single point applies the same additional lead across sizes.
- The result adds to the existing Extra Lead setting; that combined extra-lead value is capped at 300 ms.
This is additional lead, not a replacement for the predictor. It does not force an offset on a stationary target or guarantee correct prediction when motion estimates are unreliable.
Start with small changes and test moving targets, including reversals. Too much lead can overshoot even if it looks good during a single constant-speed pass.
Recheck calibration after changing the detection model or capture scale. Also verify it after changes to game view settings or other settings that affect the target's appearance and response.
If a variable-zoom optic keeps exactly the same HUD icon and text at both zoom levels, recognition cannot distinguish those levels from that region alone. Use a genuinely different visible indicator or avoid a calibration that depends on knowing that distinction.
#Testing your setup
Before relying on or sharing a setup:
- Leave adjustments disabled and confirm each optic is recognized correctly.
- Test empty slots, menus, unsupported sights, and normal optic changes.
- Test every configured slot and check for conflicting visible optics.
- Test fresh scenes and sessions, not only the images used for training.
- Enable one adjustment at a time and confirm the correct weapon class is selected.
- Test ADS held and released if using ADS-only adjustments.
- Test prediction at different target sizes, speeds, and direction changes.
- Confirm normal behavior returns after the optic is no longer recognized.
Keep a copy of a working configuration before substantially changing rules, labels, or calibration.
#Sharing and backing up
Paths below are relative to the Moonlight folder.
| Item | Location | Needed to use the setup? |
|---|---|---|
| Rules, regions, and per-class adjustments | Your saved Moonlight configuration | Yes |
| Trained AI model | optic_models/<model>/ | Yes, for AI recognition |
| Template images | Referenced files in optic_templates/ | Yes, for template recognition |
| Training samples | optic_datasets/<model>/<label>/ | Only for inspection or further training |
For AI, copy the whole model folder, including active.json and its version subfolders. Copying only an ONNX file is not a complete model package for this workflow.
Keep model names and training labels consistent with the configuration. Include referenced template images if the configuration uses template rules. OCR rules do not need a trained model or template image.
Close Moonlight before replacing shared files, and back up the recipient's configuration rather than overwriting their only copy. Recheck regions and recognition on the recipient's capture and HUD layout.
Removing an optic rule does not delete its saved samples or models. Duplicating a rule does not duplicate its dataset or per-class adjustments. Keep the configuration as well as model files when backing up a working setup.
#Troubleshooting
#Capture samples or Train model is unavailable
Select or create a model in AI Optic Detection. These buttons operate on the selected model, not the highlighted optic row. Sample capture also requires at least one configured label and search slot.
#I cannot add an optic or edit its region
Start capture and wait for a fresh frame. Region editing needs a current captured image.
#The sample preview is stale or Save sample is disabled
Check that capture is running and the selected slot is valid. Close the training window before collecting samples. Wait for any pending save to finish.
#Training reports missing samples
Collect at least 10 samples for every required label, including Background. Check the selected model and training-label names. Old label folders with too few images can also need attention; inspect the dataset rather than assuming visible rule counts cover every folder.
#Training completed, but no optic activates
Check the live slot result, confidence threshold, model name, and training-label mapping. Confirm the configured regions contain the icon. Look for another rule detecting a conflicting optic. If you added labels after training, retrain.
#The wrong optic activates
Check for mislabeled samples, missing Background examples, loose OCR matching, overly broad regions, or competing rules. Test recognition before changing prediction or recoil settings.
#It works for me but not another user
Compare HUD layout, icon size, capture appearance, and search regions. Templates may need recapturing. AI needs examples representative of the other setup; a successful local training score does not guarantee compatibility.
#Snapshot target box is unavailable
Enable the size-based lead option, run detection, and make sure the optic being edited is the one currently recognized. A fresh target box must be available. The curve must also have room for another point, and its height must not duplicate an existing point.
#Adjustments appear to do nothing
Check the active optic, current weapon class, adjustment checkbox, underlying feature, and ADS-only condition. Selecting an optic in the editor does not make it active. A multiplier of 1.00× intentionally leaves the base response unchanged.
#Results expire or recognition is slow
Reduce unnecessarily large regions and avoid full-screen searches. Check for stale capture or reported recognition errors. Increasing a confidence threshold does not reduce the amount of image area being searched.
#A model is missing after copying the setup
Copy the complete model folder and matching configuration. Check that active.json and its referenced version folder are present, and that the model name matches the rule.
#A required component fails to load
Use a complete matching Moonlight build rather than mixing modules from different releases. Preserve the exact error and the relevant recognition status when reporting the issue.
Stuck on a step? Ask in the Moonlight Discord and a staff member will help.