Fix CS0104: 'Random' is an ambiguous reference (Oxide plugins)
CS0104 means two imported namespaces both export a type called Random, so the compiler cannot pick one. In Oxide plugins it is almost always `using System;` plus `using UnityEngine;`, and the fix is to write `UnityEngine.Random.Range` explicitly.
Error while compiling RandomLoot: [1] 'Random' is an ambiguous reference between 'Oxide.Core.Random' and 'UnityEngine.Random' at 28:37
Why it happens
The Rust game assemblies define UnityEngine.Random (the engine RNG used for ranges, points in a sphere, and shared random state) and the .NET runtime defines System.Random (a class you instantiate with new Random()). Both namespaces are imported by nearly every plugin: System for Exception, DateTime, Math and Action; UnityEngine for Vector3, Quaternion, Time and TextAnchor. Once both are in scope, the bare name Random has two candidates and Roslyn stops with CS0104 rather than guessing. The error usually points at the first use, so a plugin with several Random.Range calls reports only line 30. Importing using Oxide.Game.Rust.Cui; or using Newtonsoft.Json; does not cause this; only the two RNG types collide.
How to fix it
Pick the type you actually meant and spell it out.
- For engine randomness (random integer or float ranges, random points, shared seed) replace
Random.Range(...)withUnityEngine.Random.Range(...). This is what most Rust plugin code wants. - For a private .NET generator, keep
new System.Random()and keep calling instance methods on that variable; static engine methods do not exist on it. - Fix every occurrence, not just the reported line. A search for
Random.without a namespace prefix finds the rest. - Alternatively drop the unqualified import (
using UnityEngine;) and qualify the engine types too, but this is verbose and rarely worth it. - Save the file, which triggers an automatic reload, or run
oxide.reload RandomLoot. Success printsLoaded plugin RandomLoot v1.0.0 by RustPluginGenerator; theError while compilingblock stops appearing.
Before and after
using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("RandomLoot", "RustPluginGenerator", "1.0.0")]
[Description("Gives a player a random item from a configured list")]
public class RandomLoot : RustPlugin
{
private readonly List<string> pool = new List<string>
{
"scrap", "metal.fragments", "wood", "stone", "cloth", "lowgradefuel"
};
[ChatCommand("rangeloot")]
private void CmdRangeLoot(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsConnected) return;
GiveRandomItem(player);
}
private void GiveRandomItem(BasePlayer player)
{
if (pool.Count == 0) return;
string shortname = pool[Random.Range(0, pool.Count)];
int amount = Random.Range(5, 20);
var item = ItemManager.CreateByName(shortname, amount);
if (item == null)
{
Puts("Unknown item shortname: " + shortname);
return;
}
if (!player.inventory.GiveItem(item))
{
item.Drop(player.transform.position, Vector3.zero);
}
SendReply(player, "You received " + amount + " x " + item.info.displayName.english);
}
}
}using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("RandomLoot", "RustPluginGenerator", "1.0.0")]
[Description("Gives a player a random item from a configured list")]
public class RandomLoot : RustPlugin
{
private readonly List<string> pool = new List<string>
{
"scrap", "metal.fragments", "wood", "stone", "cloth", "lowgradefuel"
};
[ChatCommand("rangeloot")]
private void CmdRangeLoot(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsConnected) return;
GiveRandomItem(player);
}
private void GiveRandomItem(BasePlayer player)
{
if (pool.Count == 0) return;
string shortname = pool[UnityEngine.Random.Range(0, pool.Count)];
int amount = UnityEngine.Random.Range(5, 20);
var item = ItemManager.CreateByName(shortname, amount);
if (item == null)
{
Puts("Unknown item shortname: " + shortname);
return;
}
if (!player.inventory.GiveItem(item))
{
item.Drop(player.transform.position, Vector3.zero);
}
SendReply(player, "You received " + amount + " x " + item.info.displayName.english);
}
}
}FAQ
Why does the compiler only report one line when I have three Random calls?
The compiler stops on the first construct that makes the name ambiguous, so one error is reported per compile pass. Fix the reported line, reload, and the next ambiguous use (if any) is reported. Searching for Random. without a namespace prefix catches all of them at once.
I removed `using UnityEngine;` and now get CS0246 instead.
Removing that import also removes Vector3, Quaternion and Time, so they become unknown. Keep the import and qualify the ambiguous name instead: UnityEngine.Random.Range(min, max). See the CS0246 page if other types are still unresolved.
Does Carbon report this error differently?
Carbon compiles the same C# and reports the same CS0104 message, but it prints the CS code next to the message in its own format. The fix is identical because it is a C# rule, not an Oxide rule.
Is `System.Random` ever the right choice here?
Only if you want a self-contained generator you seed and store, for example reproducible loot rolls kept in data. For one-off ranges in hooks, the engine RNG is simpler and needs no field. If you use it, store the instance in a field and call methods on that field, never the bare type name.
Different error?
Paste the full console output and get the cause and a fix in plain English.
Open the error explainerSkip the debugging
Generated plugins are compiled before you get them, and compiler errors are fixed automatically.
Generate a plugin2 free plugins a month, no card.
Last updated Oct 26, 2026.
Get plugins that compile first time
Generate