Skip to content

ItemOpticAsset — Standalone Optic Items

Choosing the right observation tool for long-range reconnaissance in Unturned means understanding how standalone optic assets (binoculars, spotting scopes) control camera field of view through zoom multipliers, distinct from weapon-mounted sights that integrate into the gun attachment system. ItemOpticAsset is the smallest non-empty item asset class at 41 lines. It defines standalone zoom items — binoculars, spotting scopes, and other hand-held optical devices that do not attach to guns. Unlike ItemSightAsset (which mounts to a weapon's sight hook), ItemOpticAsset is a complete holdable item with its own UseableOptic runtime class.

Source code location: Unturned/Bundles/ItemOpticAsset.cs

Inheritance Chain

ItemAsset
  → ItemOpticAsset

ItemOpticAsset extends ItemAsset directly. It does not inherit from ItemCaliberAsset or ItemWeaponAsset — it is a purely non-combat observation device. This is the flattest inheritance among all item asset classes with behavioral fields.

Class Definition

csharp
public class ItemOpticAsset : ItemAsset
{
    /// <summary>
    /// Factor e.g. 2 is a 2x multiplier.
    /// Prior to 2022-04-11 this was the target field of view. (90/fov)
    /// </summary>
    public float zoom { get; private set; }
}

The class contains exactly one field: zoom. All other properties — name, description, rarity, size, type, quality, and audio — are inherited from ItemAsset.

Zoom Field

FieldType.dat KeyDefaultDescription
zoomfloatZoom1.0 (clamped)Magnification factor

The zoom value is clamped to a minimum of 1.0:

csharp
zoom = Mathf.Max(1.0f, p.data.ParseFloat("Zoom"));

A value of 2.0 = 2x magnification. A value of 1.0 = no magnification (the minimum). Values below 1.0 are silently clamped — there is no wide-angle or de-magnification optic.

Zoom History

Prior to 2022-04-11, the zoom field represented a target field of view value (90/fov). It was refactored to a straightforward magnification multiplier. The old behavior can be reconstructed as 90.0f / zoom for backwards compatibility, though no migration code exists in the asset.

PopulateAsset

csharp
public override void PopulateAsset(in PopulateAssetParameters p)
{
    base.PopulateAsset(in p);
    zoom = Mathf.Max(1.0f, p.data.ParseFloat("Zoom"));
}

The implementation loads only the Zoom key from the .dat file. The base ItemAsset.PopulateAsset handles the standard item fields (ID, Name, Size_X, Size_Y, Amount, Rarity, Type, etc.).

BuildDescription

csharp
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance)
{
    base.BuildDescription(builder, itemInstance);

    if (!builder.HasFlag(EItemDescriptionFlags.Uncategorized))
        return;

    if (zoom != 1.0f)
    {
        builder.Append(PlayerDashboardInventoryUI.localization.format(
            "ItemDescription_ZoomFactor", zoom), DescSort_ItemStat);
    }
}

The description shows the zoom factor if it differs from 1.0. The zoom line is rendered as a standard item stat (not a gun attachment stat) using DescSort_ItemStat.

Cargo Data Export

ItemOpticAsset does not override BuildCargoData. All data is exported by the base ItemAsset.BuildCargoData to the Item Cargo table. The zoom field is not exported to Cargo at the asset level — it would need a custom table if wiki data export were required.

UseableOptic Runtime Behavior

The UseableOptic class (separate file, Useables/UseableOptic.cs) provides the runtime behavior for optic items:

  1. Equip: The optic item is held like any other item. A view model appears in the player's hands.
  2. Zoom activation: When the player presses the aim key (right mouse button by default), the camera's field of view is reduced according to zoom.
  3. Zoom calculation: The camera FOV is divided by zoom (e.g., 90 FOV at 2x = 45 FOV).
  4. Sensitivity adjustment: Mouse sensitivity may be adjusted during zoom to maintain a consistent feel.
  5. Deactivation: Releasing the aim key returns to normal FOV.

Unlike gun sights, UseableOptic does not:

  • Render a scope overlay.
  • Support night vision.
  • Have attachment slots.
  • Fire projectiles.
  • Consume ammunition.

Comparison to ItemSightAsset

PropertyItemOpticAssetItemSightAsset
Inherits fromItemAssetItemCaliberAsset
Attaches to gunsNoYes
Has stat modifiersNoYes (recoil, spread, etc.)
Has caliber systemNoYes
Has night visionNoYes
Has holographic modeNoYes
Has scope overlayNo (camera FOV only)Optional
Prefab loadingStandard item"Sight" bundle asset
Useable classUseableOpticIntegrated into UseableGun

Optic items are designed for observation and reconnaissance, not combat precision. They are the scouting equivalent of combat optics.

Common Use Cases

  1. Binoculars: Zoom=4 or Zoom=6 for long-range observation.
  2. Spotting scope: Zoom=8 to Zoom=12 for extreme distance.
  3. Magnifying glass: Zoom=2 for close-up examination.
  4. Range finder alternative: An optic item with Zoom=1 provides no magnification but occupies the item slot differently than the tactical rangefinder.

Common Issues

  1. Zoom minimum clamp — Values below 1.0 are silently clamped to 1.0. A Zoom=0.5 setting produces 1x, not wide-angle. There is no warning or error for sub-1.0 zoom values.
  2. No Cargo export for zoom — The zoom field is not exported to any Cargo table. Wiki data systems that expect to scrape zoom information from cargo tables will not find it for optic items.
  3. Same key as sight zoom — Both ItemSightAsset and ItemOpticAsset use the .dat key Zoom. However, ItemSightAsset validates and clamps the value in the same way (Mathf.Max(1.0f, ...)), so the key semantics are identical.
  4. Type assignment required — Optic items must be assigned EItemType.OPTIC in the ItemManager item registry. If misconfigured as another type, the UseableOptic class will not be activated and the item will not zoom.
  5. No third-person zoom — Unlike ItemSightAsset, ItemOpticAsset has no thirdPersonZoomFactor. When using an optic item in third-person view, the zoom is either unavailable or uses a hardcoded default.

Worked Code Example: Optic Zoom System

csharp
using SDG.Unturned;
using UnityEngine;

public class ZoomController
{
    private static float _defaultFOV = 90f;
    private static float _currentZoomTarget = 1f;

    /// <summary>
    /// Smoothly transitions the camera FOV to the target zoom level
    /// when the player aims an optic item. Supports configurable
    /// transition speed for smooth zoom animation.
    /// </summary>
    public static void ApplyZoom(float zoomFactor, float transitionSpeed)
    {
        if (Camera.main == null) return;

        float targetFOV = _defaultFOV / zoomFactor;
        _currentZoomTarget = Mathf.Lerp(
            Camera.main.fieldOfView,
            targetFOV,
            Time.deltaTime * transitionSpeed
        );

        Camera.main.fieldOfView = _currentZoomTarget;
    }

    /// <summary>
    /// Calculates the effective viewing range of an optic at given zoom,
    /// estimating the distance at which a 1-meter object subtends 10 pixels.
    /// </summary>
    public static float GetEffectiveRange(float zoomFactor, int screenHeight)
    {
        float angularSize = Mathf.Atan(1f / 100f) * Mathf.Rad2Deg;
        return (1f / angularSize) * zoomFactor * (screenHeight / 10f);
    }
}

Mermaid Diagram: Optic Zoom Pipeline

Comparison: Optic vs. Weapon Sight Zoom

FeatureItemOpticAssetItemSightAssetTactical Rangefinder
Attaches to weaponNoYes (sight hook)Yes (tactical slot)
Zoom mechanismCamera FOV divisionScope overlay or FOVDistance readout
Stat modifiersNoneRecoil, spread, sway via caliberNone (measurement only)
Night visionNoOptional (holographic)No
PrefabStandard item model"Sight" bundle assetHUD text overlay
SensitivityAdjusted during zoomAdjusted per sight configNo change
Zoom range1x to any float1x to configurable maxN/A (rangefinder)
InheritanceItemAsset (flat)ItemCaliberAssetItemAsset

Failure Modes and Common Mistakes

  1. Zoom clamping silent fail — Values below 1.0 are clamped to 1.0 without warning. A Zoom=0.5 setting silently becomes 1x. No log message or error indicates the clamp occurred.

  2. FOV conflict with other camera effects — Other systems (scoped weapons, flashbang overlay, night vision) may modify Camera.fieldOfView simultaneously. The last writer wins, causing optic zoom to be overridden or to override other intentional FOV effects.

  3. Zoom factor vs. actual FOV — The zoom formula divides default FOV by the zoom factor. At 90 FOV default, a 2x zoom = 45 FOV. Players accustomed to camera zoom conventions from other games may expect 2x to halve the FOV, which it does, but only when the default is 90.

How This Field Behaves Differently from the SDG Docs

  • SDG docs suggest optics have scope overlays. The documentation sometimes groups optics with scoped weapons. In the SDK, ItemOpticAsset has no scope overlay, no holographic mode, and no night vision. It is a pure camera FOV manipulator.
  • SDG docs list zoom as "optional." Some resources suggest binoculars work without a Zoom key. In the SDK, the Zoom key defaults to 0 (parsed as 0f), which is clamped to 1.0 — producing a "viewfinder" with no magnification.

Performance Considerations

Optic zoom is purely camera FOV manipulation — a single float assignment per frame. GPU cost is zero (no additional render passes). CPU cost is one Mathf.Lerp call (smooth zoom transition) at approximately 0.0001ms per frame. No memory allocation or garbage collection overhead.

Deeper FAQ

Q: Can I make a thermal or infrared optic?

Not through the optic asset alone. A Harmony patch on UseableOptic to modify the camera's render texture or apply a post-processing effect would be needed. Some servers use shader replacement on the camera during zoom for thermal overlays.

Q: Does zoom affect bullet spread or accuracy?

No. Standalone optics have no weapon stats. The zoom is visual only — it does not modify any weapon, projectile, or player stat.

Q: Can I use multiple optics simultaneously?

No. A player can only equip one item at a time. Equipping an optic unequips the previous item. UseableOptic overrides any weapon sight zoom while the optic is held.

Cross-References

Document history