Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

NativeList Remove and RemoveAt methods

Discussion in 'Entity Component System' started by jGate99, Nov 17, 2019.

  1. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936
    Hi there,

    I'm using NativeList in Jobs but how do i RemoveAt(index) and Remove(item) pefrom these operations as there is no implementation for that?

    How do you handle these requirements which require these methods?

    Thanks
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    If you don't care about order, there is a fast remove using RemoveAtSwapBack

    Code (CSharp):
    1.         /// <summary>
    2.         /// Truncates the list by replacing the item at the specified index with the last item in the list. The list
    3.         /// is shortened by one.
    4.         /// </summary>
    5.         /// <param name="index">The index of the item to delete.</param>
    6.         /// <exception cref="ArgumentOutOfRangeException">If index is negative or >= <see cref="Length"/>.</exception>
    7.         public void RemoveAtSwapBack(int index)
    Otherwise here are a bunch of extension methods I've written at some point or other.

    void Reverse<T>(this NativeList<T> list)
    void Insert<T>(this NativeList<T> list, T item, int index)
    bool Remove<T, TI>(this NativeList<T> list, TI element)
    void RemoveAt<T>(this NativeList<T> list, int index)
    void RemoveRange<T>(this NativeList<T> list, int index, int count)
    void ResizeInitialized<T>(this NativeList<T> buffer, int length)
    void ResizeInitializeNegativeOne(this NativeList<int> buffer, int length)

    Some of these are based off similar implementations Unity added to dynamic buffers. Some are more efficient / optimized than others. I also wrote most of these 6+ months ago so been a while to see if they could be improved.

    Code (CSharp):
    1. // <copyright file="NativeListExtensions.cs" company="BovineLabs">
    2. //     Copyright (c) BovineLabs. All rights reserved.
    3. // </copyright>
    4.  
    5. namespace BovineLabs.Common.Extensions
    6. {
    7.     using System;
    8.     using Unity.Collections;
    9.     using Unity.Collections.LowLevel.Unsafe;
    10.  
    11.     /// <summary>
    12.     /// Extension methods for <see cref="NativeList{T}"/>.
    13.     /// </summary>
    14.     public static class NativeListExtensions
    15.     {
    16.         /// <summary>
    17.         /// Reverses a <see cref="NativeList{T}"/>.
    18.         /// </summary>
    19.         /// <typeparam name="T"><see cref="NativeList{T}"/>.</typeparam>
    20.         /// <param name="list">The <see cref="NativeList{T}"/> to reverse.</param>
    21.         public static void Reverse<T>(this NativeList<T> list)
    22.             where T : struct
    23.         {
    24.             var length = list.Length;
    25.             var index1 = 0;
    26.  
    27.             for (var index2 = length - 1; index1 < index2; --index2)
    28.             {
    29.                 var obj = list[index1];
    30.                 list[index1] = list[index2];
    31.                 list[index2] = obj;
    32.                 ++index1;
    33.             }
    34.         }
    35.  
    36.         /// <summary>
    37.         /// Insert an element into a list.
    38.         /// </summary>
    39.         /// <typeparam name="T">The type.</typeparam>
    40.         /// <param name="list">The list.</param>
    41.         /// <param name="item">The element.</param>
    42.         /// <param name="index">The index.</param>
    43.         public static unsafe void Insert<T>(this NativeList<T> list, T item, int index)
    44.             where T : struct
    45.         {
    46.             if (list.Length == list.Capacity - 1)
    47.             {
    48.                 list.Capacity *= 2;
    49.             }
    50.  
    51.             // Inserting at end same as an add
    52.             if (index == list.Length)
    53.             {
    54.                 list.Add(item);
    55.                 return;
    56.             }
    57.  
    58.             if (index < 0 || index > list.Length)
    59.             {
    60.                 throw new IndexOutOfRangeException();
    61.             }
    62.  
    63.             // add a default value to end to list to increase length by 1
    64.             list.Add(default);
    65.  
    66.             int elemSize = UnsafeUtility.SizeOf<T>();
    67.             byte* basePtr = (byte*)list.GetUnsafePtr();
    68.  
    69.             var from = (index * elemSize) + basePtr;
    70.             var to = (elemSize * (index + 1)) + basePtr;
    71.             var size = elemSize * (list.Length - index - 1); // -1 because we added an extra fake element
    72.  
    73.             UnsafeUtility.MemMove(to, from, size);
    74.  
    75.             list[index] = item;
    76.         }
    77.  
    78.         /// <summary>
    79.         /// Remove an element from a <see cref="NativeList{T}"/>.
    80.         /// </summary>
    81.         /// <typeparam name="T">The type of NativeList.</typeparam>
    82.         /// <typeparam name="TI">The type of element.</typeparam>
    83.         /// <param name="list">The NativeList.</param>
    84.         /// <param name="element">The element.</param>
    85.         /// <returns>True if removed, else false.</returns>
    86.         public static bool Remove<T, TI>(this NativeList<T> list, TI element)
    87.             where T : struct, IEquatable<TI>
    88.             where TI : struct
    89.         {
    90.             var index = list.IndexOf(element);
    91.             if (index < 0)
    92.             {
    93.                 return false;
    94.             }
    95.  
    96.             list.RemoveAt(index);
    97.             return true;
    98.         }
    99.  
    100.         /// <summary>
    101.         /// Remove an element from a <see cref="NativeList{T}"/>.
    102.         /// </summary>
    103.         /// <typeparam name="T">The type.</typeparam>
    104.         /// <param name="list">The list to remove from.</param>
    105.         /// <param name="index">The index to remove.</param>
    106.         public static void RemoveAt<T>(this NativeList<T> list, int index)
    107.             where T : struct
    108.         {
    109.             list.RemoveRange(index, 1);
    110.         }
    111.  
    112.         /// <summary>
    113.         /// Removes a range of elements from a <see cref="NativeList{T}"/>.
    114.         /// </summary>
    115.         /// <typeparam name="T">The type.</typeparam>
    116.         /// <param name="list">The list to remove from.</param>
    117.         /// <param name="index">The index to remove.</param>
    118.         /// <param name="count">Number of elements to remove.</param>
    119.         public static unsafe void RemoveRange<T>(this NativeList<T> list, int index, int count)
    120.             where T : struct
    121.         {
    122. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    123.             if ((uint)index >= (uint)list.Length)
    124.             {
    125.                 throw new IndexOutOfRangeException(
    126.                     $"Index {index} is out of range in NativeList of '{list.Length}' Length.");
    127.             }
    128. #endif
    129.  
    130.             int elemSize = UnsafeUtility.SizeOf<T>();
    131.             byte* basePtr = (byte*)list.GetUnsafePtr();
    132.  
    133.             UnsafeUtility.MemMove(basePtr + (index * elemSize), basePtr + ((index + count) * elemSize), elemSize * (list.Length - count - index));
    134.  
    135.             // No easy way to change length so we just loop this unfortunately.
    136.             for (var i = 0; i < count; i++)
    137.             {
    138.                 list.RemoveAtSwapBack(list.Length - 1);
    139.             }
    140.         }
    141.  
    142.         /// <summary>
    143.         /// Resizes a <see cref="NativeList{T}"/> and then clears the memory.
    144.         /// </summary>
    145.         /// <typeparam name="T">The type.</typeparam>
    146.         /// <param name="buffer">The <see cref="NativeList{T}"/> to resize.</param>
    147.         /// <param name="length">Size to resize to.</param>
    148.         public static unsafe void ResizeInitialized<T>(this NativeList<T> buffer, int length)
    149.             where T : struct
    150.         {
    151.             buffer.ResizeUninitialized(length);
    152.             UnsafeUtility.MemClear(buffer.GetUnsafePtr(), length * UnsafeUtility.SizeOf<T>());
    153.         }
    154.  
    155.         /// <summary>
    156.         /// Resizes a <see cref="NativeList{T}"/> and then sets all the bits to 1.
    157.         /// For an integer array this is the same as setting the entire thing to -1.
    158.         /// </summary>
    159.         /// <param name="buffer">The <see cref="NativeList{T}"/> to resize.</param>
    160.         /// <param name="length">Size to resize to.</param>
    161.         public static void ResizeInitializeNegativeOne(this NativeList<int> buffer, int length)
    162.         {
    163.             buffer.ResizeUninitialized(length);
    164.  
    165. #if UNITY_2019_3_OR_NEWER
    166.             unsafe
    167.             {
    168.                 UnsafeUtility.MemSet(buffer.GetUnsafePtr(), byte.MaxValue, length * UnsafeUtility.SizeOf<int>());
    169.             }
    170. #else
    171.             for (var i = 0; i < length; i++)
    172.             {
    173.                 buffer[i] = -1;
    174.             }
    175. #endif
    176.         }
    177.     }
    178. }
     
    Last edited: Nov 17, 2019
  3. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,936

    Thank you very much, these extensions should have been part of NativeList.

    Edit: Just realized you created this awesome stuff and much more, thank you for making lives easier for others.
     
  4. PBN_Pure

    PBN_Pure

    Joined:
    Jan 10, 2020
    Posts:
    23
    Thamks a bunch bro
     
  5. radiatoryang

    radiatoryang

    Joined:
    Jul 7, 2014
    Posts:
    19
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    This post is very old. Many of these are built into NativeList now.
    Up to date extensions are also now always found in my core library:
    https://gitlab.com/tertle/com.bovin...eLabs.Core/Extensions/NativeListExtensions.cs
    https://gitlab.com/tertle/com.bovin...Labs.Core/Extensions/NativeArrayExtensions.cs
     
    makaolachsiungca likes this.