如何让C#函数接受多种类型的Unity NativeArray参数?
解决方案
针对你遇到的NativeArray重载函数代码重复问题,以下几种方法可以在不复制数组的前提下合并逻辑:
方法1:泛型函数结合MemoryMarshal.Cast实现无复制类型转换
利用ushort和short都是16位值类型、内存布局兼容的特性,通过MemoryMarshal.Cast在只读场景下安全转换视图,统一处理逻辑:
using System.Runtime.InteropServices; using Unity.Collections; public void Func<T>(NativeArray<T> a) where T : unmanaged { // 限制仅支持目标类型 if (typeof(T) != typeof(ushort) && typeof(T) != typeof(short)) throw new ArgumentException("仅支持ushort或short类型的NativeArray"); // 无复制转换为ushort的只读Span ReadOnlySpan<ushort> span = MemoryMarshal.Cast<T, ushort>(a.AsReadOnlySpan()); // -------------------------- // 这里写入原函数的核心逻辑,例如: foreach (ushort val in span) { // 处理逻辑 } // -------------------------- }
- 优势:无需复制数组,性能无损耗;通过泛型实现单一入口;
MemoryMarshal.Cast是安全的只读转换,不会修改原始数据。
方法2:提取核心逻辑到私有函数,保留轻量重载
如果不想用泛型,可以把重复逻辑抽到接受ReadOnlySpan<ushort>的私有函数,重载函数仅做无复制转换:
using System.Runtime.InteropServices; using Unity.Collections; public void Func(NativeArray<ushort> a) { InternalProcess(a.AsReadOnlySpan()); } public void Func(NativeArray<short> a) { // 无复制转换为ushort的Span InternalProcess(MemoryMarshal.Cast<short, ushort>(a.AsReadOnlySpan())); } private void InternalProcess(ReadOnlySpan<ushort> span) { // -------------------------- // 这里写入原函数的核心逻辑 // -------------------------- }
- 优势:避免泛型的类型检查,调用方仍保持原有的参数类型入口,无学习成本。
方法3:Unsafe代码直接操作内存指针(需开启unsafe支持)
如果项目允许unsafe代码,可以直接获取NativeArray的只读指针,转换为ushort*统一处理:
using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; public unsafe void Func<T>(NativeArray<T> a) where T : unmanaged { if (typeof(T) != typeof(ushort) && typeof(T) != typeof(short)) throw new ArgumentException("仅支持ushort或short类型的NativeArray"); ushort* ptr = (ushort*)NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr(a); int length = a.Length; // -------------------------- // 这里写入原函数的核心逻辑,例如: for (int i = 0; i < length; i++) { ushort val = ptr[i]; // 处理逻辑 } // -------------------------- }
- 注意:需要在Unity项目设置中开启"Allow unsafe code"选项;确保NativeArray未被释放且处于有效状态。
所有方法均不会复制数组内容,仅通过内存视图转换实现逻辑复用,性能与原重载函数一致。
内容的提问来源于stack exchange,提问作者sdugan
相关产品推荐
相关产品推荐

