首页 > 其他分享 >Unity 性能优化之DynamicBone

Unity 性能优化之DynamicBone

时间:2023-02-25 15:48:33浏览次数:58  
标签:DynamicBoneFast index int MAX void Unity DynamicBone 优化 public

DynmaicBone最新版本使用了多线程,30人同屏情况下消耗为6ms左右,如下图:

这个消耗依旧挺大,会使50帧的游戏降10帧左右。

 

使用 job system + burst 优化后的消耗为 0.05 ms,如下图:

 

 优化方案参考如下:

https://blog.csdn.net/tangyin025/article/details/109683573

https://zhuanlan.zhihu.com/p/113367281

本人已将其整合到项目中,提供简略版的DynmaicBone,即DynamicBoneFast,源码分享如下:

DynamicBoneFast.cs

  1 using Unity.Collections;
  2 using Unity.Mathematics;
  3 using UnityEngine;
  4 
  5 [AddComponentMenu("Dynamic Bone/Dynamic Bone Fast")]
  6 public class DynamicBoneFast : MonoBehaviour
  7 {
  8     #region Particle & HeadInfo
  9 
 10     public struct Particle
 11     {
 12         public int m_ParentIndex;
 13         public int m_ChildCount;
 14         public float m_Damping;
 15         public float m_Elasticity;
 16         public float m_Stiffness;
 17         public float m_Inert;
 18 
 19         public float3 m_EndOffset;
 20         public float3 m_InitLocalPosition;
 21         public quaternion m_InitLocalRotation;
 22 
 23         // [ta]
 24         public int index;
 25         public float3 tmpWorldPosition;
 26         public float3 tmpPrevWorldPosition;
 27         public float3 localPosition;
 28         public quaternion localRotation;
 29         public float3 parentScale;
 30         public int isRootParticle;
 31 
 32         //for output
 33         public float3 worldPosition;
 34         public quaternion worldRotation;
 35     }
 36 
 37     // [ta]
 38     public struct HeadInfo
 39     {
 40         int m_HeadIndex;
 41 
 42         public float m_UpdateRate;
 43         public Vector3 m_ObjectMove;
 44         public int m_particleCount;
 45         public int m_jobDataOffset;
 46         public int m_ParticleLoopCount;
 47 
 48         public float3 m_RootParentBoneWorldPos;
 49         public quaternion m_RootParentBoneWorldRot;
 50 
 51         public int HeadIndex
 52         {
 53             get => m_HeadIndex;
 54             set => m_HeadIndex = value;
 55         }
 56     }
 57 
 58     #endregion
 59 
 60     public const int MAX_TRANSFORM_LIMIT = 10;
 61 
 62     public Transform m_Root;
 63     public float m_UpdateRate = 60.0f;
 64     [Range(0, 1)]
 65     public float m_Damping = 0.1f;
 66     [Range(0, 1)]
 67     public float m_Elasticity = 0.1f;
 68     [Range(0, 1)]
 69     public float m_Stiffness = 0.1f;
 70     [Range(0, 1)]
 71     public float m_Inert = 0;
 72 
 73     public bool m_DistantDisable = false;
 74     public Transform m_ReferenceObject = null;
 75     public float m_DistanceToObject = 20;
 76 
 77     public NativeArray<Particle> m_Particles;
 78     public Transform[] m_particleTransformArr;
 79     private int m_ParticleCount;
 80     public Transform m_rootParentTransform;
 81     public HeadInfo m_headInfo;
 82     bool m_IsInited;
 83 
 84 
 85     public HeadInfo ResetHeadIndexAndDataOffset(int headIndex)
 86     {
 87         m_headInfo.HeadIndex = headIndex;
 88         m_headInfo.m_jobDataOffset = headIndex * MAX_TRANSFORM_LIMIT;
 89 
 90         return m_headInfo;
 91     }
 92     public void ClearJobData()
 93     {
 94         if (m_Particles.IsCreated)
 95         {
 96             m_Particles.Dispose();
 97         }
 98 
 99         m_particleTransformArr = null;
100         m_IsInited = false;
101     }
102 
103     void Awake()
104     {
105         Init();
106     }
107 
108     void Init()
109     {
110         if (m_Root == null)
111             return;
112 
113         m_headInfo = new HeadInfo();
114         m_headInfo.m_UpdateRate = this.m_UpdateRate;
115         m_headInfo.m_ObjectMove = Vector3.zero;
116         m_headInfo.m_particleCount = 0;
117 
118         m_Particles = new NativeArray<Particle>(MAX_TRANSFORM_LIMIT, Allocator.Persistent);
119         m_particleTransformArr = new Transform[MAX_TRANSFORM_LIMIT];
120         m_ParticleCount = 0;
121 
122         SetupParticles();
123 
124         m_IsInited = true;
125     }
126 
127     public void BeginWork()
128     {
129         if (!m_IsInited)
130             Init();
131         DoEnable();
132     }
133 
134     void DoEnable()
135     {
136         if (m_IsInited)
137             DynamicBoneFastMgr.Singleton.OnEnter(this);
138     }
139 
140     void DoDisable()
141     {
142         DynamicBoneFastMgr.Singleton.OnExit(this);
143     }
144 
145     void OnEnable()
146     {
147         if (!m_IsInited)
148             Init();
149         DoEnable();
150     }
151 
152     void OnDisable()
153     {
154         InitTransforms();
155         DoDisable();
156     }
157 
158     void OnDestroy()
159     {
160         DoDisable();
161     }
162 
163     void SetupParticles()
164     {
165         if (m_Root == null)
166             return;
167 
168         AppendParticles(m_Root, -1, 0);
169         UpdateParameters();
170 
171         m_headInfo.m_particleCount = m_ParticleCount;
172         m_rootParentTransform = m_Root.parent;
173     }
174 
175     void AppendParticles(Transform b, int parentIndex, float boneLength)
176     {
177         var p = new Particle();
178         p.index = m_ParticleCount++;
179         p.m_ParentIndex = parentIndex;
180 
181         if (b != null)
182         {
183             p.tmpWorldPosition = p.tmpPrevWorldPosition = b.position;
184             p.m_InitLocalPosition = b.localPosition;
185             p.m_InitLocalRotation = b.localRotation;
186 
187             // [ta]
188             p.localPosition = b.localPosition;
189             p.localRotation = b.localRotation;
190             p.parentScale = b.parent.lossyScale;
191             p.isRootParticle = parentIndex == -1 ? 1 : 0;
192         }
193         else     // end bone
194         {
195             Transform pb = m_particleTransformArr[parentIndex];
196             p.m_EndOffset = pb.InverseTransformPoint(transform.position + pb.position);
197             p.tmpWorldPosition = p.tmpPrevWorldPosition = pb.TransformPoint(p.m_EndOffset);
198             p.m_InitLocalPosition = Vector3.zero;
199             p.m_InitLocalRotation = Quaternion.identity;
200         }
201 
202         if (parentIndex >= 0)
203         {
204             float dis = math.distance(m_particleTransformArr[parentIndex].position, p.tmpWorldPosition);
205             boneLength += dis;
206             ++p.m_ChildCount;
207         }
208 
209         m_Particles[p.index] = p;
210         m_particleTransformArr[p.index] = b;
211 
212         int index = p.index;
213 
214         if (b != null)
215         {
216             for (int i = 0; i < b.childCount; ++i)
217             {
218                 Transform child = b.GetChild(i);
219                 AppendParticles(child, index, boneLength);
220             }
221         }
222     }
223 
224     public void UpdateParameters()
225     {
226         if (m_Root == null)
227             return;
228 
229         for (int i = 0; i < m_ParticleCount; ++i)
230         {
231             Particle p = m_Particles[i];
232             p.m_Damping = m_Damping;
233             p.m_Elasticity = m_Elasticity;
234             p.m_Stiffness = m_Stiffness;
235             p.m_Inert = m_Inert;
236             p.m_Damping = Mathf.Clamp01(p.m_Damping);
237             p.m_Elasticity = Mathf.Clamp01(p.m_Elasticity);
238             p.m_Stiffness = Mathf.Clamp01(p.m_Stiffness);
239             p.m_Inert = Mathf.Clamp01(p.m_Inert);
240 
241             m_Particles[i] = p;
242         }
243     }
244 
245     void InitTransforms()
246     {
247         for (int i = 0; i < m_ParticleCount; ++i)
248         {
249             Particle p = m_Particles[i];
250             Transform trans = m_particleTransformArr[p.index];
251             if (trans != null)
252             {
253                 p.localPosition = p.m_InitLocalPosition;
254                 p.localRotation = p.m_InitLocalRotation;
255             }
256         }
257     }
258 
259 }

DynamicBoneFastMgr.cs

  1 using System.Collections.Generic;
  2 using Tools;
  3 using Unity.Burst;
  4 using Unity.Collections;
  5 using Unity.Jobs;
  6 using Unity.Mathematics;
  7 using UnityEngine;
  8 using UnityEngine.Jobs;
  9 
 10 public class DynamicBoneFastMgr : SingletonMonoBehaviour<DynamicBoneFastMgr>
 11 {
 12     #region Job
 13 
 14     [BurstCompile]
 15     struct RootPosApplyJob : IJobParallelForTransform
 16     {
 17         public NativeArray<DynamicBoneFast.HeadInfo> ParticleHeadInfo;
 18 
 19         public void Execute(int index, TransformAccess transform)
 20         {
 21             DynamicBoneFast.HeadInfo headInfo = ParticleHeadInfo[index];
 22             headInfo.m_RootParentBoneWorldPos = transform.position;
 23             headInfo.m_RootParentBoneWorldRot = transform.rotation;
 24 
 25             ParticleHeadInfo[index] = headInfo;
 26         }
 27     }
 28 
 29     [BurstCompile]
 30     struct PrepareParticleJob : IJob
 31     {
 32         [ReadOnly]
 33         public NativeArray<DynamicBoneFast.HeadInfo> ParticleHeadInfo;
 34         public NativeArray<DynamicBoneFast.Particle> ParticleInfo;
 35         public int HeadCount;
 36 
 37         public void Execute()
 38         {
 39             for (int i = 0; i < HeadCount; i++)
 40             {
 41                 DynamicBoneFast.HeadInfo curHeadInfo = ParticleHeadInfo[i];
 42 
 43                 float3 parentPosition = curHeadInfo.m_RootParentBoneWorldPos;
 44                 quaternion parentRotation = curHeadInfo.m_RootParentBoneWorldRot;
 45 
 46                 for (int j = 0; j < curHeadInfo.m_particleCount; j++)
 47                 {
 48                     int pIdx = curHeadInfo.m_jobDataOffset + j;
 49                     DynamicBoneFast.Particle p = ParticleInfo[pIdx];
 50 
 51                     var localPosition = p.localPosition * p.parentScale;
 52                     var localRotation = p.localRotation;
 53                     var worldPosition = parentPosition + math.mul(parentRotation, localPosition);
 54                     var worldRotation = math.mul(parentRotation, localRotation);
 55 
 56                     p.worldPosition = worldPosition;
 57                     p.worldRotation = worldRotation;
 58 
 59                     parentPosition = worldPosition;
 60                     parentRotation = worldRotation;
 61 
 62                     ParticleInfo[pIdx] = p;
 63                 }
 64             }
 65         }
 66     }
 67 
 68     [BurstCompile]
 69     struct UpdateParticles1Job : IJobParallelFor
 70     {
 71         [ReadOnly]
 72         public NativeArray<DynamicBoneFast.HeadInfo> ParticleHeadInfo;
 73         public NativeArray<DynamicBoneFast.Particle> ParticleInfo;
 74         public int HeadCount;
 75 
 76         public void Execute(int index)
 77         {
 78             int headIndex = index / DynamicBoneFast.MAX_TRANSFORM_LIMIT;
 79             DynamicBoneFast.HeadInfo curHeadInfo = ParticleHeadInfo[headIndex];
 80             int singleId = index % DynamicBoneFast.MAX_TRANSFORM_LIMIT;
 81 
 82             if (singleId >= curHeadInfo.m_particleCount)
 83                 return;
 84 
 85             int pIdx = curHeadInfo.m_jobDataOffset + (index % DynamicBoneFast.MAX_TRANSFORM_LIMIT);
 86 
 87             DynamicBoneFast.Particle p = ParticleInfo[pIdx];
 88 
 89             if (p.m_ParentIndex >= 0)
 90             {
 91                 float3 ev = p.tmpWorldPosition - p.tmpPrevWorldPosition;
 92                 float3 evrmove = curHeadInfo.m_ObjectMove * p.m_Inert;
 93                 p.tmpPrevWorldPosition = p.tmpWorldPosition + evrmove;
 94 
 95                 float edamping = p.m_Damping;
 96                 float3 tmp = ev * (1 - edamping) + evrmove;
 97                 p.tmpWorldPosition += tmp;
 98             }
 99             else
100             {
101                 p.tmpPrevWorldPosition = p.tmpWorldPosition;
102                 p.tmpWorldPosition = p.worldPosition;
103             }
104 
105             ParticleInfo[pIdx] = p;
106         }
107     }
108 
109     [BurstCompile]
110     struct UpdateParticle2Job : IJobParallelFor
111     {
112         [ReadOnly]
113         public NativeArray<DynamicBoneFast.HeadInfo> ParticleHeadInfo;
114         public NativeArray<DynamicBoneFast.Particle> ParticleInfo;
115         public int HeadCount;
116         public float DeltaTime;
117 
118         public void Execute(int index)
119         {
120             if (index % DynamicBoneFast.MAX_TRANSFORM_LIMIT == 0)
121                 return;
122 
123             int headIndex = index / DynamicBoneFast.MAX_TRANSFORM_LIMIT;
124             DynamicBoneFast.HeadInfo curHeadInfo = ParticleHeadInfo[headIndex];
125 
126             int singleId = index % DynamicBoneFast.MAX_TRANSFORM_LIMIT;
127 
128             if (singleId >= curHeadInfo.m_particleCount)
129                 return;
130 
131             int pIdx = curHeadInfo.m_jobDataOffset + (index % DynamicBoneFast.MAX_TRANSFORM_LIMIT);
132 
133             DynamicBoneFast.Particle p = ParticleInfo[pIdx];
134             int p0Idx = curHeadInfo.m_jobDataOffset + p.m_ParentIndex;
135             DynamicBoneFast.Particle p0 = ParticleInfo[p0Idx];
136 
137             float3 ePos = p.worldPosition;
138             float3 ep0Pos = p0.worldPosition;
139 
140             float erestLen = math.distance(ep0Pos, ePos);
141 
142             float stiffness = p.m_Stiffness;
143             if (stiffness > 0 || p.m_Elasticity > 0)
144             {
145                 float4x4 em0 = float4x4.TRS(p0.tmpWorldPosition, p0.worldRotation, p.parentScale);
146                 float3 erestPos = math.mul(em0, new float4(p.localPosition.xyz, 1)).xyz;
147                 float3 ed = erestPos - p.tmpWorldPosition;
148                 float3 eStepElasticity = ed * p.m_Elasticity * curHeadInfo.m_UpdateRate * DeltaTime;
149                 p.tmpWorldPosition += eStepElasticity;
150 
151                 if (stiffness > 0)
152                 {
153                     float len = math.distance(erestPos, p.tmpWorldPosition);
154                     float maxlen = erestLen * (1 - stiffness) * 2;
155                     if (len > maxlen)
156                     {
157                         float3 max = ed * ((len - maxlen) / len);
158                         p.tmpWorldPosition += max;
159                     }
160                 }
161             }
162 
163             float3 edd = p0.tmpWorldPosition - p.tmpWorldPosition;
164             float eleng = math.distance(p0.tmpWorldPosition, p.tmpWorldPosition);
165             if (eleng > 0)
166             {
167                 float3 tmp = edd * ((eleng - erestLen) / eleng);
168                 p.tmpWorldPosition += tmp;
169             }
170 
171             ParticleInfo[pIdx] = p;
172         }
173     }
174 
175     [BurstCompile]
176     struct ApplyParticleToTransform : IJobParallelFor
177     {
178         [ReadOnly]
179         public NativeArray<DynamicBoneFast.HeadInfo> ParticleHeadInfo;
180         public NativeArray<DynamicBoneFast.Particle> ParticleInfo;
181         public int HeadCount;
182 
183         public void Execute(int index)
184         {
185             if (index % DynamicBoneFast.MAX_TRANSFORM_LIMIT == 0)
186                 return;
187 
188             int headIndex = index / DynamicBoneFast.MAX_TRANSFORM_LIMIT;
189 
190             DynamicBoneFast.HeadInfo curHeadInfo = ParticleHeadInfo[headIndex];
191             int singleId = index % DynamicBoneFast.MAX_TRANSFORM_LIMIT;
192 
193             if (singleId >= curHeadInfo.m_particleCount)
194                 return;
195 
196             int pIdx = curHeadInfo.m_jobDataOffset + (index % DynamicBoneFast.MAX_TRANSFORM_LIMIT);
197 
198             DynamicBoneFast.Particle p = ParticleInfo[pIdx];
199             int p0Idx = curHeadInfo.m_jobDataOffset + p.m_ParentIndex;
200             DynamicBoneFast.Particle p0 = ParticleInfo[p0Idx];
201 
202             if (p0.m_ChildCount <= 1)
203             {
204                 float3 ev = p.localPosition;
205                 float3 ev2 = p.tmpWorldPosition - p0.tmpWorldPosition;
206 
207                 float4x4 epm = float4x4.TRS(p.worldPosition, p.worldRotation, p.parentScale);
208 
209                 var worldV = math.mul(epm, new float4(ev, 0)).xyz;
210                 Quaternion erot = Quaternion.FromToRotation(worldV, ev2);
211                 var eoutputRot = math.mul(erot, p.worldRotation);
212                 p0.worldRotation = eoutputRot;
213             }
214 
215             p.worldPosition = p.tmpWorldPosition;
216 
217             ParticleInfo[pIdx] = p;
218             ParticleInfo[p0Idx] = p0;
219         }
220     }
221 
222     [BurstCompile]
223     struct FinalJob : IJobParallelForTransform
224     {
225         [ReadOnly]
226         public NativeArray<DynamicBoneFast.Particle> ParticleInfo;
227 
228         public void Execute(int index, TransformAccess transform)
229         {
230             transform.rotation = ParticleInfo[index].worldRotation;
231             transform.position = ParticleInfo[index].worldPosition;
232         }
233     }
234 
235     #endregion
236 
237 
238     List<DynamicBoneFast> m_DynamicBoneList;
239     NativeList<DynamicBoneFast.Particle> m_ParticleInfoList;
240     NativeList<DynamicBoneFast.HeadInfo> m_HeadInfoList;
241 
242     TransformAccessArray m_headRootTransform;
243     TransformAccessArray m_particleTransformArr;
244     int m_DbDataLen;
245     JobHandle m_lastJobHandle;
246 
247     Queue<DynamicBoneFast> m_loadingQueue = new Queue<DynamicBoneFast>();
248     Queue<DynamicBoneFast> m_removeQueue = new Queue<DynamicBoneFast>();
249 
250 
251     void Awake()
252     {
253         m_DynamicBoneList = new List<DynamicBoneFast>();
254         m_ParticleInfoList = new NativeList<DynamicBoneFast.Particle>(Allocator.Persistent);
255         m_HeadInfoList = new NativeList<DynamicBoneFast.HeadInfo>(Allocator.Persistent);
256         m_particleTransformArr = new TransformAccessArray(200 * DynamicBoneFast.MAX_TRANSFORM_LIMIT, 64);
257         m_headRootTransform = new TransformAccessArray(200, 64);
258     }
259 
260     void UpdateQueue()
261     {
262         while (m_loadingQueue.Count > 0)
263         {
264             DynamicBoneFast target = m_loadingQueue.Dequeue();
265             int index = m_DynamicBoneList.IndexOf(target);
266             if (index != -1)
267                 continue;
268 
269             m_DynamicBoneList.Add(target);
270             target.m_headInfo.m_jobDataOffset = m_ParticleInfoList.Length;
271             target.m_headInfo.HeadIndex = m_HeadInfoList.Length;
272             m_HeadInfoList.Add(target.m_headInfo);
273             m_ParticleInfoList.AddRange(target.m_Particles);
274             m_headRootTransform.Add(target.m_rootParentTransform);
275 
276             for (int i = 0; i < DynamicBoneFast.MAX_TRANSFORM_LIMIT; i++)
277                 m_particleTransformArr.Add(target.m_particleTransformArr[i]);
278 
279             m_DbDataLen++;
280         }
281 
282         while (m_removeQueue.Count > 0)
283         {
284             DynamicBoneFast target = m_removeQueue.Dequeue();
285             int index = m_DynamicBoneList.IndexOf(target);
286             if (index != -1)
287             {
288                 m_DynamicBoneList.RemoveAt(index);
289 
290                 int curHeadIndex = target.m_headInfo.HeadIndex;
291 
292                 //是否是队列中末尾对象
293                 bool isEndTarget = curHeadIndex == m_HeadInfoList.Length - 1;
294                 if (isEndTarget)
295                 {
296                     m_HeadInfoList.RemoveAtSwapBack(curHeadIndex);
297                     m_headRootTransform.RemoveAtSwapBack(curHeadIndex);
298 
299                     for (int i = DynamicBoneFast.MAX_TRANSFORM_LIMIT - 1; i >= 0; i--)
300                     {
301                         int dataOffset = curHeadIndex * DynamicBoneFast.MAX_TRANSFORM_LIMIT + i;
302                         m_ParticleInfoList.RemoveAtSwapBack(dataOffset);
303                         m_particleTransformArr.RemoveAtSwapBack(dataOffset);
304                     }
305                 }
306                 else
307                 {
308                     //将最末列的HeadInfo 索引设置为当前将要移除的HeadInfo 索引
309                     DynamicBoneFast lastTarget = m_DynamicBoneList[m_DynamicBoneList.Count - 1];
310                     m_DynamicBoneList.RemoveAt(m_DynamicBoneList.Count - 1);
311                     m_DynamicBoneList.Insert(index, lastTarget);
312 
313                     DynamicBoneFast.HeadInfo lastHeadInfo = lastTarget.ResetHeadIndexAndDataOffset(curHeadIndex);
314                     m_HeadInfoList.RemoveAtSwapBack(curHeadIndex);
315                     m_HeadInfoList[curHeadIndex] = lastHeadInfo;
316                     m_headRootTransform.RemoveAtSwapBack(curHeadIndex);
317 
318                     for (int i = DynamicBoneFast.MAX_TRANSFORM_LIMIT - 1; i >= 0; i--)
319                     {
320                         int dataOffset = curHeadIndex * DynamicBoneFast.MAX_TRANSFORM_LIMIT + i;
321                         m_ParticleInfoList.RemoveAtSwapBack(dataOffset);
322                         m_particleTransformArr.RemoveAtSwapBack(dataOffset);
323                     }
324                 }
325 
326                 m_DbDataLen--;
327             }
328 
329             target.ClearJobData();
330         }
331     }
332 
333     public void OnEnter(DynamicBoneFast target)
334     {
335         m_loadingQueue.Enqueue(target);
336     }
337 
338     public void OnExit(DynamicBoneFast target)
339     {
340         m_removeQueue.Enqueue(target);
341     }
342 
343     void LateUpdate()
344     {
345         if (!m_lastJobHandle.IsCompleted)
346             return;
347 
348         m_lastJobHandle.Complete();
349 
350         UpdateQueue();
351 
352         if (m_DbDataLen == 0)
353             return;
354 
355         var dataArrLength = m_DbDataLen * DynamicBoneFast.MAX_TRANSFORM_LIMIT;
356 
357         var rootJob = new RootPosApplyJob
358         {
359             ParticleHeadInfo = m_HeadInfoList
360         };
361         var rootHandle = rootJob.Schedule(m_headRootTransform);
362 
363         var prepareJob = new PrepareParticleJob
364         {
365             ParticleHeadInfo = m_HeadInfoList,
366             ParticleInfo = m_ParticleInfoList,
367             HeadCount = m_DbDataLen
368         };
369         var prepareHandle = prepareJob.Schedule(rootHandle);
370 
371         var update1Job = new UpdateParticles1Job
372         {
373             ParticleHeadInfo = m_HeadInfoList,
374             ParticleInfo = m_ParticleInfoList,
375             HeadCount = m_DbDataLen
376         };
377         var update1Handle = update1Job.Schedule(dataArrLength, DynamicBoneFast.MAX_TRANSFORM_LIMIT, prepareHandle);
378 
379         var update2Job = new UpdateParticle2Job
380         {
381             ParticleHeadInfo = m_HeadInfoList,
382             ParticleInfo = m_ParticleInfoList,
383             HeadCount = m_DbDataLen,
384             DeltaTime = Time.deltaTime,
385         };
386         var update2Handle = update2Job.Schedule(dataArrLength, DynamicBoneFast.MAX_TRANSFORM_LIMIT, update1Handle);
387 
388         var appTransJob = new ApplyParticleToTransform
389         {
390             ParticleHeadInfo = m_HeadInfoList,
391             ParticleInfo = m_ParticleInfoList,
392             HeadCount = m_DbDataLen
393         };
394 
395         var appTransHandle = appTransJob.Schedule(dataArrLength, DynamicBoneFast.MAX_TRANSFORM_LIMIT, update2Handle);
396         var finalJob = new FinalJob
397         {
398             ParticleInfo = m_ParticleInfoList,
399         };
400         var finalHandle = finalJob.Schedule(m_particleTransformArr, appTransHandle);
401 
402         m_lastJobHandle = finalHandle;
403 
404         JobHandle.ScheduleBatchedJobs();
405     }
406 
407     void OnDestroy()
408     {
409         if (m_particleTransformArr.isCreated)
410         {
411             m_particleTransformArr.Dispose();
412         }
413 
414         if (m_ParticleInfoList.IsCreated)
415         {
416             m_ParticleInfoList.Dispose();
417         }
418 
419         if (m_HeadInfoList.IsCreated)
420         {
421             m_HeadInfoList.Dispose();
422         }
423 
424         if (m_headRootTransform.isCreated)
425         {
426             m_headRootTransform.Dispose();
427         }
428     }
429 }

转载请注明出处:https://www.cnblogs.com/jietian331/p/17154522.html

标签:DynamicBoneFast,index,int,MAX,void,Unity,DynamicBone,优化,public
From: https://www.cnblogs.com/jietian331/p/17154522.html

相关文章