各位朋友,大家好,欢迎大家关注我的博客,我是秦元培,我的博客地址是http://qinyuanpei.com。今天我们来说说在Unity3D中如何实现屏幕震动效果。屏幕震动效果在某些游戏场景中,对于提升游戏的真实感有较大的帮助。比如在《水果忍者》这个游戏中,当玩家碰到炸弹的时候屏幕会出现强烈的震动效果,同时手机自身发出震动,这样就大大地增强了玩家在碰到炸弹这一瞬间的游戏体验。
再比如《Swordigo》这个游戏是博主一直比较喜欢的一款手机游戏,在这个游戏中玩家将扮演一个少年剑客,跨过重重阻隔、经历种种磨难,收集剑柄、剑刃、剑心最终打败魔王。这是一个完完全全的RPG游戏,在游戏当中玩家将会在不同风格的迷宫中探索、然后消灭各种各样的敌人,是一款相当出色的手机游戏,如果大家感兴趣的话,可以去下载下来玩一玩哦!在这个游戏中有一个火属性的敌人,它会向玩家投掷一种火球,当火球接触到地面时,整个地面会发生剧烈的震动,这同样是为了体现出一种真实的游戏体验。
我们知道在3D世界里空间的大小是可以无限延伸的,而我们的视线所能触及到的空间则是相对有限的。我们常常说要开阔眼界,因为开阔眼界能够让我们看到的内容更多。那么这句话在游戏世界里该如何解释呢?我们知道在3D世界里摄像机扮演着和人的眼睛相同的角色,因此我们在3D世界里能够看到多少内容完全取决于摄像机。好了,了解了这一点,我们大致可以找到两类实现屏幕震动的方法:
场景固定的情况下震动摄像机
第一类方法实现起来较为简单,而且这种方法更容易让人接受。因为我们平时在拍照或者摄像的过程中难免会出现因为拍摄者身体或者手部发生抖动而引起的画面震动效果,因此现在的摄像设备如DV或者数码相机甚至是智能手机,都会有图像防抖动功能。这就是第一类实现屏幕震动的方法在生活中的现实例子,因此基于这种思路,实现屏幕震动只要让相机震动即可。
摄像机固定的情况下震动场景
第二类方法是对真实世界的一种模拟,主要模拟的是地球上的地震灾害。这种方式主要运用在3D游戏中,通过使游戏中的虚拟地面发生震动,来达到一种使画面震动的效果。可是因为这种方法可能涉及到场景中的其它物体以及主要运用在3D游戏这一局限性,因此在2D和3D游戏中主要通过第一类方法来实现屏幕震动效果。
项目实例
这里以在Unity3D引擎下实现《水果忍者》这个游戏为例,这是博主最近在研究的一个项目吧。在这个游戏中档玩家碰到炸弹的时候是有一个屏幕震动的效果的,所以这里我们就以这个功能的实现为例来讲解今天的内容吧!
首先给出第一种方法,通过调整相机的Rect视口范围实现屏幕震动,该方法是博主在这个游戏中使用的方法。
/// 在这个脚本中主要实现的功能是相机的震动效果
/// 时间:2015年4月8日
///是否震动相机
public bool isShake=false;
/// <summary>
/// 震动间隔
/// </summary>
public float ShakeTime=1.0f;
/// <summary>
/// 震动增量
/// </summary>
public float ShakeDelta=0.1f;
/// <summary>
/// 记录当前帧时间
/// </summary>
private float frameTime=0.0f;
/// <summary>
/// FPS
/// </summary>
private float fps=20.0f;
/// <summary>
/// 从开始震动计时
/// </summary>
private float time=0.0f;
/// <summary>
/// 相机震动的方法
/// </summary>
private void ShakeCamera()
{
if(isShake){
time+=Time.deltaTime;
if(ShakeTime>0){
ShakeTime-=Time.deltaTime;
if(ShakeTime<=0){
//重置相机
transform.camera.rect=new Rect(0.0f,0.0f,1.0f,1.0f);
//重置震动间隔
ShakeTime=1.0f;
}else{
//为了使相机震动平稳而均匀设计一个帧时间
frameTime+=Time.deltaTime;
//只有帧时间大于FPS时震动
if(frameTime>=1/fps){
//重置帧时间
frameTime=0;
//随机调整相机矩形
transform.camera.rect =
new Rect(0.1f * (-ShakeDelta + 2.0f * Random.value),
0.1f * (-ShakeDelta + 2.0f * Random.value)
, 1.0f, 1.0f);
}
}
}
}
当然,我们可以采取简单粗暴的办法,让相机的位置不断地改变即可,因此我们可以采用的第二种方法是:
public bool isShake=false;
//定义相机的震幅
private float shakeDelta=0.75f;
//震动间隔
public float ShakeTime=1.0f;
void Update ()
{
if(isShake)
{
if(ShakeTime>0)
{
ShakeTime-=Time.deltaTime;
if(ShakeTime<=0){
ShakeTime=1.0f;
transform.position=new Vector3(0,0,transform.position.z);
}else{
transform.position=new Vector3(-shakeDelta+ 1 * Random.value,
-shakeDelta+ 1 * Random.value,transform.position.z);
}
}
}
}
}
不过从实际的效果对比来看,第一种实现方法要比第二种要好些,或许是博主自己写的不好吧,哈哈。好了,现在我们来看看实际的效果吧!
如果大家有更好的方法或者思路,欢迎大家在文章下面留言,今天的内容就是这样了,希望大家喜欢!