12 第1页 | 共2 页下一页
返回列表 发新帖
查看: 4444|回复: 17
打印 上一主题 下一主题

第一人称射击游戏(中级教程)(四)

[复制链接]

5552

主题

2

听众

8万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
11

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2011-12-13 14:22:30 |只看该作者 |倒序浏览
生命值(Hit Points)

脚本Explosion和MachineGun已经展示了当物体被击中时(火箭弹或子弹),如何设定毁伤程度,并把伤害值传给周围的游戏物体。但是,游戏物体并不知道这些值意味着什么。

游戏物体的健康程度可以通过使用变量hitPoints来进行跟踪。每个物体都有自己的生命值(根据物体自身的生命强度)。每个游戏物体也应该对伤害有所反应并使用了ApplyDamage()函数(注意,这正是Explosion和MachineGun脚本中调用的用来产生伤害函数)。这个函数将会根据伤害程度降低游戏物体的生命值,并在生命值为零时调用其它函数来产生一定的变化(例如死亡或爆炸)。

下一节我们来看看如何使用生命值(hitPoints)和函数ApplyDamage()
爆炸的桶子(Exploding Barrels)

下面的脚本是通用脚本,所以可以作为一个部件加载在任何可以产生毁伤的物体上。DamageReceiver脚本代码如下:
var hitPoints = 100.0;

var detonationDelay = 0.0;

var explosion : Transform;

var deadReplacement : Rigidbody;

function ApplyDamage (damage : float)

{

// We already have less than 0 hitpoints, maybe we got killed already?

if (hitPoints <= 0.0)

return;

hitPoints -= damage;

if (hitPoints <= 0.0)

{

// Start emitting particles

var emitter : ParticleEmitter = GetComponentInChildren(ParticleEmitter);

if (emitter)

emitter.emit = ***e;

Invoke("DelayedDetonate", detonationDelay);

}

}
函数对被击中或被爆炸影响的物体应用毁伤效果。如果物体生命值已经是0或者更少,不会有任何效果,否则生命数值会根据毁伤效果不断减小。当生命值比零还小的时候就会调用DelayedDetonate函数(延迟只是为了爆炸效果更酷,没别的原因)。
function DelayedDetonate ()

{

BroadcastMessage ("Detonate");

}
这就是引爆游戏物体和其子物体的方法
function Detonate ()

{

// Destroy ourselves

Destroy(gameObject);

// Create the explosion

if (explosion)

Instantiate (explosion, transform.position, transform.rotation);
如果桶子上加载了爆炸预制,那么生命值为0是就会显示这个爆炸预制。
// If we have a dead barrel then replace ourselves with it!

if (deadReplacement)

{

var dead : Rigidbody = Instantiate(deadReplacement, transform.position,

transform.rotation);

// For better effect we assign the same velocity to the exploded barrel

dead.rigidbody.velocity = rigidbody.velocity;

dead.angularVelocity = rigidbody.angularVelocity;

}
如果游戏物体还有一个死亡状态,那么桶子爆炸,然后用这种死亡状态代替这个游戏物体。同时要注意方向的一致性。
// If there is a particle emitter stop emitting and detach so it doesnt get destroyed

// right away

var emitter : ParticleEmitter = GetComponentInChildren(ParticleEmitter);

if (emitter)

{

emitter.emit = false;

emitter.transform.parent = null;

}

}

// We require the barrel to be a rigidbody, so that it can do nice physics

@script RequireComponent (Rigidbody)
下面我们在几个桶子上使用DamageReceiver脚本。先插入一些资源:

拖放Objects/crateAndBarrel/barrel物体到场景中

对桶子(barrel)添加刚体属性

给桶子增加一个盒子碰撞器(box collider)。根据桶子大小调节盒子碰撞器大小。在盒子碰撞器参数栏中的Size中调节。

层级栏中,把脚本DamageReceiver付给桶子

把标准资源库中的explosion预制付给Explosion变量(在桶子的毁伤接收器属性中)

创建一个新预制Barrel(注意大写B,插入的模型桶子名字是小写b)

把设置好的桶子物体(barrel)从层级栏中拖放到工程栏中的新建的预制上

增加几个Barrel到场景(直接复制即可)

运行游戏



你可能注意到,当桶子爆炸后,它仅仅就只消失了,我们还需要添加一个爆炸后的桶子的来代替它。

创建一个新预制Barrel-dead

把原始桶子物体付给预制(从文件夹Objects/crateAndBarrel中导入的)

此时,桶子(Barrel)和爆炸后的桶子(Barrel-dead)看上去是一样的,因为他们的纹理一样(barrel1)

我们需要炸后的桶子纹理跟桶子纹理不一样,这样玩家才知道爆炸没爆炸,类似烧毁的纹理。仅仅调节barrel1是不行的,必须创建一个新的材质付给Barrel-dead。首先复制材质barrel1,调节成烧毁的样子。

工程栏中选择barrel1材质(点击Barrel-dead,在参数Mesh Renderer中点 Materials,然后工程栏中会高亮显示barrel1)

复制材质barrel1(Ctrl+D),重命名为barrelDead。注意,复制的材质会自动命名为barrel2

设定材质,在参数Main Color中把颜色调为黑色

工程栏中选择Barrel-dead,材质栏中下拉菜单选择barrelDead

比较两个材质的不同

下一步,点选Barrel-dead,为其增加盒子碰撞器和刚体属性

把Barrel-dead配置到Barrel的Dead Replacement参数中

运行游戏,将会出现桶子爆炸前后不一样的效果
防卫机枪(Sentry Gun)

最后我们在游戏中增加一个敌人,一挺防卫机枪。防卫机枪将自动寻找玩家,并进行射击。

首先插入机枪模型:

把Object/weapons文件夹下的sentryGun物体拖放到场景中

给机枪增加box collider和rigidbody属性

调节下盒子碰撞器大小,使他包裹炮塔上机枪管

把脚本DamageReceiver付给机枪

现在我们来解释下防卫机枪的脚本代码。全代码如下SentryGun:
var attackRange = 30.0;

var shootAngleDistance = 10.0;

var target : Transform;

function Start () {

if (target == null && GameObject.FindWithTag("layer"))

target = GameObject.FindWithTag("layer").transform;

}
函数Start检测是否给机枪赋予了一个目标物体(参数面板中可以设置),但在参数面板中把Player标签付给参数会更方便(马上来操作)。
function Update () {

if (target == null)

return;

if (!CanSeeTarget ())

return;

// Rotate towards target

var targetPoint = target.position;

var targetRotation = Quaternion.LookRotation (targetPoint - transform.position,

Vector3.up);

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,

Time.deltaTime * 2.0);
如果玩家在游戏中,并被防卫机枪发现,机枪炮塔将从当前角度旋转朝向玩家。
// If we are almost rotated towards target - fire one clip of ammo

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

var targetDir = target.position - transform.position;

if (Vector3.Angle(forward, targetDir) < shootAngleDistance)

SendMessage("Fire");

}
如果当前机枪管位置与玩家的夹角小于shootAngleDistance所设置的数值,机枪将开始开火。
function CanSeeTarget () : boolean

{

if (Vector3.Distance(transform.position, target.position) > attackRange)

return false;

var hit : RaycastHit;

if (Physics.Linecast (transform.position, target.position, hit))

return hit.transform == target;

return false;

}
函数CanSeeTarget计算出机枪是否看见了目标(在这里是玩家)
最后我们来完成对防卫机枪最后的设置:

设置防卫机枪的目标。层级面板中点选Fps控制器,标签栏中的下拉菜单选择标签Player。

把脚本SentryGun配置给防卫机枪的子物体sentryGunRotateY。这会使防卫机枪仅仅顶部旋转,三角基座固定不动。

把爆炸预制配置给机枪中DamageReceiver属性中的爆炸栏

把防卫机枪配置到DamageReceiver属性中的Dead Replacement栏(也可以配置一个自己创建的物体作为破坏状态物体)

把脚本MachineGun付给sentryGunRotateY

在资源库中,把sentryGunTop的子物体muzzleflash配置给机枪属性中的Muzzle Flash变量。

层级栏中点选muzzleflash,把它的着色器类型改为Particles/Additive

运行游戏。现在可以朝油桶和机枪开火了
天空物体(Skybox)

给场景添加天空效果。

    选择Edit>Render Settings。把skyBoxTest拖放配置给Skybox材质。这样就创建了天空。



由 lsermao  发表
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

   

671

主题

1

听众

3247

积分

中级设计师

Rank: 5Rank: 5

纳金币
324742
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2012-1-25 23:29:27 |只看该作者
新词新语迎新年, 年味十足乃作年.
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

板凳
发表于 2012-1-28 23:22:52 |只看该作者
美酒令人回味,音乐让人陶醉,好书百读不悔,情意形影相随,节日问候最可贵。又到年终岁尾,愿你幸福健康作陪,笑得合不拢嘴,预祝春节快乐!
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

地板
发表于 2012-2-8 23:29:32 |只看该作者
呵呵,很好,方便罗。
回复

使用道具 举报

5969

主题

1

听众

39万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

5#
发表于 2012-3-14 23:25:19 |只看该作者
心中有爱,爱咋咋地
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

6#
发表于 2012-3-15 23:32:01 |只看该作者
不错 非常经典  实用
回复

使用道具 举报

797

主题

1

听众

1万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
5568
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

7#
发表于 2012-3-16 18:59:02 |只看该作者
  学习
回复

使用道具 举报

   

671

主题

1

听众

3247

积分

中级设计师

Rank: 5Rank: 5

纳金币
324742
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

8#
发表于 2012-3-20 23:19:27 |只看该作者
楼主收集的可真全哦
回复

使用道具 举报

5969

主题

1

听众

39万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

9#
发表于 2012-4-11 23:32:13 |只看该作者
很有心,部分已收录自用,谢谢
回复

使用道具 举报

markq    

511

主题

1

听众

1万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
15839
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

10#
发表于 2012-4-12 22:47:40 |只看该作者
不错 非常经典 实用
回复

使用道具 举报

12 第1页 | 共2 页下一页
返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-13 12:28 , Processed in 0.698614 second(s), 33 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部