I'm building my game and after like 4 seconds there is an error that says:
Assets\PlayerInventory.cs(228,37): error CS0103: The name 'ObjectNames' does not exist in the current context
I'm using the function so that the objects don't all have the same name, but I can't build because of it. I'm using it like this:
string uniqueName = ObjectNames.GetUniqueName(names, "");
this is just adding a number on the end so it would be
Object
Object (1)
Object (2)
and so on...
Why is it not letting me build?
EDIT:
Code snippet:
using System.Collections;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using UnityEditor;
using Photon.Pun;
using UnityEngine.UI;
public class PlayerInventory : MonoBehaviour
{
// Names taken
public string[] names = new string[] { "Object" };
void Start()
{
string uniqueName = ObjectNames.GetUniqueName(names, "");
}
}
Some of the using
are not needed for this snippet.
CodePudding user response:
Because ObjectNames
is part of the namespace UnityEditor
which only exists within the Unity editor itself and is completely stripped of during the build process.
=> You can't use any of it in the actual released application, it is only for doing stuff within the editor itself.
Unfortunately the exact content of GetUniqueName
is also not public in the source code but you can implement something similar yourself.
There might be better and more efficient ways but I would go with e.g.
public static class StringExtensions
{
// Regex Matches a trailing indexer
// e.g. "Example (1)"
private const string k_IndexMatch = " \\(([0-9] )\\)$";
private static bool HasIndexer(string name, out int? index, out string nameWithoutIndex)
{
var matches = Regex.Matches(name, k_IndexMatch);
var nameIndexMatch = matches.LastOrDefault();
// or in case of older Unity/c# version without Linq
//var nameIndexMatch = matches.Count == 0 ? null : matches[matches.Count - 1];
if (nameIndexMatch == null)
{
index = null;
nameWithoutIndex = name;
return false;
}
// First group is always entire match, we want only the numeric value which is the second group
var group = nameIndexMatch.Groups[1];
index = int.Parse(group.Value);
nameWithoutIndex = name.Substring(0, name.Length - nameIndexMatch.Value.Length);
return true;
}
public static string GetUniqueName(this string name, IEnumerable<string> existingNames)
{
HasIndexer(name, out var index, out var nameWithoutIndex);
foreach (var existingName in existingNames)
{
if (existingName == nameWithoutIndex)
{
// Exact match (without index)
// in this case either keep your index or if there is none use 1
if (index == null)
{
index = 1;
}
continue;
}
if (HasIndexer(existingName, out var existingIndex, out var existingNameWithoutIndex))
{
if (existingNameWithoutIndex == nameWithoutIndex)
{
index = index == null ? existingIndex 1 : Math.Max(index.Value, existingIndex.Value 1);
}
}
}
return nameWithoutIndex (index == null ? "" : $" ({index})");
}
}
See also .NetFiddle (older c#)
Example usage
var uniqueName = "Example".GetUniqueName(new []{"Example 0", "Example (1)", "Nope", "Example", "Example (2)"});
=>
Example (3)
since only "Example (1)", "Example", "Example (2)"
are overlapping matches and highest free index is 3
.