(Russian translation from English by Maxim Voloshin)

Мое введение в Job System приводит большой список функций Unity, доступных для C# задач, но этот список неполный. Сегодня я хочу дополнить его недавно добавленными в 2018.2 функциями, а также некоторыми мощными функциями версии 2018.1, которые мы пропустили в прошлой статье. Многие из них не описаны в замечаниях к релизу Unity. Читайте, чтобы узнать больше о том, что вы можете сделать с системой задач C#!

Потокобезопасные функции

Как упоминается в введении в Job System, многие функции Unity помечены или атрибутом [ThreadSafe] или [FreeFunction] и IsThreadSafe возвращает true. Ниже приведен обновленный список таких функций. Строки, помеченные символом * в самом начале, были добавлены в Unity 2018.2:

*AnimationCurve:    private extern int AddKey_Internal_Injected(ref Keyframe key);
*AnimationCurve:    private extern Keyframe[] GetKeys();
*AnimationCurve:    private extern void SetKeys(Keyframe[] keys);
*AnimationCurve:    private int AddKey_Internal(Keyframe key)
*AnimationCurve:    private Keyframe GetKey(int index)
*AnimationCurve:    private static extern IntPtr Internal_Create(Keyframe[] keys);
*AnimationCurve:    private static extern void Internal_Destroy(IntPtr ptr);
*AnimationCurve:    public extern float Evaluate(float time);
*AnimationCurve:    public extern int AddKey(float time, float value);
*AnimationCurve:    public extern void RemoveKey(int index);
*AnimationCurve:    public extern void SmoothTangents(int index, float weight);
*AnimationCurve:    public int MoveKey(int index, Keyframe key)
*AnimationCurve:    public extern int length { get; }
*AnimationCurve:    public extern WrapMode postWrapMode { set; }
*AnimationCurve:    public extern WrapMode preWrapMode { set; }
*AnimationHumanStream:    private float GetFootHeight(bool left)
*AnimationHumanStream:    private float GetHumanScale()
*AnimationHumanStream:    private float InternalGetGoalWeightPosition(AvatarIKGoal index)
*AnimationHumanStream:    private float InternalGetGoalWeightRotation(AvatarIKGoal index)
*AnimationHumanStream:    private float InternalGetHintWeightPosition(AvatarIKHint index)
*AnimationHumanStream:    private float InternalGetMuscle(MuscleHandle muscle)
*AnimationHumanStream:    private Quaternion InternalGetBodyLocalRotation()
*AnimationHumanStream:    private Quaternion InternalGetBodyRotation()
*AnimationHumanStream:    private Quaternion InternalGetGoalLocalRotation(AvatarIKGoal index)
*AnimationHumanStream:    private Quaternion InternalGetGoalRotation(AvatarIKGoal index)
*AnimationHumanStream:    private Quaternion InternalGetGoalRotationFromPose(AvatarIKGoal index)
*AnimationHumanStream:    private Vector3 GetLeftFootVelocity()
*AnimationHumanStream:    private Vector3 GetRightFootVelocity()
*AnimationHumanStream:    private Vector3 InternalGetBodyLocalPosition()
*AnimationHumanStream:    private Vector3 InternalGetBodyPosition()
*AnimationHumanStream:    private Vector3 InternalGetGoalLocalPosition(AvatarIKGoal index)
*AnimationHumanStream:    private Vector3 InternalGetGoalPosition(AvatarIKGoal index)
*AnimationHumanStream:    private Vector3 InternalGetGoalPositionFromPose(AvatarIKGoal index)
*AnimationHumanStream:    private Vector3 InternalGetHintPosition(AvatarIKHint index)
*AnimationHumanStream:    private void InternalResetToStancePose()
*AnimationHumanStream:    private void InternalSetBodyLocalPosition(Vector3 value)
*AnimationHumanStream:    private void InternalSetBodyLocalRotation(Quaternion value)
*AnimationHumanStream:    private void InternalSetBodyPosition(Vector3 value)
*AnimationHumanStream:    private void InternalSetBodyRotation(Quaternion value)
*AnimationHumanStream:    private void InternalSetGoalLocalPosition(AvatarIKGoal index, Vector3 pos)
*AnimationHumanStream:    private void InternalSetGoalLocalRotation(AvatarIKGoal index, Quaternion rot)
*AnimationHumanStream:    private void InternalSetGoalPosition(AvatarIKGoal index, Vector3 pos)
*AnimationHumanStream:    private void InternalSetGoalRotation(AvatarIKGoal index, Quaternion rot)
*AnimationHumanStream:    private void InternalSetGoalWeightPosition(AvatarIKGoal index, float value)
*AnimationHumanStream:    private void InternalSetGoalWeightRotation(AvatarIKGoal index, float value)
*AnimationHumanStream:    private void InternalSetHintPosition(AvatarIKHint index, Vector3 pos)
*AnimationHumanStream:    private void InternalSetHintWeightPosition(AvatarIKHint index, float value)
*AnimationHumanStream:    private void InternalSetLookAtBodyWeight(float weight)
*AnimationHumanStream:    private void InternalSetLookAtClampWeight(float weight)
*AnimationHumanStream:    private void InternalSetLookAtEyesWeight(float weight)
*AnimationHumanStream:    private void InternalSetLookAtHeadWeight(float weight)
*AnimationHumanStream:    private void InternalSetLookAtPosition(Vector3 lookAtPosition)
*AnimationHumanStream:    private void InternalSetMuscle(MuscleHandle muscle, float value)
*AnimationHumanStream:    private void InternalSolveIK()
*AnimationStream:    private AnimationHumanStream GetHumanStream()
*AnimationStream:    private AnimationStream InternalGetInputStream(int index)
*AnimationStream:    private bool GetIsHumanStream()
*AnimationStream:    private float GetDeltaTime()
*AnimationStream:    private int GetInputStreamCount()
*AnimationStream:    private Quaternion GetRootMotionRotation()
*AnimationStream:    private Vector3 GetAngularVelocity()
*AnimationStream:    private Vector3 GetRootMotionPosition()
*AnimationStream:    private Vector3 GetVelocity()
*AnimationStream:    private void InternalReadSceneTransforms()
*AnimationStream:    private void InternalWriteSceneTransforms()
*AnimationStream:    private void SetAngularVelocity(Vector3 velocity)
*AnimationStream:    private void SetVelocity(Vector3 velocity)
Animator:    public static extern int StringToHash(string name);
AnimatorControllerPlayable:    private static extern int StringToHash(string name);
*Application:    public static extern RuntimePlatform platform { get; }
*AsyncOperation:    private static extern void InternalDestroy(IntPtr ptr);
*AtomicSafetyHandle:    internal static void CheckReadAndThrowNoEarlyOut(AtomicSafetyHandle handle)
*AtomicSafetyHandle:    internal static void CheckWriteAndThrowNoEarlyOut(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static AtomicSafetyHandle Create()
AtomicSafetyHandle:    public static AtomicSafetyHandle GetTempUnsafePtrSliceHandle()
*AtomicSafetyHandle:    public static bool GetAllowReadOrWriteAccess(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static EnforceJobResult EnforceAllBufferJobsHaveCompleted(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static EnforceJobResult EnforceAllBufferJobsHaveCompletedAndDisableReadWrite(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static EnforceJobResult EnforceAllBufferJobsHaveCompletedAndRelease(AtomicSafetyHandle handle)
*AtomicSafetyHandle:    public static extern void PrepareUndisposable(ref AtomicSafetyHandle handle);
AtomicSafetyHandle:    public static extern void UseSecondaryVersion(ref AtomicSafetyHandle handle);
AtomicSafetyHandle:    public static int GetReaderArray(AtomicSafetyHandle handle, int maxCount, IntPtr output)
*AtomicSafetyHandle:    public static JobHandle GetWriter(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static string GetReaderName(AtomicSafetyHandle handle, int readerIndex)
AtomicSafetyHandle:    public static string GetWriterName(AtomicSafetyHandle handle)
*AtomicSafetyHandle:    public static void CheckDeallocateAndThrow(AtomicSafetyHandle handle)
*AtomicSafetyHandle:    public static void CheckGetSecondaryDataPointerAndThrow(AtomicSafetyHandle handle)
*AtomicSafetyHandle:    public static void CheckWriteAndBumpSecondaryVersion(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static void Release(AtomicSafetyHandle handle)
AtomicSafetyHandle:    public static void SetAllowReadOrWriteAccess(AtomicSafetyHandle handle, bool allowReadWriteAccess)
AtomicSafetyHandle:    public static void SetAllowSecondaryVersionWriting(AtomicSafetyHandle handle, bool allowWriting)
AudioSampleProvider:    private static extern bool InternalGetEnableSampleFramesAvailableEvents(uint providerId);
AudioSampleProvider:    private static extern bool InternalGetEnableSilencePadding(uint id);
AudioSampleProvider:    private static extern bool InternalIsValid(uint providerId);
*AudioSampleProvider:    private static extern IntPtr InternalGetConsumeSampleFramesNativeFunctionPtr();
AudioSampleProvider:    private static extern uint InternalGetAvailableSampleFrameCount(uint providerId);
AudioSampleProvider:    private static extern uint InternalGetFreeSampleFrameCount(uint providerId);
AudioSampleProvider:    private static extern uint InternalGetFreeSampleFrameCountLowThreshold(uint providerId);
AudioSampleProvider:    private static extern uint InternalGetMaxSampleFrameCount(uint providerId);
AudioSampleProvider:    private static extern void InternalSetEnableSampleFramesAvailableEvents(uint providerId, bool enable);
AudioSampleProvider:    private static extern void InternalSetEnableSilencePadding(uint id, bool enabled);
AudioSampleProvider:    private static extern void InternalSetFreeSampleFrameCountLowThreshold(uint providerId, uint sampleFrameCount);
AudioSampleProvider:    private static extern void InternalSetScriptingPtr(uint providerId, AudioSampleProvider provider);
Bounds:    private static bool IntersectRayAABB(Ray ray, Bounds bounds, out float dist)
Bounds:    public bool Contains(Vector3 point)
Bounds:    public float SqrDistance(Vector3 point)
*Bounds:    public Vector3 ClosestPoint(Vector3 point)
CertificateHandler:    private extern void Release();
*CullingGroup:    private extern void FinalizerFailure();
CustomEventData:    internal static extern void Internal_Destroy(IntPtr ptr);
*Device:    private static extern void SettvOSNoBackupFlag(string path);
*Device:    private static extern void tvOSResetNoBackupFlag(string path);
Device:    public static extern bool RequestStoreReview();
Device:    public static extern void ResetNoBackupFlag(string path);
Device:    public static extern void SetNoBackupFlag(string path);
*DictationRecognizer:    private static extern void DestroyThreaded(IntPtr self);
DownloadHandler:    private extern void Release();
*Event:    internal extern void CopyFromPtr(IntPtr ptr);
*Event:    private static extern IntPtr Internal_Copy(IntPtr otherPtr);
*Event:    private static extern IntPtr Internal_Create(int displayIndex);
*Event:    private static extern void Internal_Destroy(IntPtr ptr);
GcLeaderboard:    private static extern void GcLeaderboard_Dispose(IntPtr leaderboard);
*Gradient:    private extern void Cleanup();
*Gradient:    private static extern IntPtr Init();
*Gradient:    public Color Evaluate(float time)
*Gradient:    public extern GradientMode mode { get; set; }
*Gradient:    public extern void SetKeys(GradientColorKey[] colorKeys, GradientAlphaKey[] alphaKeys);
*Gradient:    public extern GradientAlphaKey[] alphaKeys { get; set; }
*Gradient:    public extern GradientColorKey[] colorKeys { get; set; }
*GUIStyle:    private extern IntPtr GetStyleStatePtr(int idx);
*GUIStyle:    private static extern IntPtr Internal_Copy(GUIStyle self, GUIStyle other);
*GUIStyle:    private static extern IntPtr Internal_Create(GUIStyle self);
*GUIStyle:    private static extern void Internal_Destroy(IntPtr self);
*GUIStyleState:    private extern void Cleanup();
*GUIStyleState:    private static extern IntPtr Init();
JobsUtility:    public static extern bool GetWorkStealingRange(ref JobRanges ranges, int jobIndex, out int beginIndex, out int endIndex);
JobsUtility:    public static extern unsafe void PatchBufferMinMaxRanges(IntPtr bufferRangePatchData, void* jobdata, int startIndex, int rangeSize);
*JsonUtility:    private static extern object FromJsonInternal(string json, object objectToOverwrite, System.Type type);
*JsonUtility:    private static extern string ToJsonInternal(object obj, bool prettyPrint);
MaterialPropertyBlock:    private static extern void DestroyImpl(IntPtr mpb);
Mathf:    public static Color CorrelatedColorTemperatureToRGB(float kelvin)
Mathf:    public static extern bool IsPowerOfTwo(int value);
Mathf:    public static extern float GammaToLinearSpace(float value);
Mathf:    public static extern float HalfToFloat(ushort val);
Mathf:    public static extern float LinearToGammaSpace(float value);
Mathf:    public static extern float PerlinNoise(float x, float y);
Mathf:    public static extern int ClosestPowerOfTwo(int value);
Mathf:    public static extern int NextPowerOfTwo(int value);
Mathf:    public static extern ushort FloatToHalf(float val);
*Matrix4x4:    private bool IsIdentity()
*Matrix4x4:    private float GetDeterminant()
Matrix4x4:    private FrustumPlanes DecomposeProjection()
Matrix4x4:    private Quaternion GetRotation()
Matrix4x4:    private Vector3 GetLossyScale()
Matrix4x4:    public bool ValidTRS()
Matrix4x4:    public static Matrix4x4 Frustum(float left, float right, float bottom, float top, float zNear, float zFar)
Matrix4x4:    public static Matrix4x4 Inverse(Matrix4x4 m)
Matrix4x4:    public static Matrix4x4 LookAt(Vector3 from, Vector3 to, Vector3 up)
Matrix4x4:    public static Matrix4x4 Ortho(float left, float right, float bottom, float top, float zNear, float zFar)
Matrix4x4:    public static Matrix4x4 Perspective(float fov, float aspect, float zNear, float zFar)
Matrix4x4:    public static Matrix4x4 Transpose(Matrix4x4 m)
*Matrix4x4:    public static Matrix4x4 TRS(Vector3 pos, Quaternion q, Vector3 s)
MeshReconstructionServer:    internal static extern void DestroyThreaded(IntPtr server);
MonoBehaviour:    private static extern void ConstructorCheck(Object self);
*Native:    private static extern void YGConfigFreeInternal(IntPtr config);
*Native:    private static extern void YGNodeFreeInternal(IntPtr ygNode);
NavMeshQuery:    private static bool GetPortalPoints(IntPtr navMeshQuery, PolygonId polygon, PolygonId neighbourPolygon, out Vector3 left, out Vector3 right)
NavMeshQuery:    private static bool IsPositionInPolygon(IntPtr navMeshQuery, Vector3 position, PolygonId polygon)
NavMeshQuery:    private static bool IsValidPolygon(IntPtr navMeshQuery, PolygonId polygon)
*NavMeshQuery:    private static extern bool HasNodePool(IntPtr navMeshQuery);
NavMeshQuery:    private static extern PathQueryStatus EndFindPath(IntPtr navMeshQuery, out int pathSize);
NavMeshQuery:    private static extern PathQueryStatus UpdateFindPath(IntPtr navMeshQuery, int iterations, out int iterationsPerformed);
NavMeshQuery:    private static extern unsafe int GetPathResult(IntPtr navMeshQuery, void* path, int maxPath);
NavMeshQuery:    private static extern unsafe void MoveLocations(IntPtr navMeshQuery, void* locations, void* targets, void* areaMasks, int count);
NavMeshQuery:    private static extern unsafe void MoveLocationsInSameAreas(IntPtr navMeshQuery, void* locations, void* targets, int count, int areaMask);
*NavMeshQuery:    private static int GetAgentTypeIdForPolygon(IntPtr navMeshQuery, PolygonId polygon)
*NavMeshQuery:    private static Matrix4x4 PolygonLocalToWorldMatrix(IntPtr navMeshQuery, PolygonId polygon)
*NavMeshQuery:    private static Matrix4x4 PolygonWorldToLocalMatrix(IntPtr navMeshQuery, PolygonId polygon)
*NavMeshQuery:    private static NavMeshLocation MapLocation(IntPtr navMeshQuery, Vector3 position, Vector3 extents, int agentTypeID, int areaMask = -1)
*NavMeshQuery:    private static NavMeshLocation MoveLocation(IntPtr navMeshQuery, NavMeshLocation location, Vector3 target, int areaMask)
*NavMeshQuery:    private static NavMeshPolyTypes GetPolygonType(IntPtr navMeshQuery, PolygonId polygon)
*NavMeshQuery:    private static PathQueryStatus GetClosestPointOnPoly(IntPtr navMeshQuery, PolygonId polygon, Vector3 position, out Vector3 nearest)
*NavMeshQuery:    private static unsafe PathQueryStatus BeginFindPath(IntPtr navMeshQuery, NavMeshLocation start, NavMeshLocation end, int areaMask, void* costs)
NotificationHelper:    internal static extern void DestroyLocal(IntPtr target);
NotificationHelper:    internal static extern void DestroyRemote(IntPtr target);
Object:    internal static extern bool DoesObjectWithInstanceIDExist(int instanceID);
Object:    private static extern bool CurrentThreadIsMainThread();
Object:    private static extern int GetOffsetOfInstanceIDInCPlusPlusObject();
ObjectGUIState:    private static extern void Internal_Destroy(IntPtr ptr);
OnDemandResourcesRequest:    private static extern void DestroyFromScript(IntPtr ptr);
*PhraseRecognizer:    private static extern void DestroyThreaded(IntPtr recognizer);
Ping:    private static extern void Internal_Destroy(IntPtr ptr);
*PropertySceneHandle:    private bool GetBoolInternal(ref AnimationStream stream)
*PropertySceneHandle:    private bool HasValidTransform(ref AnimationStream stream)
*PropertySceneHandle:    private bool IsBound(ref AnimationStream stream)
*PropertySceneHandle:    private float GetFloatInternal(ref AnimationStream stream)
*PropertySceneHandle:    private int GetIntInternal(ref AnimationStream stream)
*PropertySceneHandle:    private void ResolveInternal(ref AnimationStream stream)
*PropertySceneHandle:    private void SetBoolInternal(ref AnimationStream stream, bool value)
*PropertySceneHandle:    private void SetFloatInternal(ref AnimationStream stream, float value)
*PropertySceneHandle:    private void SetIntInternal(ref AnimationStream stream, int value)
*PropertyStreamHandle:    private bool GetBoolInternal(ref AnimationStream stream)
*PropertyStreamHandle:    private float GetFloatInternal(ref AnimationStream stream)
*PropertyStreamHandle:    private int GetIntInternal(ref AnimationStream stream)
*PropertyStreamHandle:    private void ResolveInternal(ref AnimationStream stream)
*PropertyStreamHandle:    private void SetBoolInternal(ref AnimationStream stream, bool value)
*PropertyStreamHandle:    private void SetFloatInternal(ref AnimationStream stream, float value)
*PropertyStreamHandle:    private void SetIntInternal(ref AnimationStream stream, int value)
Quaternion:    private static Quaternion Internal_FromEulerRad(Vector3 euler)
Quaternion:    private static Vector3 Internal_ToEulerRad(Quaternion rotation)
Quaternion:    private static void Internal_ToAxisAngleRad(Quaternion q, out Vector3 axis, out float angle)
Quaternion:    public static Quaternion AngleAxis(float angle, Vector3 axis)
Quaternion:    public static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection)
Quaternion:    public static Quaternion Inverse(Quaternion rotation)
Quaternion:    public static Quaternion Lerp(Quaternion a, Quaternion b, float t)
Quaternion:    public static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t)
Quaternion:    public static Quaternion LookRotation(Vector3 forward, Vector3 upwards)
Quaternion:    public static Quaternion Slerp(Quaternion a, Quaternion b, float t)
Quaternion:    public static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t)
RemoteConfigSettings:    internal static extern void Internal_Destroy(IntPtr ptr);
*Screen:    public static extern float dpi { get; }
Screen:    public static extern int height { get; }
Screen:    public static extern int width { get; }
ScriptableObject:    private static extern void CreateScriptableObject(ScriptableObject self);
*Shader:    public static extern int PropertyToID(string name);
*StylePainter:    private static extern IntPtr Internal_Create();
*StylePainter:    private static extern void Internal_Destroy(IntPtr self);
*TerrainData:    private static extern int GetBoundaryValue(TerrainData.BoundaryValueType type);
*TextGenerator:    private static extern IntPtr Internal_Create();
*TextGenerator:    private static extern void Internal_Destroy(IntPtr ptr);
*TouchScreenKeyboard:    private static extern void Internal_Destroy(IntPtr ptr);
TransformAccess:    private static extern void GetLocalPosition(ref TransformAccess access, out Vector3 p);
TransformAccess:    private static extern void GetLocalRotation(ref TransformAccess access, out Quaternion r);
TransformAccess:    private static extern void GetLocalScale(ref TransformAccess access, out Vector3 r);
TransformAccess:    private static extern void GetPosition(ref TransformAccess access, out Vector3 p);
TransformAccess:    private static extern void GetRotation(ref TransformAccess access, out Quaternion r);
TransformAccess:    private static extern void SetLocalPosition(ref TransformAccess access, ref Vector3 p);
TransformAccess:    private static extern void SetLocalRotation(ref TransformAccess access, ref Quaternion r);
TransformAccess:    private static extern void SetLocalScale(ref TransformAccess access, ref Vector3 r);
TransformAccess:    private static extern void SetPosition(ref TransformAccess access, ref Vector3 p);
TransformAccess:    private static extern void SetRotation(ref TransformAccess access, ref Quaternion r);
TransformAccessArray:    internal static extern IntPtr GetSortedToUserIndex(IntPtr transformArrayIntPtr);
TransformAccessArray:    internal static extern IntPtr GetSortedTransformAccess(IntPtr transformArrayIntPtr);
*TransformSceneHandle:    private bool HasValidTransform(ref AnimationStream stream)
*TransformSceneHandle:    private Quaternion GetLocalRotationInternal(ref AnimationStream stream)
*TransformSceneHandle:    private Quaternion GetRotationInternal(ref AnimationStream stream)
*TransformSceneHandle:    private Vector3 GetLocalPositionInternal(ref AnimationStream stream)
*TransformSceneHandle:    private Vector3 GetLocalScaleInternal(ref AnimationStream stream)
*TransformSceneHandle:    private Vector3 GetPositionInternal(ref AnimationStream stream)
*TransformSceneHandle:    private void SetLocalPositionInternal(ref AnimationStream stream, Vector3 position)
*TransformSceneHandle:    private void SetLocalRotationInternal(ref AnimationStream stream, Quaternion rotation)
*TransformSceneHandle:    private void SetLocalScaleInternal(ref AnimationStream stream, Vector3 scale)
*TransformSceneHandle:    private void SetPositionInternal(ref AnimationStream stream, Vector3 position)
*TransformSceneHandle:    private void SetRotationInternal(ref AnimationStream stream, Quaternion rotation)
*TransformStreamHandle:    private Quaternion GetLocalRotationInternal(ref AnimationStream stream)
*TransformStreamHandle:    private Quaternion GetRotationInternal(ref AnimationStream stream)
*TransformStreamHandle:    private Vector3 GetLocalPositionInternal(ref AnimationStream stream)
*TransformStreamHandle:    private Vector3 GetLocalScaleInternal(ref AnimationStream stream)
*TransformStreamHandle:    private Vector3 GetPositionInternal(ref AnimationStream stream)
*TransformStreamHandle:    private void ResolveInternal(ref AnimationStream stream)
*TransformStreamHandle:    private void SetLocalPositionInternal(ref AnimationStream stream, Vector3 position)
*TransformStreamHandle:    private void SetLocalRotationInternal(ref AnimationStream stream, Quaternion rotation)
*TransformStreamHandle:    private void SetLocalScaleInternal(ref AnimationStream stream, Vector3 scale)
*TransformStreamHandle:    private void SetPositionInternal(ref AnimationStream stream, Vector3 position)
*TransformStreamHandle:    private void SetRotationInternal(ref AnimationStream stream, Quaternion rotation)
UnityAnalytHandler:    internal static extern void Internal_Destroy(IntPtr ptr);
UnityLogWriter:    private static extern void WriteStringToUnityLogImpl(string s);
UnityWebRequest:    private extern void Release();
UnityWebRequest:    private static extern string GetWebErrorString(UnityWebRequest.UnityWebRequestError err);
UnityWebRequest:    public extern void Abort();
UnsafeUtility:    internal static extern void LogError(string msg, string filename, int linenumber);
UnsafeUtility:    private static extern int GetFieldOffsetInClass(FieldInfo field);
UnsafeUtility:    private static extern int GetFieldOffsetInStruct(FieldInfo field);
UnsafeUtility:    public static extern bool IsBlittable(Type type);
UnsafeUtility:    public static extern int SizeOf(Type type);
*UnsafeUtility:    public static extern unsafe int MemCmp(void* ptr1, void* ptr2, long size);
UnsafeUtility:    public static extern unsafe void CopyObjectAddressToPtr(object target, void* dstPtr);
UnsafeUtility:    public static extern unsafe void Free(void* memory, Allocator allocator);
UnsafeUtility:    public static extern unsafe void MemClear(void* destination, long size);
UnsafeUtility:    public static extern unsafe void MemCpy(void* destination, void* source, long size);
UnsafeUtility:    public static extern unsafe void MemCpyReplicate(void* destination, void* source, int size, int count);
UnsafeUtility:    public static extern unsafe void MemCpyStride(void* destination, int destinationStride, void* source, int sourceStride, int elementSize, int count);
UnsafeUtility:    public static extern unsafe void MemMove(void* destination, void* source, long size);
UnsafeUtility:    public static extern unsafe void* Malloc(long size, int alignment, Allocator allocator);
UnsafeUtility:    public static extern unsafe void* PinGCObjectAndGetAddress(object target, out ulong gcHandle);
UnsafeUtility:    public static extern void ReleaseGCObject(ulong gcHandle);
UploadHandler:    private extern void Release();
Vector3:    private static extern void OrthoNormalize2(ref Vector3 a, ref Vector3 b);
Vector3:    private static extern void OrthoNormalize3(ref Vector3 a, ref Vector3 b, ref Vector3 c);
Vector3:    public static Vector3 RotateTowards(Vector3 current, Vector3 target, float maxRadiansDelta, float maxMagnitudeDelta)
Vector3:    public static Vector3 Slerp(Vector3 a, Vector3 b, float t)
Vector3:    public static Vector3 SlerpUnclamped(Vector3 a, Vector3 b, float t)

Множество разнообразных функций теперь доступно из системы задач в 2018.2. Полезность многих из них ограничена, либо в силу своей природы, либо в силу того факта, что они принимают ссылочные типы, такие как классы или массивы, которые запрещено использовать в задачах. Хотя некоторые из них довольно удобны. Вот некоторые основные моменты:

  • Bounds.ClosestPoint: полезна для реализации логики 3D геометрии Ñ‚.к. Physics не доступен
  • JsonUtility.FromJsonInternal и ToJsonInternal: JSON сериализация и десериализация теперь может работать вне главного потока
  • Matrix4x4.IsIdentity и GetDeterminant: полезные функции для работы с матрицами
  • UnsafeUtility.MemCmp: Эффективное сравнение двух блоков памяти
Анимации в C# системе задач

Большинство функций выше были добавлены для поддержки фичи Animation C# Jobs, которая позволяет задачам манипулировать анимациями и трансформациями. Это справедливо для AnimationHumanStream, AnimationStream, PropertySceneHandle, и спорно для TransformSceneHandle и TransformStreamHandle. Это более глубокая тема, выходящая за рамки данной статьи, посмотрите примеры Unity для того чтобы узнать как это можно использовать и почерпнуть пару идей что с этим можно сделать.

NavMeshQuery

Другая большая часть вышеприведенных функций – это подкапотные изменения “экспериментальной” структуры NavMeshQuery. Совместно со связанными с ней структурами NavMeshWorld, PolygonId, и NavMeshLocation, она позволяет опрашивать nav mesh и выполнять поиск пути из системы задач. Эти операции могут очень интенсивно использовать CPU и было бы прекрасно перенести их из главного потока в задачи. Такая возможность была “экспериментальной” в 2018.1 и продолжает быть таковой в 2018.2. Дорожная карта Unity на данный момент молчит о том, когда ждать стабильный релиз этого функционала.

RaycastCommand

Отсутствует в списке выше и не упомянута в замечаниях к релизу 2018.1 RaycastCommand. Не смотря на то, что она была добавлена в 2018.1 и позволяла нам создавать задачи, бросающие набор лучей и выводить результат в NativeArray. Пока Physics, в общем случае, не доступен вне главного потока, включая систему задач, как минимум бросание лучей поддерживается, как одна из наиболее распространенных операций с физикой, широко используемая всем, от выстрелов до логики передвижения. В конце концов, Unity хотят добавить больше команд для работы с физикой, а также поддержку 2D физики.

Заключение

Все больше и больше функционала становится доступно для системы задач C# с каждым релизом Unity. Поддержка бросания лучей в 2018.1, анимации и JSON в 2018.2 позволяет нам перенести самые трудоемкие части из главного потока, что было невозможно в предыдущих версиях Unity. Стабильная поддержка nav mesh и дополнительные функции для работы с физикой уже на горизонте, как и ECS. Как только они будут выпущены, еще больше кода может быть конвертировано из старого API в новый, ориентированный на задачи подход. Делая это, мы получаем огромное повышение производительности и снижение энергопотребления. Дайте мне знать в комментариях что Вы думаете о такой смене парадигм.