您的位置:首页 > 移动开发 > Unity3D

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

2016-11-08 14:22 381 查看
版本: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轴的移动(晃动)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: