public void Play(string clipName) { GPUSkinningClip[] clips = res.anim.clips; int numClips = clips == null ? 0 : clips.Length; for (int i = 0; i < numClips; ++i) { if (clips[i].name == clipName) { if (playingClip != clips[i] || (playingClip != null && playingClip.wrapMode == GPUSkinningWrapMode.Once && IsTimeAtTheEndOfLoop) || (playingClip != null && !isPlaying)) { isPlaying = true; playingClip = clips[i]; rootMotionFrameIndex = -1; if (playingClip.wrapMode == GPUSkinningWrapMode.Once) { time = 0; } else if (playingClip.wrapMode == GPUSkinningWrapMode.Loop) { time = 0; timeDiff = Random.Range(0, playingClip.length); } else { throw new System.NotImplementedException(); } } return; } } }
/// <summary> /// 设置动画片段的Material->Shader属性,使用GPU计算动画片段数据 /// </summary> /// <param name="mpb"> 需要设置的MaterialPropertyBlock </param> /// <param name="playingClip"> 当前播放的动画片段 </param> /// <param name="frameIndex"> 帧索引 </param> /// <param name="frame"> 帧数据 </param> /// <param name="rootMotionEnabled"> 是否应用RootMotion </param> /// <param name="lastPlayedClip"> 上一次播放的动画片段 </param> /// <param name="frameIndex_crossFade"> 需要CrossFade的上一个动画片段帧索引(上一次播放到的动画片段) </param> /// <param name="crossFadeTime"> CrossFade所花的时间 </param> /// <param name="crossFadeProgress"> CrossFade已经处理的时间 </param> public void UpdatePlayingData( MaterialPropertyBlock mpb, GPUSkinningClip playingClip, int frameIndex, GPUSkinningFrame frame, bool rootMotionEnabled, GPUSkinningClip lastPlayedClip, int frameIndex_crossFade, float crossFadeTime, float crossFadeProgress) { //Profiler.BeginSample("Res.UpdatePlayingData"); //设置mpb的Vector属性 mpb.SetVector(shaderPorpID_GPUSkinning_FrameIndex_PixelSegmentation, new Vector4(frameIndex, playingClip.pixelSegmentation, 0, 0)); //如果开启RootMotion if (rootMotionEnabled) { Matrix4x4 rootMotionInv = frame.RootMotionInv(anim.rootBoneIndex); mpb.SetMatrix(shaderPropID_GPUSkinning_RootMotion, rootMotionInv); } //如果开启CrossFade if (IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { if (lastPlayedClip.rootMotionEnabled) { mpb.SetMatrix(shaderPropID_GPUSkinning_RootMotion_CrossFade, lastPlayedClip.frames[frameIndex_crossFade].RootMotionInv(anim.rootBoneIndex)); } mpb.SetVector(shaderPorpID_GPUSkinning_FrameIndex_PixelSegmentation_Blend_CrossFade, new Vector4(frameIndex_crossFade, lastPlayedClip.pixelSegmentation, CrossFadeBlendFactor(crossFadeProgress, crossFadeTime))); } //Profiler.EndSample(); }
private void CreateTextureMatrix(string dir, GPUSkinningAnimation gpuSkinningAnim) { Texture2D texture = new Texture2D(gpuSkinningAnim.textureWidth, gpuSkinningAnim.textureHeight, TextureFormat.RGBAHalf, false, true); Color[] pixels = texture.GetPixels(); int pixelIndex = 0; for (int clipIndex = 0; clipIndex < gpuSkinningAnim.clips.Length; ++clipIndex) { GPUSkinningClip clip = gpuSkinningAnim.clips[clipIndex]; GPUSkinningFrame[] frames = clip.frames; int numFrames = frames.Length; for (int frameIndex = 0; frameIndex < numFrames; ++frameIndex) { GPUSkinningFrame frame = frames[frameIndex]; Matrix4x4[] matrices = frame.matrices; int numMatrices = matrices.Length; for (int matrixIndex = 0; matrixIndex < numMatrices; ++matrixIndex) { Matrix4x4 matrix = matrices[matrixIndex]; pixels[pixelIndex++] = new Color(matrix.m00, matrix.m01, matrix.m02, matrix.m03); pixels[pixelIndex++] = new Color(matrix.m10, matrix.m11, matrix.m12, matrix.m13); pixels[pixelIndex++] = new Color(matrix.m20, matrix.m21, matrix.m22, matrix.m23); } } } texture.SetPixels(pixels); texture.Apply(); string savedPath = dir + "/GPUSKinning_Texture_" + animName + ".bytes"; File.WriteAllBytes(savedPath, texture.GetRawTextureData()); WriteTempData(TEMP_SAVED_TEXTURE_PATH, savedPath); }
private void FillEvents(GPUSkinningClip clip, GPUSkinningBetterList <GPUSkinningAnimEvent> events) { events.Clear(); if (clip != null && clip.events != null && clip.events.Length > 0) { events.AddRange(clip.events); } }
public static int NormalizeTimeToFrameIndex(GPUSkinningClip clip, float normalizedTime) { if (clip == null) { return(0); } normalizedTime = Mathf.Clamp01(normalizedTime); return((int)(normalizedTime * (clip.length * clip.fps - 1))); }
private void SetNewPlayingClip(GPUSkinningClip clip) { lastPlayedClip = playingClip; lastPlayedTime = GetCurrentTime(); isPlaying = true; playingClip = clip; rootMotionFrameIndex = -1; time = 0; timeDiff = Random.Range(0, playingClip.length); }
public void UpdatePlayingData(MaterialPropertyBlock mpb, GPUSkinningClip playingClip, int frameIndex, GPUSkinningFrame frame, bool rootMotionEnabled) { mpb.SetFloat(shaderPorpID_GPUSkinning_FrameIndex, frameIndex); mpb.SetFloat(shaderPropID_GPUSkinning_PixelSegmentation, playingClip.pixelSegmentation); mpb.SetFloat(shaderPropID_GPUSkinning_RootMotionEnabled, rootMotionEnabled ? 1 : -1); if (rootMotionEnabled) { Matrix4x4 rootMotionInv = frame.RootMotionInv(anim.rootBoneIndex); mpb.SetMatrix(shaderPropID_GPUSkinning_RootMotion, rootMotionInv); } }
public static float FrameIndexToNormalizedTime(GPUSkinningClip clip, int frameIndex) { if (clip == null) { return(0); } int totalFrams = (int)(clip.fps * clip.length); frameIndex = Mathf.Clamp(frameIndex, 0, totalFrams - 1); return((float)frameIndex / (float)(totalFrams - 1)); }
private void SetNewPlayingClip(GPUSkinningClip clip, float normalize = 0) { lastPlayedClip = playingClip; lastPlayedTime = GetCurrentTime(); isPlaying = true; playingClip = clip; rootMotionFrameIndex = -1; m_AnimTime = playingClip.length * normalize; //timeDiff = Random.Range(0, playingClip.length); timeDiff = m_AnimTime; }
public void UpdatePlayingData( GPUSkinningClip playingClip, int frameIndex, GPUSkinningFrame frame, bool rootMotionEnabled, GPUSkinningClip lastPlayedClip, int frameIndex_crossFade, float crossFadeTime, float crossFadeProgress) { //Profiler.BeginSample("PlayerMono.UpdatePlayingData"); myRes.UpdatePlayingData(mpb, playingClip, frameIndex, frame, rootMotionEnabled, lastPlayedClip, frameIndex_crossFade, crossFadeTime, crossFadeProgress); //Profiler.EndSample(); //Profiler.BeginSample("PlayerMono.SetPropertyBlock"); mr.SetPropertyBlock(mpb); //Profiler.EndSample(); }
/// <summary> /// 更新当前播放的动画 /// </summary> /// <param name="clip"></param> private void SetNewPlayingClip(GPUSkinningClip clip) { //记录上一个播放的动画片段(用处?) lastPlayedClip = playingClip; //记录播放上一个动画片段的时间 lastPlayedTime = GetCurrentTime(); isPlaying = true; playingClip = clip; rootMotionFrameIndex = -1; time = 0; // 随机生成动画帧数偏移 timeDiff = Random.Range(0, playingClip.length); }
private void UpdateMaterial(float deltaTime, GPUSkinningMaterial currMtrl) { int frameIndex = GetFrameIndex(); if (lastPlayingClip == playingClip && lastPlayingFrameIndex == frameIndex) { res.Update(deltaTime, currMtrl); return; } lastPlayingClip = playingClip; lastPlayingFrameIndex = frameIndex; float blend_crossFade = 1; int frameIndex_crossFade = -1; GPUSkinningFrame frame_crossFade = null; if (res.IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { frameIndex_crossFade = GetCrossFadeFrameIndex(); frame_crossFade = lastPlayedClip.frames[frameIndex_crossFade]; blend_crossFade = res.CrossFadeBlendFactor(crossFadeProgress, crossFadeTime); } GPUSkinningFrame frame = playingClip.frames[frameIndex]; if (Visible || CullingMode == GPUSKinningCullingMode.AlwaysAnimate) { res.Update(deltaTime, currMtrl); res.UpdatePlayingData( mpb, playingClip, frameIndex, frame, playingClip.rootMotionEnabled && rootMotionEnabled, lastPlayedClip, GetCrossFadeFrameIndex(), crossFadeTime, crossFadeProgress ); mr.SetPropertyBlock(mpb); UpdateJoints(frame); } if (playingClip.rootMotionEnabled && rootMotionEnabled && frameIndex != rootMotionFrameIndex) { if (CullingMode != GPUSKinningCullingMode.CullCompletely) { rootMotionFrameIndex = frameIndex; DoRootMotion(frame_crossFade, 1 - blend_crossFade, false); DoRootMotion(frame, blend_crossFade, true); } } UpdateEvents(playingClip, frameIndex, frame_crossFade == null ? null : lastPlayedClip, frameIndex_crossFade); }
private void UpdateMaterial_Thread(float deltaTime) { int frameIndex = GetFrameIndex(); //动画片段(WrapMode.Once)播放完毕 if (lastPlayingClip == playingClip && lastPlayingFrameIndex == frameIndex) { resTime += deltaTime; //for (int i = 0; i < playerMonosCount; i++) // playerMonos[i].UpdateMaterial(deltaTime); return; } //记录上一帧播放的动画片段 lastPlayingClip = playingClip; //记录上一次播放的动画片段帧数(有可能跳帧) lastPlayingFrameIndex = frameIndex; blend_crossFade = 1; frameIndex_crossFade = -1; // 新建动画帧,用于crossFade GPUSkinningFrame frame_crossFade = null; if (IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { frameIndex_crossFade = GetCrossFadeFrameIndex(); frame_crossFade = lastPlayedClip.frames[frameIndex_crossFade]; blend_crossFade = CrossFadeBlendFactor(crossFadeProgress, crossFadeTime); } GPUSkinningFrame frame = playingClip.frames[frameIndex]; if (Visible || CullingMode == GPUSKinningCullingMode.AlwaysAnimate) { resTime += deltaTime; //计算临时变量 isRootMotionEnabled = playingClip.rootMotionEnabled && rootMotionEnabled; framePixelSegmentation = new Vector4(frameIndex, playingClip.pixelSegmentation, 0, 0); if (lastPlayedClip != null && frameIndex_crossFade >= 0) { framePixelSegmentation_Blend_CrossFade = new Vector4(frameIndex_crossFade, lastPlayedClip.pixelSegmentation, CrossFadeBlendFactor(crossFadeProgress, crossFadeTime)); rootMotionInv_Last = lastPlayedClip.frames[frameIndex_crossFade].RootMotionInv(anim.rootBoneIndex); } //Unity API无法在线程内调用 //UpdatePlayingData(framePixelSegmentation, rootMotionInv, isRootMotionEnabled, rootMotionInv_Last, framePixelSegmentation_Blend_CrossFade); } }
private void RestoreCustomClipData(GPUSkinningClip src, GPUSkinningClip dest) { if (src.events != null) { int totalFrames = (int)(dest.length * dest.fps); dest.events = new GPUSkinningAnimEvent[src.events.Length]; for (int i = 0; i < dest.events.Length; ++i) { GPUSkinningAnimEvent evt = new GPUSkinningAnimEvent(); evt.eventId = src.events[i].eventId; evt.frameIndex = Mathf.Clamp(src.events[i].frameIndex, 0, totalFrames - 1); dest.events[i] = evt; } } }
private void CreateTextureMatrix(string dir, GPUSkinningAnimation gpuSkinningAnim) { Texture2D texture = new Texture2D(gpuSkinningAnim.textureWidth, gpuSkinningAnim.textureHeight, TextureFormat.RGBAHalf, false, true); texture.filterMode = FilterMode.Point; texture.wrapMode = TextureWrapMode.Clamp; texture.anisoLevel = 0; Color[] pixels = texture.GetPixels(); int pixelIndex = 0; for (int clipIndex = 0; clipIndex < gpuSkinningAnim.clips.Length; ++clipIndex) { GPUSkinningClip clip = gpuSkinningAnim.clips[clipIndex]; GPUSkinningFrame[] frames = clip.frames; int numFrames = frames.Length; for (int frameIndex = 0; frameIndex < numFrames; ++frameIndex) { GPUSkinningFrame frame = frames[frameIndex]; Matrix4x4[] matrices = frame.matrices; int numMatrices = matrices.Length; for (int matrixIndex = 0; matrixIndex < numMatrices; ++matrixIndex) { Matrix4x4 matrix = matrices[matrixIndex]; pixels[pixelIndex++] = new Color(matrix.m00, matrix.m01, matrix.m02, matrix.m03); pixels[pixelIndex++] = new Color(matrix.m10, matrix.m11, matrix.m12, matrix.m13); pixels[pixelIndex++] = new Color(matrix.m20, matrix.m21, matrix.m22, matrix.m23); } } } texture.SetPixels(pixels); texture.Apply(); string savedPath = dir + "/GPUSKinning_Texture_" + animName + ".asset"; AssetDatabase.CreateAsset(texture, savedPath); WriteTempData(TEMP_SAVED_TEXTURE_PATH, savedPath); //string savedPath = dir + "/GPUSKinning_Texture_" + animName + ".bytes"; //using (FileStream fileStream = new FileStream(savedPath, FileMode.Create)) //{ // byte[] bytes = texture.GetRawTextureData(); // fileStream.Write(bytes, 0, bytes.Length); // fileStream.Flush(); // fileStream.Close(); // fileStream.Dispose(); //} //WriteTempData(TEMP_SAVED_TEXTURE_PATH, savedPath); }
private void SetNewPlayingClip(GPUSkinningClip clip) { lastPlayedClip = playingClip; lastPlayedTime = GetCurrentTime(); isPlaying = true; playingClip = clip; rootMotionFrameIndex = -1; time = 0; timeDiff = Random.Range(0, playingClip.length); //OnEventEnter if (this.OnAnimEventCallback != null) { this.OnAnimEventCallback(this, clip.name, 0); } }
private void UpdateClipEvent(GPUSkinningClip clip, int frameIndex) { if (this.OnAnimEventCallback != null && clip != null && clip.events != null && clip.events.Length > 0) { GPUSkinningAnimEvent[] events = clip.events; int numEvents = events.Length; for (int i = 0; i < numEvents; ++i) { if (events[i].frameIndex <= frameIndex && mCurClipEventCb) { mCurClipEventCb = false; OnAnimEventCallback(this, clip.name, events[i].eventId); break; } } } }
/// <summary> /// 设置当前播放的动画片段 /// </summary> /// <param name="newClip"> 新的动画片段 </param> private void SetCurPlayingClip(GPUSkinningClip newClip) { lastPlayedClip = playingClip; lastPlayedTime = GetCurrentTime(); isPlaying = true; playingClip = newClip; time = 0; //timeDiff = Random.Range(0, playingClip.length); if (isTimeDiff) { timeDiff = ((float)rnd.NextDouble()) * playingClip.length; } else { timeDiff = 0.0f; } }
private void SetSthAboutTexture(GPUSkinningAnimation gpuSkinningAnim) { int numPixels = 0; GPUSkinningClip[] clips = gpuSkinningAnim.clips; int numClips = clips.Length; for (int clipIndex = 0; clipIndex < numClips; ++clipIndex) { GPUSkinningClip clip = clips[clipIndex]; clip.pixelSegmentation = numPixels; GPUSkinningFrame[] frames = clip.frames; int numFrames = frames.Length; numPixels += gpuSkinningAnim.bones.Length * 3 /*treat 3 pixels as a float3x4*/ * numFrames; } CalculateTextureSize(numPixels, out gpuSkinningAnim.textureWidth, out gpuSkinningAnim.textureHeight); }
private void UpdateClipEvent(GPUSkinningClip clip, int frameIndex) { if (clip == null || clip.events == null || clip.events.Length == 0) { return; } GPUSkinningAnimEvent[] events = clip.events; int numEvents = events.Length; for (int i = 0; i < numEvents; ++i) { if (events[i].frameIndex == frameIndex && onAnimEvent != null) { onAnimEvent(this, events[i].eventId); break; } } }
public void UpdatePlayingData( MaterialPropertyBlock mpb, GPUSkinningClip playingClip, int frameIndex, GPUSkinningFrame frame, bool rootMotionEnabled, GPUSkinningClip lastPlayedClip, int frameIndex_crossFade, float crossFadeTime, float crossFadeProgress) { mpb.SetVector(shaderPorpID_GPUSkinning_FrameIndex_PixelSegmentation, new Vector4(frameIndex, playingClip.pixelSegmentation, 0, 0)); if (rootMotionEnabled) { Matrix4x4 rootMotionInv = frame.rootMotionInv; mpb.SetMatrix(shaderPropID_GPUSkinning_RootMotion, rootMotionInv); } if (IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { if (lastPlayedClip.rootMotionEnabled) { mpb.SetMatrix(shaderPropID_GPUSkinning_RootMotion_CrossFade, lastPlayedClip.frames[frameIndex_crossFade].rootMotionInv); } mpb.SetVector(shaderPorpID_GPUSkinning_FrameIndex_PixelSegmentation_Blend_CrossFade, new Vector4(frameIndex_crossFade, lastPlayedClip.pixelSegmentation, CrossFadeBlendFactor(crossFadeProgress, crossFadeTime))); } }
/// <summary> /// 获取动画片段的最后一帧索引数 /// </summary> /// <param name="clip"></param> /// <returns></returns> private int GetTheLastFrameIndex_WrapMode_Once(GPUSkinningClip clip) { return((int)(clip.length * clip.fps) - 1); }
public void StartSample() { if (isSampling) { return; } if (string.IsNullOrEmpty(animName.Trim())) { ShowDialog("Animation name is empty."); return; } if (rootBoneTransform == null) { ShowDialog("Please set Root Bone."); return; } if (animClips == null || animClips.Length == 0) { ShowDialog("Please set Anim Clips."); return; } animClip = animClips[samplingClipIndex]; if (animClip == null) { isSampling = false; return; } int numFrames = (int)(GetClipFPS(animClip, samplingClipIndex) * animClip.length); if (numFrames == 0) { isSampling = false; return; } smr = GetComponentInChildren <SkinnedMeshRenderer>(); if (smr == null) { ShowDialog("Cannot find SkinnedMeshRenderer."); return; } if (smr.sharedMesh == null) { ShowDialog("Cannot find SkinnedMeshRenderer.mesh."); return; } Mesh mesh = smr.sharedMesh; if (mesh == null) { ShowDialog("Missing Mesh"); return; } samplingFrameIndex = 0; gpuSkinningAnimation = anim == null?ScriptableObject.CreateInstance <GPUSkinningAnimation>() : anim; gpuSkinningAnimation.name = animName; if (anim == null) { gpuSkinningAnimation.guid = System.Guid.NewGuid().ToString(); } List <GPUSkinningBone> bones_result = new List <GPUSkinningBone>(); CollectBones(bones_result, smr.bones, mesh.bindposes, null, rootBoneTransform, 0); GPUSkinningBone[] newBones = bones_result.ToArray(); GenerateBonesGUID(newBones); if (anim != null) { RestoreCustomBoneData(anim.bones, newBones); } gpuSkinningAnimation.bones = newBones; gpuSkinningAnimation.rootBoneIndex = 0; int numClips = gpuSkinningAnimation.clips == null ? 0 : gpuSkinningAnimation.clips.Length; int overrideClipIndex = -1; for (int i = 0; i < numClips; ++i) { if (gpuSkinningAnimation.clips[i].name == animClip.name) { overrideClipIndex = i; break; } } gpuSkinningClip = new GPUSkinningClip(); gpuSkinningClip.name = animClip.name; gpuSkinningClip.fps = GetClipFPS(animClip, samplingClipIndex); gpuSkinningClip.length = animClip.length; gpuSkinningClip.wrapMode = wrapModes[samplingClipIndex]; gpuSkinningClip.frames = new GPUSkinningFrame[numFrames]; gpuSkinningClip.rootMotionEnabled = rootMotionEnabled[samplingClipIndex]; gpuSkinningClip.individualDifferenceEnabled = individualDifferenceEnabled[samplingClipIndex]; if (gpuSkinningAnimation.clips == null) { gpuSkinningAnimation.clips = new GPUSkinningClip[] { gpuSkinningClip }; } else { if (overrideClipIndex == -1) { List <GPUSkinningClip> clips = new List <GPUSkinningClip>(gpuSkinningAnimation.clips); clips.Add(gpuSkinningClip); gpuSkinningAnimation.clips = clips.ToArray(); } else { GPUSkinningClip overridedClip = gpuSkinningAnimation.clips[overrideClipIndex]; RestoreCustomClipData(overridedClip, gpuSkinningClip); gpuSkinningAnimation.clips[overrideClipIndex] = gpuSkinningClip; } } SetCurrentAnimationClip(); PrepareRecordAnimator(); isSampling = true; }
//判断是否应用CrossFadeBlending public bool IsCrossFadeBlending(GPUSkinningClip lastPlayedClip, float crossFadeTime, float crossFadeProgress) { return(lastPlayedClip != null && crossFadeTime > 0 && crossFadeProgress <= crossFadeTime); }
private void UpdateEvents(GPUSkinningClip playingClip, int playingFrameIndex, GPUSkinningClip corssFadeClip, int crossFadeFrameIndex) { UpdateClipEvent(playingClip, playingFrameIndex); UpdateClipEvent(corssFadeClip, crossFadeFrameIndex); }
/// <summary> /// 根据当前动画片段播放状态设置Material /// fzy remak:CPU资源消耗过多 /// </summary> /// <param name="deltaTime">本帧Update消耗的时间</param> private void UpdateMaterial(float deltaTime) { //Profiler.BeginSample("UpdateMaterial.Other"); int frameIndex = GetFrameIndex(); //动画片段(WrapMode.Once)播放完毕 if (lastPlayingClip == playingClip && lastPlayingFrameIndex == frameIndex) { //res.Update(deltaTime); resTime += deltaTime; //for (int i = 0; i < playerMonosCount; i++) // playerMonos[i].UpdateMaterial(deltaTime); return; } //记录上一帧播放的动画片段 lastPlayingClip = playingClip; //记录上一次播放的动画片段帧数(有可能跳帧) lastPlayingFrameIndex = frameIndex; blend_crossFade = 1; frameIndex_crossFade = -1; // 新建动画帧,用于crossFade GPUSkinningFrame frame_crossFade = null; if (IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { frameIndex_crossFade = GetCrossFadeFrameIndex(); frame_crossFade = lastPlayedClip.frames[frameIndex_crossFade]; blend_crossFade = CrossFadeBlendFactor(crossFadeProgress, crossFadeTime); } GPUSkinningFrame frame = playingClip.frames[frameIndex]; //Profiler.EndSample(); //模型可以被看见(Culling)或者CullingMode为AlwaysAnimate if (Visible || CullingMode == GPUSKinningCullingMode.AlwaysAnimate) { //author version //res.Update(deltaTime); resTime += deltaTime; //fzy remark:不需要每帧调用,已在初始化时设置属性 //for (int i = 0; i < playerMonosCount; i++) //{ // playerMonos[i].UpdateMaterial(deltaTime); //} /*author version * res.UpdatePlayingData( * mpb, playingClip, frameIndex, frame, playingClip.rootMotionEnabled && rootMotionEnabled, * lastPlayedClip, GetCrossFadeFrameIndex(), crossFadeTime, crossFadeProgress * ); * mr.SetPropertyBlock(mpb);*/ //if (Time.frameCount % updatePreFrame != updateRemark) return; //Profiler.BeginSample("UpdatePlayingData"); //计算临时变量 isRootMotionEnabled = playingClip.rootMotionEnabled && rootMotionEnabled; framePixelSegmentation = new Vector4(frameIndex, playingClip.pixelSegmentation, 0, 0); rootMotionInv = frame.RootMotionInv(anim.rootBoneIndex); if (lastPlayedClip != null && frameIndex_crossFade >= 0) { framePixelSegmentation_Blend_CrossFade = new Vector4(frameIndex_crossFade, lastPlayedClip.pixelSegmentation, CrossFadeBlendFactor(crossFadeProgress, crossFadeTime)); rootMotionInv_Last = lastPlayedClip.frames[frameIndex_crossFade].RootMotionInv(anim.rootBoneIndex); } //设置动画播放的Material数据 //UpdatePlayingData(framePixelSegmentation, rootMotionInv, isRootMotionEnabled, rootMotionInv_Last, framePixelSegmentation_Blend_CrossFade); UpdatePlayingData(); //Profiler.EndSample(); //bone.isExposed //UpdateJoints(frame); } //Profiler.BeginSample("RootMotion"); /* * if (playingClip.rootMotionEnabled && rootMotionEnabled && frameIndex != rootMotionFrameIndex) * { * if (CullingMode != GPUSKinningCullingMode.CullCompletely) * { * rootMotionFrameIndex = frameIndex; * DoRootMotion(frame_crossFade, 1 - blend_crossFade, false); * DoRootMotion(frame, blend_crossFade, true); * } * }*/ //Profiler.EndSample(); //UpdateEvents(playingClip, frameIndex, frame_crossFade == null ? null : lastPlayedClip, frameIndex_crossFade); }
/// <summary> /// 获取动画片段当前帧的索引(注意考虑循环) /// </summary> /// <param name="clip"> 当前动画片段 </param> /// <param name="time"> 当前动画片段已播放时间 </param> /// <returns></returns> private int GetFrameIndex_WrapMode_Loop(GPUSkinningClip clip, float time) { return((int)(time * clip.fps) % (int)(clip.length * clip.fps)); }
/// <summary> /// 根据当前动画片段播放状态设置Material /// fzy remak:CPU资源消耗过多 /// </summary> /// <param name="deltaTime">本帧Update消耗的时间</param> /// <param name="currMtrl">当前使用的Material</param> private void UpdateMaterial(float deltaTime, GPUSkinningMaterial currMtrl) { int frameIndex = GetFrameIndex(); //Profiler.BeginSample("PlayerResources.Update"); //动画片段(WrapMode.Once)播放完毕 if (lastPlayingClip == playingClip && lastPlayingFrameIndex == frameIndex) { res.Update(deltaTime, currMtrl); return; } //Profiler.EndSample(); //记录上一帧播放的动画片段 lastPlayingClip = playingClip; //记录上一次播放的动画片段帧数(有可能跳帧) lastPlayingFrameIndex = frameIndex; float blend_crossFade = 1; int frameIndex_crossFade = -1; // 新建动画帧,用于crossFade GPUSkinningFrame frame_crossFade = null; //Profiler.BeginSample("PlayerResources.CrossFadeBlending"); if (res.IsCrossFadeBlending(lastPlayedClip, crossFadeTime, crossFadeProgress)) { frameIndex_crossFade = GetCrossFadeFrameIndex(); frame_crossFade = lastPlayedClip.frames[frameIndex_crossFade]; blend_crossFade = res.CrossFadeBlendFactor(crossFadeProgress, crossFadeTime); } //Profiler.EndSample(); //Profiler.BeginSample("PlayerResources.Update"); GPUSkinningFrame frame = playingClip.frames[frameIndex]; //模型可以被看见(Culling)或者CullingMode为AlwaysAnimate if (Visible || CullingMode == GPUSKinningCullingMode.AlwaysAnimate) { res.Update(deltaTime, currMtrl); res.UpdatePlayingData( mpb, playingClip, frameIndex, frame, playingClip.rootMotionEnabled && rootMotionEnabled, lastPlayedClip, GetCrossFadeFrameIndex(), crossFadeTime, crossFadeProgress ); mr.SetPropertyBlock(mpb); //bone.isExposed UpdateJoints(frame); } //Profiler.EndSample(); //Profiler.BeginSample("RootMotion"); if (playingClip.rootMotionEnabled && rootMotionEnabled && frameIndex != rootMotionFrameIndex) { if (CullingMode != GPUSKinningCullingMode.CullCompletely) { rootMotionFrameIndex = frameIndex; DoRootMotion(frame_crossFade, 1 - blend_crossFade, false); DoRootMotion(frame, blend_crossFade, true); } } //Profiler.EndSample(); UpdateEvents(playingClip, frameIndex, frame_crossFade == null ? null : lastPlayedClip, frameIndex_crossFade); }