Job-Safe APIs in Unity 2018.3
Unity 2018.3 brings us even more thread-safe APIs that we can call from the C# job system. Today we’ll look at a systematic way to find them all so we know what’s safe to use and what’s not.
Update: A Russian translation of this article is available.
Previous articles (2018.1, 2018.2) have featured lists of job-safe APIs, but those lists were generated with a combination of decompiling all of Unity’s DLLs, using grep
to find [ThreadSafe]
and IsThreadSafe = true
, then manually formatting the results for the article. It’s a lengthy, tedious, and error-prone process that can be improved.
So for today, we now have a little Unity editor script that will generate the list for us. Here’s what it does:
- Find all the
.dll
files in the Unity install directory’sManaged
sub-directory - Open them as an
Assembly
- Scan through all their methods and properties
- Check if the
[NativeMethod]
attribute is present - Call the
get
forNativeMethodAttribute.IsThreadSafe
- Output all the matches to
Debug.Log
and the system clipboard
The following script runs on macOS only right now, but can be easily modified to support Windows or Linux if necessary by changing managedDirPath
:
using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using UnityEngine; using UnityEditor; public static class JobSafeMenuItem { [MenuItem("Help/List Job Safe APIs")] private static void JobSafe() { #if !UNITY_EDITOR_OSX throw new Exception("Only macOS is supported at this time"); #endif string managedDirPath = Path.Combine( Path.Combine( EditorApplication.applicationPath, "Contents"), "Managed"); Type nativeMethodAttribute = Assembly.LoadFile( Path.Combine( Path.Combine( managedDirPath, "UnityEngine"), "UnityEngine.SharedInternalsModule.dll")) .GetType("UnityEngine.Bindings.NativeMethodAttribute"); string[] paths = Directory.GetFiles( managedDirPath, "*.dll", SearchOption.AllDirectories); var methodsByType = new Dictionary<Type, List<string>>(512); object[] emptyParameters = { }; void AddIfThreadSafe(Type type, Attribute attribute, string method) { if (nativeMethodAttribute.IsInstanceOfType(attribute) && (bool)nativeMethodAttribute .GetProperty("IsThreadSafe") .GetGetMethod() .Invoke(attribute, emptyParameters)) { List<string> list; if (!methodsByType.TryGetValue(type, out list)) { list = new List<string>(32); methodsByType[type] = list; } list.Add(method); } } BindingFlags allFlags = BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; foreach (var path in paths) { Assembly assembly = Assembly.LoadFile(path); foreach (Type type in assembly.GetTypes()) { foreach (MethodInfo meth in type.GetMethods(allFlags)) { foreach (Attribute attribute in meth.GetCustomAttributes()) { AddIfThreadSafe(type, attribute, meth.ToString()); } } foreach (PropertyInfo prop in type.GetProperties(allFlags)) { foreach (Attribute attribute in prop.GetCustomAttributes()) { AddIfThreadSafe(type, attribute, prop.ToString()); } } } } StringBuilder builder = new StringBuilder(1024 * 10); var sortedMethodsByType = new List<KeyValuePair<Type, List<string>>>( methodsByType); sortedMethodsByType.Sort((a, b) => a.Key.Name.CompareTo(b.Key.Name)); foreach (var pair in sortedMethodsByType) { pair.Value.Sort(); foreach (string method in pair.Value) { builder.Append(pair.Key.Name); builder.Append(": "); builder.AppendLine(method); } } Debug.Log(builder.ToString()); EditorGUIUtility.systemCopyBuffer = builder.ToString(); } }
To use it, just paste into a .cs
file in an Editor
folder in a Unity project. Then click Help > List Job Safe APIs
to run the script. It takes a few seconds and then shows a log in the Console
pane. The log is quite long and likely to be truncated, but it’s also been copied to the system clipboard. Paste it into a text editor to see the full results.
I ran this in Unity 2018.1.3f2 and got the following:
ActiveEditorTracker: Void Internal_Create(UnityEditor.ActiveEditorTracker) ActiveEditorTracker: Void Internal_Dispose(UnityEditor.ActiveEditorTracker) Analytics: Boolean IsInitialized() Analytics: Boolean QueueEvent(System.String, System.Object, Int32, System.String) Analytics: UnityEngine.Analytics.AnalyticsResult SendEventWithLimit(System.String, System.Object, Int32, System.String) AnimationCurve: Int32 AddKey_Internal(UnityEngine.Keyframe) AnimationCurve: IntPtr Internal_Create(UnityEngine.Keyframe[]) AnimationCurve: UnityEngine.Keyframe GetKey(Int32) AnimationCurve: UnityEngine.Keyframe[] GetKeys() AnimationCurve: Void Internal_Destroy(IntPtr) AnimationCurve: Void SetKeys(UnityEngine.Keyframe[]) AnimationHumanStream: Single GetFootHeight(Boolean) AnimationHumanStream: Single GetHumanScale() AnimationHumanStream: Single InternalGetGoalWeightPosition(UnityEngine.AvatarIKGoal) AnimationHumanStream: Single InternalGetGoalWeightRotation(UnityEngine.AvatarIKGoal) AnimationHumanStream: Single InternalGetHintWeightPosition(UnityEngine.AvatarIKHint) AnimationHumanStream: Single InternalGetMuscle(UnityEngine.Experimental.Animations.MuscleHandle) AnimationHumanStream: UnityEngine.Quaternion InternalGetBodyLocalRotation() AnimationHumanStream: UnityEngine.Quaternion InternalGetBodyRotation() AnimationHumanStream: UnityEngine.Quaternion InternalGetGoalLocalRotation(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Quaternion InternalGetGoalRotation(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Quaternion InternalGetGoalRotationFromPose(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Vector3 GetLeftFootVelocity() AnimationHumanStream: UnityEngine.Vector3 GetRightFootVelocity() AnimationHumanStream: UnityEngine.Vector3 InternalGetBodyLocalPosition() AnimationHumanStream: UnityEngine.Vector3 InternalGetBodyPosition() AnimationHumanStream: UnityEngine.Vector3 InternalGetGoalLocalPosition(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Vector3 InternalGetGoalPosition(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Vector3 InternalGetGoalPositionFromPose(UnityEngine.AvatarIKGoal) AnimationHumanStream: UnityEngine.Vector3 InternalGetHintPosition(UnityEngine.AvatarIKHint) AnimationHumanStream: Void InternalResetToStancePose() AnimationHumanStream: Void InternalSetBodyLocalPosition(UnityEngine.Vector3) AnimationHumanStream: Void InternalSetBodyLocalRotation(UnityEngine.Quaternion) AnimationHumanStream: Void InternalSetBodyPosition(UnityEngine.Vector3) AnimationHumanStream: Void InternalSetBodyRotation(UnityEngine.Quaternion) AnimationHumanStream: Void InternalSetGoalLocalPosition(UnityEngine.AvatarIKGoal, UnityEngine.Vector3) AnimationHumanStream: Void InternalSetGoalLocalRotation(UnityEngine.AvatarIKGoal, UnityEngine.Quaternion) AnimationHumanStream: Void InternalSetGoalPosition(UnityEngine.AvatarIKGoal, UnityEngine.Vector3) AnimationHumanStream: Void InternalSetGoalRotation(UnityEngine.AvatarIKGoal, UnityEngine.Quaternion) AnimationHumanStream: Void InternalSetGoalWeightPosition(UnityEngine.AvatarIKGoal, Single) AnimationHumanStream: Void InternalSetGoalWeightRotation(UnityEngine.AvatarIKGoal, Single) AnimationHumanStream: Void InternalSetHintPosition(UnityEngine.AvatarIKHint, UnityEngine.Vector3) AnimationHumanStream: Void InternalSetHintWeightPosition(UnityEngine.AvatarIKHint, Single) AnimationHumanStream: Void InternalSetLookAtBodyWeight(Single) AnimationHumanStream: Void InternalSetLookAtClampWeight(Single) AnimationHumanStream: Void InternalSetLookAtEyesWeight(Single) AnimationHumanStream: Void InternalSetLookAtHeadWeight(Single) AnimationHumanStream: Void InternalSetLookAtPosition(UnityEngine.Vector3) AnimationHumanStream: Void InternalSetMuscle(UnityEngine.Experimental.Animations.MuscleHandle, Single) AnimationHumanStream: Void InternalSolveIK() AnimationStream: Boolean GetIsHumanStream() AnimationStream: Int32 GetInputStreamCount() AnimationStream: Single GetDeltaTime() AnimationStream: UnityEngine.Experimental.Animations.AnimationHumanStream GetHumanStream() AnimationStream: UnityEngine.Experimental.Animations.AnimationStream InternalGetInputStream(Int32) AnimationStream: UnityEngine.Quaternion GetRootMotionRotation() AnimationStream: UnityEngine.Vector3 GetAngularVelocity() AnimationStream: UnityEngine.Vector3 GetRootMotionPosition() AnimationStream: UnityEngine.Vector3 GetVelocity() AnimationStream: Void InternalReadSceneTransforms() AnimationStream: Void InternalWriteSceneTransforms() AnimationStream: Void SetAngularVelocity(UnityEngine.Vector3) AnimationStream: Void SetVelocity(UnityEngine.Vector3) AnimatorControllerPlayable: Int32 StringToHash(System.String) Asset: IntPtr Create(System.String) Asset: States GetState(IntPtr) Asset: Void Destroy(IntPtr) AssetBundle: UnityEngine.Object returnMainAsset(UnityEngine.AssetBundle) AsyncOperation: Void InternalDestroy(IntPtr) AsyncReadManager: Unity.IO.LowLevel.Unsafe.ReadHandle ReadInternal(System.String, Void*, UInt32) AtomicSafetyHandle: Void CheckReadAndThrowNoEarlyOut(Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle) AtomicSafetyHandle: Void CheckWriteAndThrowNoEarlyOut(Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle) AudioSampleProvider: Boolean InternalGetEnableSampleFramesAvailableEvents(UInt32) AudioSampleProvider: Boolean InternalGetEnableSilencePadding(UInt32) AudioSampleProvider: Boolean InternalIsValid(UInt32) AudioSampleProvider: IntPtr InternalGetConsumeSampleFramesNativeFunctionPtr() AudioSampleProvider: UInt32 InternalGetAvailableSampleFrameCount(UInt32) AudioSampleProvider: UInt32 InternalGetFreeSampleFrameCount(UInt32) AudioSampleProvider: UInt32 InternalGetFreeSampleFrameCountLowThreshold(UInt32) AudioSampleProvider: UInt32 InternalGetMaxSampleFrameCount(UInt32) AudioSampleProvider: Void InternalSetEnableSampleFramesAvailableEvents(UInt32, Boolean) AudioSampleProvider: Void InternalSetEnableSilencePadding(UInt32, Boolean) AudioSampleProvider: Void InternalSetFreeSampleFrameCountLowThreshold(UInt32, UInt32) AudioSampleProvider: Void InternalSetScriptingPtr(UInt32, UnityEngine.Experimental.Audio.AudioSampleProvider) Bounds: Boolean IntersectRayAABB(UnityEngine.Ray, UnityEngine.Bounds, Single ByRef) BuildPipeline: Boolean LicenseCheck(UnityEditor.BuildTarget) BuildPipeline: System.String GetBuildTargetName(UnityEditor.BuildTarget) BuildPipeline: System.String GetBuildToolsDirectory(UnityEditor.BuildTarget) BuildPipeline: System.String GetEditorTargetName() BuildPipeline: System.String GetPlaybackEngineDirectory(UnityEditor.BuildTargetGroup, UnityEditor.BuildTarget, UnityEditor.BuildOptions) BuildPipeline: System.String GetPlaybackEngineExtensionDirectory(UnityEditor.BuildTargetGroup, UnityEditor.BuildTarget, UnityEditor.BuildOptions) BuildReferenceMap: IntPtr Internal_Create() BuildReferenceMap: Void Internal_Destroy(IntPtr) BuildUsageCache: IntPtr Internal_Create() BuildUsageCache: Void Internal_Destroy(IntPtr) BuildUsageTagSet: IntPtr Internal_Create() BuildUsageTagSet: Void Internal_Destroy(IntPtr) CertificateHandler: Void Release() ChangeSet: IntPtr Create() ChangeSet: IntPtr CreateFromCopy(UnityEditor.VersionControl.ChangeSet) ChangeSet: IntPtr CreateFromString(System.String) ChangeSet: IntPtr CreateFromStringString(System.String, System.String) ChangeSet: Void Destroy(IntPtr) Collab: UnityEditor.Collaboration.Change[] GetSelectedChangesInternal() Collab: Void SetChangesToPublishInternal(UnityEditor.Collaboration.ChangeItem[]) CommandBuffer: Void ReleaseBuffer() ComputeBuffer: Int32 GetLineNumber() ComputeBuffer: System.String GetFileName() ConfigField: Void Destroy(IntPtr) ConnectionConfigInternal: Void InternalDestroy(IntPtr) ConnectionSimulatorConfigInternal: Void InternalDestroy(IntPtr) Coroutine: Void ReleaseCoroutine(IntPtr) CrashReport: Boolean RemoveReport(System.String) CrashReport: System.String GetReportData(System.String, Double ByRef) CrashReport: System.String[] GetReports() CullingGroup: Void FinalizerFailure() CustomEventData: Void Internal_Destroy(IntPtr) CustomSampler: IntPtr CreateInternal(System.String) CustomSampler: Void BeginWithObject(UnityEngine.Object) Device: Void SettvOSNoBackupFlag(System.String) Device: Void tvOSResetNoBackupFlag(System.String) DictationRecognizer: Void DestroyThreaded(IntPtr) DownloadHandler: Void Release() Event: IntPtr Internal_Copy(IntPtr) Event: IntPtr Internal_Create(Int32) Event: Void CopyFromPtr(IntPtr) Event: Void Internal_Destroy(IntPtr) FontEngine: Boolean TryAddGlyphsToTexture_Internal(UInt32[], Int32, UnityEngine.TextCore.LowLevel.GlyphPackingMode, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.LowLevel.GlyphRenderMode, UnityEngine.Texture2D, UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct[], Int32 ByRef) FontEngine: Boolean TryAddGlyphToTexture_Internal(UInt32, Int32, UnityEngine.TextCore.LowLevel.GlyphPackingMode, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.LowLevel.GlyphRenderMode, UnityEngine.Texture2D, UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct ByRef) FontEngine: Boolean TryGetGlyphWithIndexValue_Internal(UInt32, UnityEngine.TextCore.LowLevel.GlyphLoadFlags, UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct ByRef) FontEngine: Boolean TryGetGlyphWithUnicodeValue_Internal(UInt32, UnityEngine.TextCore.LowLevel.GlyphLoadFlags, UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct ByRef) FontEngine: Boolean TryPackGlyphInAtlas_Internal(UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct ByRef, Int32, UnityEngine.TextCore.LowLevel.GlyphPackingMode, UnityEngine.TextCore.LowLevel.GlyphRenderMode, Int32, Int32, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.GlyphRect[], Int32 ByRef) FontEngine: Boolean TryPackGlyphsInAtlas_Internal(UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct[], Int32 ByRef, UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct[], Int32 ByRef, Int32, UnityEngine.TextCore.LowLevel.GlyphPackingMode, UnityEngine.TextCore.LowLevel.GlyphRenderMode, Int32, Int32, UnityEngine.TextCore.GlyphRect[], Int32 ByRef, UnityEngine.TextCore.GlyphRect[], Int32 ByRef) FontEngine: Int32 GetFaceInfo_Internal(UnityEngine.TextCore.FaceInfo ByRef) FontEngine: Int32 LoadGlyph_Internal(UInt32, UnityEngine.TextCore.LowLevel.GlyphLoadFlags) FontEngine: Int32 RenderGlyphsToSharedTexture_Internal(UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct[], Int32, Int32, UnityEngine.TextCore.LowLevel.GlyphRenderMode) FontEngine: Int32 RenderGlyphsToTextureBuffer_Internal(UnityEngine.TextCore.LowLevel.GlyphMarshallingStruct[], Int32, Int32, UnityEngine.TextCore.LowLevel.GlyphRenderMode, Byte[], Int32, Int32) FontEngine: Int32 SetFaceSize_Internal(Int32) FontEngine: UInt32 GetGlyphIndex(UInt32) FontEngine: Void ReleaseSharedTexture() FrameDataView: IntPtr Internal_Create(UnityEditorInternal.Profiling.ProfilerViewType, Int32, Int32, UnityEditorInternal.Profiling.ProfilerColumn, Boolean, UnityEditorInternal.Profiling.FrameViewFilteringModes) FrameDataView: Void Internal_Destroy(IntPtr) GcLeaderboard: Void GcLeaderboard_Dispose(IntPtr) GlobalConfigInternal: Void InternalDestroy(IntPtr) Gradient: Boolean Internal_Equals(IntPtr) Gradient: IntPtr Init() Gradient: Void Cleanup() GUIStyle: IntPtr GetStyleStatePtr(Int32) GUIStyle: IntPtr Internal_Copy(UnityEngine.GUIStyle, UnityEngine.GUIStyle) GUIStyle: IntPtr Internal_Create(UnityEngine.GUIStyle) GUIStyle: Void Internal_Destroy(IntPtr) GUIStyleState: IntPtr Init() GUIStyleState: Void Cleanup() HostTopologyInternal: Void InternalDestroy(IntPtr) InternalEditorUtility: Boolean HasUFSTLicense() JsonUtility: System.Object FromJsonInternal(System.String, System.Object, System.Type) JsonUtility: System.Object FromJsonInternal(System.String, System.Object, System.Type) JsonUtility: System.String ToJsonInternal(System.Object, Boolean) JsonUtility: System.String ToJsonInternal(System.Object, Boolean) LineUtility: Void GeneratePointsToKeep2D(System.Object, Single, System.Object) LineUtility: Void GeneratePointsToKeep3D(System.Object, Single, System.Object) LineUtility: Void GenerateSimplifiedPoints2D(System.Object, Single, System.Object) LineUtility: Void GenerateSimplifiedPoints3D(System.Object, Single, System.Object) MaterialPropertyBlock: Void DestroyImpl(IntPtr) Matrix4x4: Boolean IsIdentity() Matrix4x4: Single GetDeterminant() Matrix4x4: UnityEngine.FrustumPlanes DecomposeProjection() Matrix4x4: UnityEngine.Quaternion GetRotation() Matrix4x4: UnityEngine.Vector3 GetLossyScale() Message: Void Destroy(IntPtr) MonoBehaviour: Void ConstructorCheck(UnityEngine.Object) Native: Void YGConfigFreeInternal(IntPtr) Native: Void YGNodeFreeInternal(IntPtr) NativeFormatImporterUtility: System.String Internal_GetExtensionForNativeAsset(UnityEngine.Object) NativeFormatImporterUtility: System.Type Internal_GetNativeTypeForExtension(System.String, Boolean ByRef) NavMeshQuery: Boolean GetPortalPoints(IntPtr, UnityEngine.Experimental.AI.PolygonId, UnityEngine.Experimental.AI.PolygonId, UnityEngine.Vector3 ByRef, UnityEngine.Vector3 ByRef) NavMeshQuery: Boolean HasNodePool(IntPtr) NavMeshQuery: Boolean IsPositionInPolygon(IntPtr, UnityEngine.Vector3, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: Boolean IsValidPolygon(IntPtr, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: Int32 GetAgentTypeIdForPolygon(IntPtr, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: Int32 GetPathResult(IntPtr, Void*, Int32) NavMeshQuery: UnityEngine.Experimental.AI.NavMeshLocation MapLocation(IntPtr, UnityEngine.Vector3, UnityEngine.Vector3, Int32, Int32) NavMeshQuery: UnityEngine.Experimental.AI.NavMeshLocation MoveLocation(IntPtr, UnityEngine.Experimental.AI.NavMeshLocation, UnityEngine.Vector3, Int32) NavMeshQuery: UnityEngine.Experimental.AI.NavMeshPolyTypes GetPolygonType(IntPtr, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: UnityEngine.Experimental.AI.PathQueryStatus BeginFindPath(IntPtr, UnityEngine.Experimental.AI.NavMeshLocation, UnityEngine.Experimental.AI.NavMeshLocation, Int32, Void*) NavMeshQuery: UnityEngine.Experimental.AI.PathQueryStatus EndFindPath(IntPtr, Int32 ByRef) NavMeshQuery: UnityEngine.Experimental.AI.PathQueryStatus GetClosestPointOnPoly(IntPtr, UnityEngine.Experimental.AI.PolygonId, UnityEngine.Vector3, UnityEngine.Vector3 ByRef) NavMeshQuery: UnityEngine.Experimental.AI.PathQueryStatus Raycast(IntPtr, UnityEngine.Experimental.AI.NavMeshLocation, UnityEngine.Vector3, Int32, Void*, UnityEngine.AI.NavMeshHit ByRef, Void*, Int32 ByRef, Int32) NavMeshQuery: UnityEngine.Experimental.AI.PathQueryStatus UpdateFindPath(IntPtr, Int32, Int32 ByRef) NavMeshQuery: UnityEngine.Matrix4x4 PolygonLocalToWorldMatrix(IntPtr, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: UnityEngine.Matrix4x4 PolygonWorldToLocalMatrix(IntPtr, UnityEngine.Experimental.AI.PolygonId) NavMeshQuery: Void MoveLocations(IntPtr, Void*, Void*, Void*, Int32) NavMeshQuery: Void MoveLocationsInSameAreas(IntPtr, Void*, Void*, Int32, Int32) NotificationHelper: Void DestroyLocal(IntPtr) NotificationHelper: Void DestroyRemote(IntPtr) Object: Boolean CurrentThreadIsMainThread() Object: Boolean DoesObjectWithInstanceIDExist(Int32) Object: Int32 GetOffsetOfInstanceIDInCPlusPlusObject() ObjectGUIState: Void Internal_Destroy(IntPtr) OnDemandResourcesRequest: Void DestroyFromScript(IntPtr) PhraseRecognizer: Void DestroyThreaded(IntPtr) Ping: Void Internal_Destroy(IntPtr) Plugin: Void Destroy(IntPtr) Profiler: Void BeginSampleImpl(System.String, UnityEngine.Object) Profiler: Void BeginThreadProfilingInternal(System.String, System.String) ProfilerFrameDataIterator: Void Internal_Destroy(IntPtr) ProfilerMarker: IntPtr Internal_Create(System.String, Unity.Profiling.MarkerFlags) ProfilerMarker: Void Internal_Begin(IntPtr) ProfilerMarker: Void Internal_BeginWithObject(IntPtr, UnityEngine.Object) ProfilerMarker: Void Internal_End(IntPtr) ProfilerProperty: Void Internal_Delete(IntPtr) PropertySceneHandle: Boolean GetBoolInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Boolean HasValidTransform(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Boolean IsBound(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Int32 GetIntInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Single GetFloatInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Void ResolveInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertySceneHandle: Void SetBoolInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Boolean) PropertySceneHandle: Void SetFloatInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Single) PropertySceneHandle: Void SetIntInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Int32) PropertyStreamHandle: Boolean GetBoolInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertyStreamHandle: Int32 GetIntInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertyStreamHandle: Single GetFloatInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertyStreamHandle: Void ResolveInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) PropertyStreamHandle: Void SetBoolInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Boolean) PropertyStreamHandle: Void SetFloatInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Single) PropertyStreamHandle: Void SetIntInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, Int32) Quaternion: UnityEngine.Quaternion Internal_FromEulerRad(UnityEngine.Vector3) Quaternion: UnityEngine.Vector3 Internal_ToEulerRad(UnityEngine.Quaternion) Quaternion: Void Internal_ToAxisAngleRad(UnityEngine.Quaternion, UnityEngine.Vector3 ByRef, Single ByRef) ReadHandle: Boolean IsReadHandleValid(Unity.IO.LowLevel.Unsafe.ReadHandle) ReadHandle: Unity.IO.LowLevel.Unsafe.ReadStatus GetReadStatus(Unity.IO.LowLevel.Unsafe.ReadHandle) ReadHandle: Unity.Jobs.JobHandle GetJobHandle(Unity.IO.LowLevel.Unsafe.ReadHandle) ReadHandle: Void ReleaseReadHandle(Unity.IO.LowLevel.Unsafe.ReadHandle) Recorder: Boolean IsEnabled() Recorder: Int32 GetSampleBlockCount() Recorder: Int64 GetElapsedNanoseconds() Recorder: Void DisposeNative(IntPtr) Recorder: Void SetEnabled(Boolean) RemoteConfigSettings: Void Internal_Destroy(IntPtr) Sampler: System.String GetSamplerName() ScriptableObject: Void CreateScriptableObject(UnityEngine.ScriptableObject) SerializedObject: Void Internal_Destroy(IntPtr) SerializedObjectChangeTracker: Void Internal_Destroy(IntPtr) SerializedProperty: Void Internal_Destroy(IntPtr) Task: Void Destroy(IntPtr) TerrainData: Int32 GetBoundaryValue(BoundaryValueType) TextGenerator: IntPtr Internal_Create() TextGenerator: Void Internal_Destroy(IntPtr) TouchScreenKeyboard: Void Internal_Destroy(IntPtr) TransformAccess: Void GetLocalPosition(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void GetLocalRotation(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Quaternion ByRef) TransformAccess: Void GetLocalScale(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void GetPosition(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void GetRotation(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Quaternion ByRef) TransformAccess: Void SetLocalPosition(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void SetLocalRotation(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Quaternion ByRef) TransformAccess: Void SetLocalScale(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void SetPosition(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Vector3 ByRef) TransformAccess: Void SetRotation(UnityEngine.Jobs.TransformAccess ByRef, UnityEngine.Quaternion ByRef) TransformAccessArray: IntPtr GetSortedToUserIndex(IntPtr) TransformAccessArray: IntPtr GetSortedTransformAccess(IntPtr) TransformSceneHandle: Boolean HasValidTransform(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: UnityEngine.Quaternion GetLocalRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: UnityEngine.Quaternion GetRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: UnityEngine.Vector3 GetLocalPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: UnityEngine.Vector3 GetLocalScaleInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: UnityEngine.Vector3 GetPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformSceneHandle: Void SetLocalPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformSceneHandle: Void SetLocalRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Quaternion) TransformSceneHandle: Void SetLocalScaleInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformSceneHandle: Void SetPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformSceneHandle: Void SetRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Quaternion) TransformStreamHandle: UnityEngine.Quaternion GetLocalRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: UnityEngine.Quaternion GetRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: UnityEngine.Vector3 GetLocalPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: UnityEngine.Vector3 GetLocalScaleInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: UnityEngine.Vector3 GetPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: Void ResolveInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef) TransformStreamHandle: Void SetLocalPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformStreamHandle: Void SetLocalRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Quaternion) TransformStreamHandle: Void SetLocalScaleInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformStreamHandle: Void SetPositionInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Vector3) TransformStreamHandle: Void SetRotationInternal(UnityEngine.Experimental.Animations.AnimationStream ByRef, UnityEngine.Quaternion) TypeDB: IntPtr Internal_Create() TypeDB: Void Internal_Destroy(IntPtr) UnityLogWriter: Void WriteStringToUnityLogImpl(System.String) UnityWebRequest: System.String GetWebErrorString(UnityWebRequestError) UnityWebRequest: Void Release() UnsafeUtility: Int32 GetFieldOffsetInClass(System.Reflection.FieldInfo) UnsafeUtility: Int32 GetFieldOffsetInStruct(System.Reflection.FieldInfo) UnsafeUtility: Void LogError(System.String, System.String, Int32) UnsafeUtility: Void* PinSystemArrayAndGetAddress(System.Object, UInt64 ByRef) UnsafeUtility: Void* PinSystemObjectAndGetAddress(System.Object, UInt64 ByRef) UploadHandler: Void Release() Vector3: Void OrthoNormalize2(UnityEngine.Vector3 ByRef, UnityEngine.Vector3 ByRef) Vector3: Void OrthoNormalize3(UnityEngine.Vector3 ByRef, UnityEngine.Vector3 ByRef, UnityEngine.Vector3 ByRef) VFXCPUBufferData: Void Internal_Destroy(IntPtr) VFXEventAttribute: Void Internal_Destroy(IntPtr) VFXSpawnerState: Void Internal_Destroy(IntPtr) WaveformStreamer: Void Internal_WaveformStreamerDestroy(IntPtr)
We’re now up to 301 job-safe APIs, but many of them are private
or internal
to Unity and so must be called indirectly via a public
API. All in all, it’s just an expansion of nine methods and properties since Unity 2018.2. However, Unity increasingly relies on packages to provide new functionality such as the ECS currently in Preview. To inspect any other libraries with this script, simply change the paths
variable to include their directories.
#1 by Pino Rossi on January 21st, 2019 ·
Dear Jackson,
after years standing like a last Japanese on a pacific island, I feel it’s time to move away from AS3 (yes, I managed to make a living with AIR so far). I am considering a transition to Unity in order to retain a similar freedom as in the Flash platform.
How does it feel working in Unity after many yars of beautiful AS3? And how is it professionally? I have been a freelance all my life and want to stay a freelance, but I see there are many more jobs and gigs in the hated JS world than in Unity. Might I ask your views on these isues?
Thank you very much
Pino
#2 by jackson on January 22nd, 2019 ·
Hi Pino,
I responded to your comment via e-mail since it’s off-topic for this article.
-Jackson
#3 by Andrés Leone on December 23rd, 2021 ·
I tried porting this to Windows and found that maybe this would work on all OS.
Can someone confirm it?
.