给对象设置唯一标识符onStart

3

我有一堆游戏对象在Start函数中,我正在为它们分配唯一的id。

void Start() {
    UniqueID = String.Format("{0:X}", DateTime.Now.Ticks);
}

我认为这个方法是可行的,但有时候我会得到重复的ID。如何确保它们总是唯一的?

3
使用GUID,它在全球范围内是唯一的。 - David
可能是Unity3D中的随机数?的重复问题。 - Hana Bzh
根据MSDN关于DateTime.Now的规范,它的分辨率为10毫秒。我真希望你能在那么短的时间内生成一堆游戏对象 :-) - Paul-Jan
3个回答

6

我会使用GUID。

UniqueID = Guid.NewGuid.ToString();

使用您的建议,在同一时间运行的 2 个实例中,可能将相同的“唯一” UniqueID 应用于 2 个不同的对象。

即使跨实例,Guid 也应该是唯一的。


你的解决方案很好,谢谢。我仍然不明白如何在完全相同的时间实例化两个事物。我认为它们之间肯定会有一些时间间隔。 - Ogen
1
如果实例在不同的机器上运行或者2个线程在不同的核心上运行,可能会出现这种情况吗? - DermFrench
3
除了多线程,仅仅因为时间流逝,并不意味着被 DateTime.Now 使用的内部时钟已经“滴答”地运行。我建议你尝试编写一个示例程序,在循环中输出 DateTime.Now.Ticks,你可能会惊讶于在下一个不同值出现之前你会得到多少个相同的值。 - Jon Skeet

3

该方法无法为您的应用程序的多个实例提供唯一的Id!

我建议使用一个static long变量,并使用Interlocked.Increment来处理并发和同步,以便轻松地为您的对象分配Id。相比GUID,它更适用于调试目的和更易读,使用的内存也更少。

//define an accessible static variable somewhere in your code
public static long __Id = 0;

//use it to assign unique Id to objects
UniqueID = Interlocked.Increment(ref __Id);

此外,它的性能比GUID更好,这里是一个快速检查和结果

public static long __Id = 0;
private static void Main(string[] args)
{
    var sw1 = new Stopwatch();
    var guid = Guid.NewGuid();
    sw1.Start();
    for (var i = 0; i < 10000000; i++)
    {
        guid = Guid.NewGuid();
    }
    sw1.Stop();
    Console.WriteLine(guid);
    Console.WriteLine(sw1.ElapsedTicks);

    var sw2 = new Stopwatch();
    long id = 0;
    sw2.Start();
    for (var i = 0; i < 10000000; i++)
    {
        id = Interlocked.Increment(ref __Id);
    }
    sw2.Stop();
    Console.WriteLine(id);
    Console.WriteLine(sw2.ElapsedTicks);
}

并且结果为:

f91419e0-9d3a-4e64-b7fd-ed2080dad599
10376104 (全局唯一标识符时间)
10000000
304231 (长整型时间) 比全局唯一标识符快34倍


很遗憾,@DermFrench,不行。 - Hamid Pourjam

1

Unity已经为每个对象实例提供了唯一的ID,可以查看GetInstanceID


哇,我没想到那个。这让一切变得简单多了,谢谢你。 - Ogen
获取实例ID仅对会话唯一。它可能会重复出现。 - Ash Blue
@Ash Blue:OP在启动时分配了GUID,因此当前会话的最后一个应该就足够了。您不会在运行时获得任何重复的ID。 - Heisenbug
@Heisenbug 好的问题是,Unity仅保证ID在会话中是唯一的。因此,如果您关闭并再次打开Unity,则先前存储的实例ID可能会无意中复制自身。解决方案并不差,但它比C#Guid API创建了更大的误差边界。如果您有一个包含数千个对象的大型项目,则通过GetInstanceID很可能会意外复制ID。 - Ash Blue
因此,如果您关闭并重新打开Unity,则先前存储的实例ID可能会无意中复制自身。这与问题无关。OP没有要求保存guids。此外,跨会话保存guids毫无意义,并且这需要比简单的api调用更复杂的数据[de |序列化] [到|从]磁盘。 - Heisenbug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接