IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【Unity】使Cinemachine立即完成Damp、当前Blend和即将发生的Blend和Damp -> 正文阅读

[游戏开发]【Unity】使Cinemachine立即完成Damp、当前Blend和即将发生的Blend和Damp

【Unity】使Cinemachine立即完成Damp、当前Blend和即将发生的Blend和Damp

游戏中很多时候都会动态生成玩家角色,这时会希望相机立即定位到刚刚生成的玩家角色,不要有从远处将镜头Blend过来或者Damp的过程,但Cinemachine直到2.8.0版本都没有提供立即完成Blend的方法。这里对Cinemachine的源码做了些微小的改动,使其能够立即完成Damp、当前Blend和即将发生的Blend。

目前版本的Cinemachine已经含有使相机立即完成Damp的功能,只需要将 cinemachineVirtualCameraBase.PreviousStateIsValid 设为 false 即可让虚拟相机在下一帧立即完成Damp。但将Damp延迟到下一帧完成,有时可能导致画面跳变,因此下面的完成Blend的代码对其进行了整合,可以使Damp和Blend都在调用方法的当帧完成。

首先需要将Cinemachine的源码从 Library 文件夹移到 Packages 文件夹中,然后将 CinemachineBrain 类改为 partial 类型,之后的修改都不会再动到Cinemachine的核心源码。

接下来新建一个 partialCinemachineBrain 类,在其中填充完成Blend和Damp的代码。下面贴出的源代码中已经包含了主要步骤的注释,因此这里不再描述细节,只说一些使用限制:下面的代码是基于Cinemachine 2.6.5版本写的,依赖了从这个版本才加入的 ManualUpdate() 方法,如果是低版本的Cinemachine,将 ManualUpdate() 方法换成 LateUpdate() 应该也可以生效(我没有测试过低版本)。

源代码

namespace Cinemachine
{
    public partial class CinemachineBrain
    {
        /// <summary>
        /// Call this method explicitly from an external script to update the virtual cameras
        /// and position the main camera, if the UpdateMode is set to ManualUpdate.
        /// For other update modes, this method is called automatically, and should not be
        /// called from elsewhere.
        /// </summary>
        public void ManualUpdate(float deltaTime)
        {
            if (m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate)
                UpdateFrame0(deltaTime);

            ComputeCurrentBlend(ref mCurrentLiveCameras, 0);

            if (m_UpdateMethod == UpdateMethod.FixedUpdate)
            {
                // Special handling for fixed update: cameras that have been enabled
                // since the last physics frame must be updated now
                if (m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate)
                {
                    CinemachineCore.Instance.CurrentUpdateFilter = CinemachineCore.UpdateFilter.Fixed;
                    if (SoloCamera == null)
                        mCurrentLiveCameras.UpdateCameraState(
                            DefaultWorldUp, GetEffectiveDeltaTime(true));
                }
            }
            else
            {
                CinemachineCore.UpdateFilter filter = CinemachineCore.UpdateFilter.Late;
                if (m_UpdateMethod == UpdateMethod.SmartUpdate)
                {
                    // Track the targets
                    UpdateTracker.OnUpdate(UpdateTracker.UpdateClock.Late);
                    filter = CinemachineCore.UpdateFilter.SmartLate;
                }
                UpdateVirtualCameras(filter, deltaTime);
            }

            // Choose the active vcam and apply it to the Unity camera
            if (m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate)
                ProcessActiveCamera(deltaTime);
        }

        /// <summary>
        /// Complete current active blend immediately.
        /// </summary>
        /// <param name="completeDamp">If true, will also complete aim and body damp.</param>
        public void CompleteCurrentBlend(bool completeDamp = true)
        {
            if (mFrameStack.Count == 0)
            {
                return;
            }

            // Complete current blend
            mFrameStack[0].blend.Duration = 0;
            ManualUpdate();

            // Use -1 to prevent dolly camera finds closest point
            var deltaTime = -1;
            CinemachineCore.UpdateFilter filter = CinemachineCore.UpdateFilter.Late;
            if (m_UpdateMethod == UpdateMethod.SmartUpdate)
            {
                // Track the targets
                UpdateTracker.OnUpdate(UpdateTracker.UpdateClock.Late);
                filter = CinemachineCore.UpdateFilter.SmartLate;
            }
            UpdateVirtualCameras(filter, deltaTime);

            // Choose the active vcam and apply it to the Unity camera
            if (m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate)
                ProcessActiveCamera(deltaTime);

            // Complete damp
            if (completeDamp && ActiveVirtualCamera is CinemachineVirtualCameraBase vcam)
            {
                vcam.PreviousStateIsValid = false;
                ManualUpdate();
            }
        }

        /// <summary>
        /// Complete incoming active blend immediately if the incoming blend is between camA and camB or contains camA or camB.
        /// </summary>
        /// <param name="appointCamera">If not null, will only take effect when top priority camera equals appointCamera.</param>
        /// <param name="completeDamp">If true, will also complete aim and body damp.</param>
        public void CompleteIncomingBlend(CinemachineVirtualCameraBase appointCamera = null, bool completeDamp = true)
        {
            if (mFrameStack.Count == 0)
            {
                return;
            }

            if (appointCamera)
            {
                appointCamera.MoveToTopOfPrioritySubqueue();
            }

            // Find new active camera
            var topCam = ActiveVirtualCamera as CinemachineVirtualCameraBase;
            int numCameras = CinemachineCore.Instance.VirtualCameraCount;
            for (int i = 0; i < numCameras; ++i)
            {
                var cam = CinemachineCore.Instance.GetVirtualCamera(i);
                if (cam.gameObject.scene != gameObject.scene)
                {
                    continue;
                }

                if (!topCam || topCam.gameObject.scene != gameObject.scene || topCam.Priority < cam.Priority)
                {
                    topCam = cam;
                }

                // When call MoveToTopOfPrioritySubqueue() and ManualUpdate(),
                // cameras in mActiveCameras may out of order, so do not break
                //if (topCam.Priority >= cam.Priority)
                //{
                //    break;
                //}
            }
            if (topCam == null || (appointCamera && appointCamera != topCam))
            {
                return;
            }

            // Trigger virtual cameras priority queen update
            topCam.MoveToTopOfPrioritySubqueue();

            // Update frame stack
            UpdateFrame0(0);

            // Complete blend
            CompleteCurrentBlend(completeDamp);
        }
    }

    public static class CinemachineCameraExtension
    {
        /// <summary>
        /// Complete body and aim damp.
        /// </summary>
        /// <param name="cmCam"></param>
        public static void CompleteDamps(this ICinemachineCamera cmCam)
        {
            if (cmCam is CinemachineVirtualCameraBase vcam)
            {
                vcam.PreviousStateIsValid = false;
            }
        }
    }
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-07-17 12:15:58  更:2021-07-17 12:16:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 14:44:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码