Unity基础包 FirstPersonController下的CurveControlledBob和LerpContolledBob 脚本研究

来源:互联网 发布:美国大学不要面试知乎 编辑:程序博客网 时间:2024/06/10 15:22

版本:unity 5.3.4  语言:C#

 

FirstPersonController的最后两个脚本,代码量不是很多,就一起贴上来了。

 

虽然这最后的两个脚本是比较容易的,不过它们跟之前的脚本融合起来,形成的一种分层而治的思想很有意思。

 

这跟没有锚点的话就多加一层的思想是类似的。

 

下面是脚本的解析,首先是控制头部镜头晃动的CurveControlledBob:

// 曲线摇晃控制器// 该脚本主要处理头部的摇动,会在FirstPersonController脚本的FixedUpdate函数中调用该类中的DoHeadBob,获取镜头的偏移[Serializable]public class CurveControlledBob{    public float HorizontalBobRange = 0.33f;    //水平和垂直的摇动范围    public float VerticalBobRange = 0.33f;    public AnimationCurve Bobcurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(0.5f, 1f),                                                        new Keyframe(1f, 0f), new Keyframe(1.5f, -1f),                                                        new Keyframe(2f, 0f)); // 摇动曲线,默认为正弦函数    public float VerticaltoHorizontalRatio = 1f;    //垂直跟水平的比例    private float m_CyclePositionX; //循环的x、y坐标,用于计算当前摇动曲线在哪个位置    private float m_CyclePositionY;    private float m_BobBaseInterval;    //摇动的步伐间隔,单位是米    private Vector3 m_OriginalCameraPosition;   //Camera的起源位置    private float m_Time;    // 设置Camera和步伐间隔,然而这边不像FOVKick做个null的判断    public void Setup(Camera camera, float bobBaseInterval)    {        m_BobBaseInterval = bobBaseInterval;    //将步伐间隔赋值,这边就是跨一步的间隔,脚本默认设置了5米        m_OriginalCameraPosition = camera.transform.localPosition;  //获取一次Camera的基础位置        // 获取摇动曲线一次的总时间,即这边最后一个key的时间        m_Time = Bobcurve[Bobcurve.length - 1].time;    }    // 摇动    public Vector3 DoHeadBob(float speed)    {        // 计算Camera新的位置,按照默认位置,相当于镜头右上到左下的的来回移动,产生一个头部晃动的效果        float xPos = m_OriginalCameraPosition.x + (Bobcurve.Evaluate(m_CyclePositionX)*HorizontalBobRange);        float yPos = m_OriginalCameraPosition.y + (Bobcurve.Evaluate(m_CyclePositionY)*VerticalBobRange);        // 增加循环x、y坐标        m_CyclePositionX += (speed*Time.deltaTime)/m_BobBaseInterval;        m_CyclePositionY += ((speed*Time.deltaTime)/m_BobBaseInterval)*VerticaltoHorizontalRatio;   //VerticaltoHorizontalRatio默认设置为1,但如果大于1则垂直比水平摇晃的快,反之慢,只是缩小或增大一次摇晃的间隔距离        // 超过设置的一次摇晃时间后重置        if (m_CyclePositionX > m_Time)        {            m_CyclePositionX = m_CyclePositionX - m_Time;        }        if (m_CyclePositionY > m_Time)        {            m_CyclePositionY = m_CyclePositionY - m_Time;        }        return new Vector3(xPos, yPos, 0f); //返回镜头的位置    }}


以上脚本主要实现了一个曲线的控制,下面的插值控制只是单坐标轴的LerpContolledBob,那就更容易了:

// 插值摇晃控制器// 插值摇动的控制器,这个只要角色着陆就会开始计算,Update中调用DoBobCycle,FixedUpdate中调用Offset设置Camera的y坐标[Serializable]public class LerpControlledBob{    public float BobDuration;   //摇晃到最大值的时间,默认这边是0.2,而完成一次摇晃需要一次下沉和上升,所以是0.4秒    public float BobAmount; //摇晃的最大值    private float m_Offset = 0f;    //当前偏移值    // 提供偏移值供上层脚本使用    public float Offset()    {        return m_Offset;    }    // 计算一次偏移值    public IEnumerator DoBobCycle()    {        // 使用Camera轻微的下沉一些,以模拟人着陆的效果        float t = 0f;        while (t < BobDuration)        {            m_Offset = Mathf.Lerp(0f, BobAmount, t/BobDuration);    //根据时间,进行一个插值运算,计算当前需要下沉的y坐标值            t += Time.deltaTime;            yield return new WaitForFixedUpdate();  //等待下一次FixedUpate更新完毕        }        // 跟上面是一个相反的操作        t = 0f;        while (t < BobDuration)        {            m_Offset = Mathf.Lerp(BobAmount, 0f, t/BobDuration);            t += Time.deltaTime;            yield return new WaitForFixedUpdate();        }        m_Offset = 0f;  //归零    }}

至此FirstPersonController脚本全部讲解完毕了。

 

总结:

第一人称控制的预制体中分为两层:FPSController角色层、FirstPersonCharacter镜头层。

FirstPersonController主脚本控制Character Controller组件,用以控制角色层的Position;

MouseLock脚本控制角色层的y轴旋转和镜头层的x轴旋转;

FovKick和这次两个摇晃脚本控制镜头层的x、y轴的移动(晃动)。



0 0