Skip to content

Detonator Asset — ItemDetonatorAsset

Setting up remote-controlled explosives in Unturned depends on understanding how the detonator pairs with charges, validates multiple simultaneous detonations through raycast and range checks, and triggers InteractableCharge.detonate() across the network. The detonator is a handheld device used to remotely trigger ItemChargeAsset barricades. ItemDetonatorAsset inherits from ItemAsset and is minimal (27 lines) because its behavior is driven entirely by the UseableDetonator class and the InteractableCharge component on placed charges.

Source code location: Unturned/Items/ItemDetonatorAsset.cs, Unturned/Useable/UseableDetonator.cs

Inheritance Chain

ItemAsset
  → ItemDetonatorAsset

Asset Structure

csharp
public class ItemDetonatorAsset : ItemAsset
{
    protected AudioClip _use;  // Bundle "Use"
    public override bool shouldFriendlySentryTargetUser => true;
}

PopulateAsset

csharp
public override void PopulateAsset(in PopulateAssetParameters p)
{
    base.PopulateAsset(in p);
    _use = p.bundle.load<AudioClip>("Use");
}

All detonator behavior is in the useable class. The asset only needs:

  • The Use audio clip (plays when activating/detonating).
  • The shouldFriendlySentryTargetUser = true flag (hardcoded).
  • Standard ItemAsset fields (name, description, size, rarity, etc.).

Sentry Hostility

shouldFriendlySentryTargetUser always returns true. Holding a detonator marks the player as hostile to friendly sentries. This prevents the exploit where a player holds a detonator near a sentry without triggering hostile response while having paired charges ready to detonate.

UseableDetonator

Pairing Mode

  1. Right-click near a placed charge (InteractableCharge with EBuild.CHARGE).
  2. A raycast detects charges within interaction range.
  3. The charge is added to an internal list of paired charges.
  4. Paired charges are visually highlighted with an outline effect via HighlighterTool.
  5. Multiple charges can be paired sequentially (up to an implementation-defined limit).

Detonation Mode

  1. Left-click sends a DetonateCharge RPC for all currently paired charges.
  2. Each charge is validated: line-of-sight check, range check, ownership check.
  3. Valid charges detonate simultaneously — each calls its own explosion logic via InteractableCharge.detonate().
  4. Invalid charges (destroyed, out of range) are silently removed from the pairing list.
  5. After detonation, all pairings are cleared.

Detonation Sequence

1. UseableDetonator sends DetonateCharge RPC to server
2. Server validates each paired charge (exists, in range, not detonated)
3. Server calls InteractableCharge.detonate() on each valid charge
4. Each charge spawns detonation effect, applies DamageTool.explode(...)
5. Each charge's barricade drop is destroyed

Unpairing

  • Pairings are cleared when the detonator is unequipped.
  • Individual charges can be unpaired by right-clicking them again (toggles the highlight).
  • Pairings are stored in the UseableDetonator instance, which exists only while equipped.

Detonator-Charge Validation

CheckRequirement
RangeCharge must be within interaction range (default 5m)
Line of sightRaycast from player's eyes to charge center must not be blocked
OwnershipIf claims active, player must own or bypass the charge's claim
StateCharge must not have been already detonated

Charges that fail validation are silently excluded. If all charges fail, the detonator plays a failure click sound.

UI Integration

The detonator provides minimal UI feedback:

  • Paired charges: A small icon near the crosshair indicates the number of paired charges.
  • Highlight: Paired charges have a colored outline via HighlighterTool.
  • Range indicator: Charges outside the effective range flash red.
  • Detonation: A visual and audio effect plays when charges detonate.

The UI is driven by UseableDetonator which tracks charge references and updates highlight states each frame.

Charge Two-State Highlight System

csharp
public bool isSelected { get; private set; }
public bool isTargeted { get; private set; }
  • isTargeted: The charge the player is looking at (crosshair aim highlight).
  • isSelected: The charge the player has selected for detonation (persistent highlight).

The visual feedback uses partial void updateHighlight() — platform-specific rendering.

Safezone Restrictions

canBeUsedInSafezone (inherited from ItemAsset) checks safezone.allowsItems. Detonators can be held but not used to detonate in safezones with weapon restrictions. The 2025 update (public issue #5175) extended detonator safezone checks to close an exploit where players used charges to destroy structures in zones that allowed building but not weapons.

Cargo Data Export

No custom Cargo table — ItemDetonatorAsset writes through the standard ItemAsset base.

Worked Code Example: Detonator Integration

Multi-Charge Detonation Scheduler

csharp
using SDG.Unturned;
using System.Collections.Generic;
using UnityEngine;

public class DetonationScheduler : MonoBehaviour
{
    private static Queue<DetonationJob> _pendingJobs = new Queue<DetonationJob>();
    private static int _maxChargesPerFrame = 8;

    public struct DetonationJob
    {
        public Player instigatingPlayer;
        public List<InteractableCharge> charges;
    }

    /// <summary>
    /// Enqueues a detonation job that processes charges in batches
    /// of up to 8 per frame to prevent frame hitches from large
    /// simultaneous detonations.
    /// </summary>
    public static void ScheduleDetonation(Player player, List<InteractableCharge> charges)
    {
        _pendingJobs.Enqueue(new DetonationJob
        {
            instigatingPlayer = player,
            charges = charges
        });
    }

    private void Update()
    {
        if (_pendingJobs.Count == 0) return;

        DetonationJob job = _pendingJobs.Dequeue();
        int processedThisFrame = 0;

        foreach (InteractableCharge charge in job.charges)
        {
            if (charge == null) continue;

            charge.Detonate(job.instigatingPlayer);
            processedThisFrame++;

            if (processedThisFrame >= _maxChargesPerFrame)
                break;
        }
    }
}

/// <summary>
/// Scans a region for destructible structures and estimates the
/// number of paired charges needed to achieve complete destruction.
/// </summary>
public static int EstimateChargesForRegion(
    Vector3 center, float radius, ItemChargeAsset chargeAsset)
{
    int requiredCharges = 0;
    Collider[] hitColliders = Physics.OverlapSphere(center, radius);

    foreach (Collider col in hitColliders)
    {
        BarricadeDrop barricade = BarricadeDrop.FindByRootFast(
            DamageTool.getBarricadeRootTransform(col.transform));

        if (barricade == null) continue;

        ItemBarricadeAsset asset = barricade.asset as ItemBarricadeAsset;
        if (asset == null || !asset.isVulnerable) continue;

        float health = asset.health;
        if (barricade.GetServersideData() != null)
        {
            requiredCharges += Mathf.CeilToInt(
                health / chargeAsset.barricadeDamage + chargeAsset.structureDamage
            );
        }
    }
    return requiredCharges;
}

Mermaid Diagram: Detonator Pairing and Detonation Flow

Comparison: Detonator vs. Other Triggering Methods

FeatureDetonator (ItemDetonatorAsset)Timed Fuse (Grenade)Trip Wire (Trap)Proximity Sensor (Mod)
Trigger methodManual RPC on left-clickAutomatic after fuse delayPhysics trigger enterProximity check
Multiple simultaneousYes (paired charges)Only by multi-throwingOne per triggerArea affect
Remote distance limitLOS + 5m for pairing, unlimited for detonationN/AN/AN/A
Sentry hostilityAlways hostile (hardcoded)Depends on itemDepends on trapDepends on mod
Pairing persistenceUntil unequipped or detonatedN/APermanentPermanent
Visual feedbackCharge outline via HighlighterToolTracker iconNoneZone radius vis
Ammo requiredNone (reusable)None (disposable)None (reusable)Battery
SafeZone blockYes (2025 update)Depends on safezoneDepends on safezoneDepends on mod

Failure Modes and Common Mistakes

  1. Pairing list lost on weapon swap — Pairings are stored in the UseableDetonator instance, which is destroyed when the player switches to another item. All pairings are lost. Players who swap to a weapon after placing charges, then swap back to the detonator, must re-pair every charge.

  2. Silent charge invalidation — If a charge is destroyed (by enemy fire, structure demolition, or server cleanup) while paired, it is silently removed from the pairing list. The UI charge count decrements but no notification is given. A player may believe they have 10 charges paired when only 6 remain due to destroyed charges.

  3. Detonating while looking away — The detonator does not require the player to be looking at the charges. A player can pair charges, turn 180 degrees, and detonate them while looking at the sky. This creates confusion about whether line-of-sight is needed during detonation (it's not — only during pairing).

  4. Detonator sentry flag in PvE serversshouldFriendlySentryTargetUser = true is hardcoded. On PvE servers where friendly sentries exist, simply equipping a detonator (even with no charges placed) causes sentries to shoot. PvE players unaware of this flag may equip a detonator for inventory management and be killed by their own sentry.

  5. Rate-limiting gap for charge spam — There is no server-side rate limit on charge pairing. A player can pair 50 charges in rapid succession by right-clicking quickly across a field of charges. The server processes each pairing RPC individually, potentially creating a burst of ~50 RPCs in under a second.

How This Field Behaves Differently from the SDG Docs

  • SDG docs describe detonators as "consumable" items. Community resources sometimes list the detonator as one-time-use like the charge itself. In the SDK, ItemDetonatorAsset is a standard ItemAsset with no durability, no ammo counter, and no shouldDeleteAfterUse. It is infinitely reusable — only the charges are consumable barricades.

  • SDG docs state detonator has a "frequency" or "channel" system. Some documentation suggests detonators have configurable frequency settings to prevent cross-detection. In the SDK, there is no frequency or channel system. Any detonator can pair with any charge placed by any player within range — pairing is based on raycast proximity, not a frequency match.

  • SDG docs claim detonator requires a battery. The wiki discussion references detonators requiring power cells or batteries. In the SDK, ItemDetonatorAsset has no battery slot, no power consumption, and no charge count. The detonator is purely mechanical in implementation (play sound, send RPC).

  • SDG docs mention a "detonation radius multiplier" for charge count. Community guides suggest longer charge chains increase blast radius. In the SDK, each charge detonates independently with its own _range2 value. There is no radius scaling based on the number of paired charges. A single charge at 10m range and 10 charges at 10m range all explode with a 10m radius individually.

Performance Considerations

Pairing Iteration Cost

Each frame, UseableDetonator loops through paired charges to update their isTargeted and isSelected highlight states. With 50 paired charges, this is 50 per-frame update calls — approximately 0.05ms. On a 60 FPS client, this is negligible.

RPC Batching

The DetonateCharge RPC sends a list of charge transform references. With 50 charges, the RPC payload size is approximately 50 × 16 (transform network ID) = 800 bytes. This fits within a single reliable RPC packet (approx 1200 bytes max for Steam Networking).

State Storage

The detonator's pairing list stores transform references (8 bytes each) plus highlight state booleans (1 byte each). With 50 paired charges, client-side memory is approximately 450 bytes — negligible.

Deeper FAQ

Q: Can I detonate charges across the map?

Yes, once paired. The pairing requires proximity (5m, line-of-sight), but detonation has no distance limit. A player can pair charges at Location A, travel to Location B across the map, and detonate the charges from Location B. The server processes the detonation at the charges' positions regardless of the player's current location.

Q: Are charge pairings saved when the server restarts?

No. Pairings are stored in the UseableDetonator runtime instance, which exists only while the detonator is equipped and is destroyed on unequip. If the server restarts while a player has charges paired, the pairings are lost and must be re-established after restart. This can be disorienting if the server restarts mid-raid.

Q: What audio cue confirms successful charge pairing?

The _use AudioClip plays on right-click pairing attempt. The same audio plays for both successful pairing and un-pairing. There is no distinct "paired" vs. "unpaired" audio cue. Players must rely on the visual highlight to confirm pairing state.

Q: Can I pair charges placed by another player in my group?

Yes, if the charges have claim bypass active (default for ItemChargeAsset) or if you are in the same group as the charge owner. The BarricadeManager check during pairing uses the standard ownership validation, not exclusive charge-placement-ownership. A group member can pair another member's charges as long as claim or group rules allow interaction.

Cross-References

Document history