Search Unity

using unsafe in IComponentData structs

Discussion in 'Entity Component System' started by yc960, Mar 12, 2019.

  1. yc960

    yc960

    Joined:
    Apr 30, 2015
    Posts:
    228
    I have a large IComponentData struct with over 30 floats that I want to iterate using index. I see that float4 has this capability but is made with unsafe code. What are the potential side effect of using unsafe in this context? Since float4 has unsafe keyword in it I assume it will be fine?
     
  2. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    unsafe = give up c# safety mechanism, such as null and bounds check.
    a bug in unsafe code may crash your app or corrupt it in strange ways.

    e.g. you can define 30 fields and access *(&this + 40) in unsafe code. the runtime will not do the checks for you.
     
    yc960 likes this.
  3. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    "unsafe" kinda loses its meaning when you are using HPC# :) If I'm not mistaken, quite a lot of the ECS framework and Burst uses it.

    I wouldn't worry about using float4 at all, but you should worry if you have to write any code yourself that uses the unsafe keyword.
     
    yc960 likes this.
  4. yc960

    yc960

    Joined:
    Apr 30, 2015
    Posts:
    228
    Since ECS and burst already uses unsafe keyword, would I be locked out of deploying on certain platforms when I use it as well? I am not that worried about bugs as this is the only instance where I deem unsafe necessary.
     
    Neiist likes this.
  5. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    No. Use unsafe whenever you want, just don't make your application crash.
     
    Neiist, yc960, siggigg and 1 other person like this.
  6. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    Afaik that would only happen when running on a runtime like the .NET CLR, which Unity is not :)
     
    yc960 likes this.
  7. TheZombieKiller

    TheZombieKiller

    Joined:
    Feb 8, 2013
    Posts:
    265
    To avoid this, I generally make use of Span<T> to ensure that accesses to the fields don't go out of bounds:
    Code (CSharp):
    1.  
    2. // The 'unsafe' modifier, when present on a signature, doesn't actually prevent
    3. // you from using a struct, class or method from safe code, as one would expect.
    4. unsafe struct Example
    5. {
    6.     fixed float thirtyFloats[30];
    7.     public Span<float> ThirtyFloats => CreateSpan(ref thirtyFloats[0], 30);
    8. }
    9.  
    10. // CreateSpan is a custom implementation of MemoryMarshal.CreateSpan, as
    11. // it isn't available in .NET Standard 2.0, only the upcoming 2.1 version.
    12.  
    13. // These custom implementations of CreateSpan and CreateReadOnlySpan
    14. // require that you can use System.Runtime.CompilerServices.Unsafe.
    15.  
    16. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    17. public static unsafe Span<T> CreateSpan<T>(ref T reference, int length)
    18.     => new Span<T>(Unsafe.AsPointer(ref reference), length);
    19.  
    20. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    21. public static unsafe ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length)
    22.     => new ReadOnlySpan<T>(Unsafe.AsPointer(ref reference), length);
     
    yc960 likes this.