.net c#在onStart上赋予对象唯一的ID

Giving objects unique ids onStart
2020-10-17
  •  译文(汉语)
  •  原文(英语)

我有一堆gameObjects,我要在Start函数中为其分配唯一的ID.

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

我以为这会工作,但有时我会得到重复的ID.我如何确保它们始终是唯一的?

速聊1:
使用GUID.这在全球范围内是独一无二的
速聊2:
速聊3:
根据DateTime.Now上的MSDN规范,现在它的分辨率为10毫秒.我肯定希望您能够在这段时间内生成一堆GameObjects :-)
解决过程1

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

速聊1:
哇,我没意识到.谢谢,这使一切变得如此简单.
速聊2:
获取实例ID仅对于会话是唯一的.它最终可能会自我复制.
速聊3:
蓝色:在启动过程中OP分配的GUID,因此如果当前会话的最后一个GUI应该足够.在运行时,您将不会获得任何重复的ID.
速聊4:
好了,问题是Unity只保证ID对于会话是唯一的.因此,如果再次关闭并打开Unity,则先前存储的实例ID可能会无意中复制自身.该解决方案还不错,但是与C#Guid API相比,它会产生更大的错误余量.如果您的大型项目包含数千个对象,则很可能会意外地复制ID GetInstanceID.
速聊5:
"因此,如果您再次关闭并打开Unity,先前存储的实例ID可能会无意间复制自身".这与问题无关.OP并没有要求保存向导.另外,跨会话保存向导是没有意义的,与简单的api调用相比,这将需要更复杂的数据从磁盘[反序列化]到磁盘.
解决过程2

我会使用GUID.

UniqueID = Guid.NewGuid.ToString();

根据您的建议,两个同时运行的实例可以将相同的"唯一" UniqueID应用于两个不同的对象.

Guid即使在实例之间也应该是唯一的.

速聊1:
您的解决方案效果很好,谢谢.我仍然看不到如何在完全相同的时间实例化两件事.我认为他们之间肯定会经过一段时间.
速聊2:
如果实例在不同的计算机上运行,​​或者两个线程在不同的内核上运行?
速聊3:
:除了多线程之外,仅仅因为时间流逝并不意味着"使用DateTime.Now" 内部时钟.我建议您尝试编写一个示例程序以DateTime.Now.Ticks循环写出-您可能会惊讶于在下次获得另一个值之前获得了多少个相等的值.
解决过程3

此方法无法在您的应用程序的多个实例之间提供唯一的ID!

我建议使用static long变量并使用Interlocked.Increment处理并发性和同步,以便您可以轻松地将ID分配给对象.在调试方面,它比GUID更好,并且可读性更好.与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倍

速聊1:
抱歉不行.

I have a bunch of gameObjects that I am assigning unique ids to in the Start function.

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

I thought this would work but every now and then I get duplicate ids. How can I make sure that they are always unique?

Talk1:
use GUID. Which is unique globally
Talk2:
possible duplicate of Random Numbers in Unity3D?
Talk3:
According to the MSDN specs on DateTime.Now, it has a resolution of 10 milliseconds. I'd sure hope you are able to generate a whole bunch of GameObjects in that amount of time :-)
Solutions1

Unity already provide an unique id for every object instance, have a look at GetInstanceID.

Talk1:
Wow, I did not realise that. That makes everything so much simpler, thank you.
Talk2:
Get instance ID is only unique to the session. It could end up duplicating itself.
Talk3:
Blue: the OP's assigning guid during start, so it should be enough if the last for the current session. You won't get any duplicated id at runtime.
Talk4:
Well the problem is Unity only guarantees that the ID will be unique for the session. So if you close and open up Unity again the previously stored instance ID can unintentionally replicate itself. The solution isn't bad, but it creates a larger margin of error than the C# Guid API. If you have a larger project with thousands of objects it's very possible to accidentally replicate an ID via GetInstanceID.
Talk5:
" So if you close and open up Unity again the previously stored instance ID can unintentionally replicate itself". This isn't relevant for the question. The OP didn't ask for saving guids. In addition it makes no sense to save guids across sessions, and this would require more complex [de|serialization] of data [to|from] disk than a simply api call.
Solutions2

I would use a guid.

UniqueID = Guid.NewGuid.ToString();

Using your suggestion, 2 instances running at same time, may apply the same "unique" UniqueID to 2 different objects.

Guid should be unique even across instances.

Talk1:
Your solution works nicely, thanks. I still don't see how two things can be instantiated at exactly the same time. I thought surely some time would pass between them.
Talk2:
If the instances where running on a different machine or 2 threads running on different cores maybe?
Talk3:
: Aside from multi-threading, just because time passes doesn't mean the internal clock used by DateTime.Now has "ticked". I suggest you try writing a sample program to write out DateTime.Now.Ticks in a loop - you may be surprised at how many equal values you get before you next get a different one.
Solutions3

This method does not provide unique Id across multiple instances of your application!

I suggest using a static long variable and using Interlocked.Increment which handles the concurrency and synchronizing so you can easily assign Id to your objects. It is better than GUID for debugging purposes and more readable, It uses less memory than 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);

also its performance is better than GUID, here is a quick check and the result

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);
}

and the result

f91419e0-9d3a-4e64-b7fd-ed2080dad599
10376104 (guid time)
10000000
304231 (long time) 34 times faster than guid

Talk1:
unfortunately no.
转载于:https://stackoverflow.com/questions/30816595/giving-objects-unique-ids-onstart

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入