纳金网

标题: 第一人称射击游戏(中级教程)(三) [打印本页]

作者: 会飞的鱼    时间: 2011-12-13 14:20
标题: 第一人称射击游戏(中级教程)(三)






爆炸(Explosions)

你可能已经注意到了,发射的火箭弹发生碰撞时并没有爆炸产生。下面我们来添加爆炸效果。

把标准资源包中粒子文件夹下的Small Explosion拖拽给火箭弹预制的外部变量Explosion

我们仍然需要定义爆炸的行为,脚本Explosion-Simple内容如下:
var explosionRadius = 5.0;

var explosionPower = 10.0;

var explosionDamage = 100.0;

var explosionTime = 1.0;

function Start () {

var explosionPosition = transform.position;

var colliders : Collider[] = Physics.OverlapSphere (explosionPosition,

explosionRadius);
返回球半径内碰撞器数列
for (var hit in colliders) {

if (!hit)

continue;

if (hit.rigidbody)

{

hit.rigidbody.AddExplosionForce(explosionPower,

explosionPosition, explosionRadius, 3.0);
这部分对爆炸半径内的所有刚体属性物体一个向上的作用力

这样会使爆炸效果看上去很棒!
var closestPoint = hit.rigidbody.ClosestPointOnBounds(explosionPosition);

var distance = Vector3.Distance(closestPoint, explosionPosition);

// The hit points we apply fall decrease with distance from the hit point

var hitPoints = 1.0 - Mathf.Clamp01(distance / explosionRadius);

hitPoints *= explosionDamage;
这部分计算爆炸对每个刚体属性物体造成的毁伤程度。并且毁伤程度随着距爆炸中心地距离而减少。
// Tell the rigidbody or any other script attached to the hit object

// how much damage is to be applied!

hit.rigidbody.SendMessageUpwards("ApplyDamage", hitPoints,

SendMessageOptions.DontRequireReceiver);
这部分是对刚体物体传递一个伤害信息。
}

}

// stop emitting ?

if (particleEmitter) {

particleEmitter.emit = true;

yield WaitForSeconds(0.5);

particleEmitter.emit = false;

}

// destroy the explosion

Destroy (gameObject, explosionTime);

}
把脚本Explosion-Simple付给Small Explosion预制体

这个爆炸脚本可以应用在任何需要爆炸效果的游戏中,要得到特定的效果,只需修改下面几个参数即可:

explosionPower:爆炸威力,移动炸点周围物体的力的大小。

explosionDamage:爆炸造成的毁伤点数。

explosionRadius:爆炸效果范围大小。
这个爆炸脚本与先前初级教程中的那个脚本非常类似,主要的区别就是有了毁伤点数这部分内容。通过变量explosionDamage设置基于距离远近的毁伤点数,外部边缘的物体毁伤程度小于爆炸中心位置的物体。
这意味着现在一个爆炸可以对炸点周围的物体造成伤害。后面我们将讨论如何应用毁伤点数。

运行游戏
机枪(Machine Gun)

类似机枪这样的武器,发射速度比火箭筒快,但造成的伤害小。

创建一个空游戏物体,命名为“机枪”。层级栏中,把这个物体拖放设为“武器”的子物体。

把(Object/weapons/machineGun)机枪模型增加到“机枪”空游戏物体中。

把脚本MachineGun赋予“机枪”游戏物体。

在机枪物体参数栏的变量Muzzle Flash栏中把muzzle_flash(机枪的子物体)付给这个变量。

机枪的脚本如下MachineGun:
var range = 100.0;

var fireRate = 0.05;

var force = 10.0;

var damage = 5.0;

var bulletsPerClip = 40;

var clips = 20;

var reloadTime = 0.5;

private var hitParticles : ParticleEmitter;

var muzzleFlash : Renderer;

private var bulletsLeft : int = 0;

private var nextFireTime = 0.0;

private var m_LastFrameShot = -1;

function Start ()

{

hitParticles = GetComponentInChildren(ParticleEmitter);

// We don't want to emit particles all the time, only when we hit something.

if (hitParticles)

hitParticles.emit = false;

bulletsLeft = bulletsPerClip;

}
函数Start其实就是用来初始化粒子发射器的(bullet spark),设定它开始时为关闭状态。
function LateUpdate()

{

if (muzzleFlash)

{

// We shot this frame, enable the muzzle flash

if (m_LastFrameShot == Time.frameCount)

{

muzzleFlash.transform.localRotation =

Quaternion.AngleAxis(Random.Range(0, 359), Vector3.forward);

muzzleFlash.enabled = true;

if (audio)

{

if (!audio.isPlaying)

audio.Play();

audio.loop = true;

}

}

// We didn't, disable the muzzle flash

else

{

muzzleFlash.enabled = false;

enabled = false;

// Play sound

if (audio)

{

audio.loop = false;

}

}

}

}
执行Update函数后,会自动执行LateUpdate函数。注意,Update函数是在脚本PlayWeapons中调用的,这个脚本配置给了Weapons游戏物体(机枪的父物体)。一般而言,当你想某些效果是在Update函数中调用而相应的效果出现在LateUpdate函数中,就使用LateUpdate函数。例如这个例子,判断玩家“是否开火”(if firing)是在Update函数中,在LateUpdate函数中应用火花效果(muzzle flash)。
function Fire ()

{

if (bulletsLeft == 0)

return;

// If there is more than one bullet between the last and this frame

// Reset the nextFireTime

if (Time.time - fireRate > nextFireTime)

nextFireTime = Time.time - Time.deltaTime;

// Keep firing until we used up the fire time

while( nextFireTime < Time.time && bulletsLeft != 0)

{

FireOneShot();

nextFireTime += fireRate;

}

}
Fire函数是基于机枪发射速度来判断玩家是否能开火。
function FireOneShot ()

{

var direction = transform.TransformDirection(Vector3.forward);

var hit : RaycastHit;

// Did we hit anything?

if (Physics.Raycast (transform.position, direction, hit, range))

{

// Apply a force to the rigidbody we hit

if (hit.rigidbody)

hit.rigidbody.AddForceAtPosition(force * direction, hit.point);

// Place the particle system for spawing out of place where we hit the surface!

// And spawn a couple of particles

if (hitParticles)

{

hitParticles.transform.position = hit.point;

hitParticles.transform.rotation =

Quaternion.FromToRotation(Vector3.up, hit.normal);

hitParticles.Emit();

}

// Send a damage message to the hit object

hit.collider.SendMessageUpwards("ApplyDamage", damage,

SendMessageOptions.DontRequireReceiver);

}

bulletsLeft--;

// Register that we shot this frame,

// so that the LateUpdate function enabled the muzzleflash renderer for one frame

m_LastFrameShot = Time.frameCount;

enabled = true;

// Reload gun in reload Time

if (bulletsLeft == 0)

Reload();

}
函数FireOneShot运行时,会在FPS控制器前方发射出一条射线来判断子弹是否击中了什么东西。我们将把子弹的射击距离限定在一定范围内。

如果射线射到某个刚体物体上,就会在那个点上对这个刚体物体产生一定的作用力(因为是机枪,所以作用力很小)。然后在这个点的位置再产生一个火花。粒子发射器方向也会变为沿着这个点的法线方向。

然后,通过对被击中的物体发送一个毁伤信息来对它应用毁伤效果。
function Reload () {

// Wait for reload time first - then add more bullets!

yield WaitForSeconds(reloadTime);

// We have a clip left reload

if (clips > 0)

{

clips--;

bulletsLeft = bulletsPerClip;

}

}

function GetBulletsLeft () {

return bulletsLeft;

}
函数Reload是来装载一个弹夹(还有弹夹的话)。装载时间可以在参数栏中进行调节。
设置粒子发射器(Configuring the particle emitter)

机枪在其子弹与其他刚体物体发生碰撞时应该有个小火花的效果,下面我们来创建它:

从Standard Assets/Particales文件夹下,把Sparks预制拖放到层级栏中,使其成为machineGun的子物体(不是MachineGun)

搞定!运行游戏。不要忘了1和2是切换武器的。



由 lsermao  发表
作者: 晃晃    时间: 2012-1-23 23:27
日出遇爱,日落见情;愿所有的吉星呵护着你!时时吉祥,刻刻平安 愿新的一年里,你位高权重责任轻,钱多事少离家近,每日睡到大天亮,工资领到手抽筋,手下花钱你收礼,别人加班你加薪!

作者: tc    时间: 2012-4-18 23:22
灌水。。。

作者: 奇    时间: 2012-6-6 23:26
既来之,则看之!

作者: 奇    时间: 2012-6-25 23:19
读铁系缘分,顶铁系友情

作者: tc    时间: 2012-9-10 08:36
再看一看,再顶楼主

作者: 奇    时间: 2012-10-5 23:25
俺是新人,这厢有礼了!

作者: C.R.CAN    时间: 2012-12-3 23:25
好可爱的字,学习了





欢迎光临 纳金网 (http://rs.narkii.com/club/) Powered by Discuz! X2.5