设为首页收藏本站
查看: 800|回复: 0

Cha10.1丨BattleStar实战:给游戏添加物理系统

[复制链接]

该用户从未签到

17

主题

19

帖子

447

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
447
橙子va 发表于 2018-5-26 11:25:26 8000 | 显示全部楼层 |阅读模式
本节要实现的目标:
1、玩家拾取血包增加血量
2、玩家可用激光对NPC造成伤害


一、导入资源文件

文件下载:微信公众号vrlife—新书推荐—新书配套资源下载
1、导入Package
2、运行_Scenes里面的BattleStar_GameScene场景,观察


二、NavMesh寻路系统
1、添加自动寻路脚本
我们发现,在Hierarchy里面有GameOverPosition,它代表着我们到达该地,将取得游戏胜利。我们添加自动寻路脚本,观察在迷宫中如何到达目的地。我们先将FPSController设置为NavMesh Agent,自动寻路到该位置看看实际效果。
    给FPSController添加endPosition脚本、NavMeshAgent组件,并取消激活FPSController的First Person Controller脚本,避免功能冲突
  1. using UnityEngine;
  2. using UnityEngine.AI;

  3. public class endPosition : MonoBehaviour {

  4.     NavMeshAgent agent;

  5.     private void Start()
  6.     {
  7.         agent = GetComponent<NavMeshAgent>();
  8.         agent.destination = GameObject.Find("GameOverPosition").transform.position;
  9.     }
  10. }
复制代码

2、重设NavMesh寻路区域
我们发现,FPSController找到了目的地,但它在某地区是穿墙而过。这是不合逻辑的。我们重新设置下NavMesh寻路区域:
Navigation-Object-Mesh Renderer将Door设置成Walkable;Floor勾选Navigation Static-Walkable;Floor_Plane取消勾选Navigation Static;mazemodel-Not Walkable;outside-Not Walkable;Roof-Not Walkable;Wall_1、3-Walkable;Wall_2、4-Not Walkable。Bake

运行游戏,我们发现FPSController正确寻路到目标点,现在我们完成了系统的NavMesh寻路系统设置,接下来我们增加人物捡到血包加血功能


三、实现血包加血功能
观察游戏项目,我们发现控制人物血量的属性PlayerHealth在FPSController—Player脚本里面

1、除了场景中的血包外,我们再在FPSController附近另增加两个如下图所示血瓶,model位于Assets-Plugins-HealthMedicalSet-Models-bottle 02
0524-01.png

2、添加Mesh Collider,更改Shader使其看起来更好看些

3、添加如下代码,让瓶子运行时自转
  1. using UnityEngine;

  2. public class RotateSelf : MonoBehaviour {

  3.     int RotateSpeed = 90;

  4.         void Update () {
  5.         transform.Rotate(Vector3.up * RotateSpeed * Time.deltaTime, Space.World);
  6.         }
  7. }
复制代码

4、激活FPSController的First Person Controller脚本,停止运行End Position,可看到如下效果。后续这类操作不再赘述
20180526111542.gif

5、给血瓶增添触发代码
a、修改FPSController-Player代码,public int static playerHealth=5改为public int playerHealth=5,这样我们便能在面板看到初始血量,当然,我们赋值的应该是下方的PlayerHealth属性

b、我们给血瓶赋予脚本blood,该脚本用于给玩家增加血量
本操作用到了Collider的OnTriggerEnter方法。当带有Collider组件的物体接触到外物时,会触发它的OnColliderEnter方法,但当该物体开启Is Trigger时,两个物体就变为可穿透状态了。当穿透时,系统会自动触发OnTriggerEnter方法
0524-1.png
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;

  4. public class blood : MonoBehaviour
  5. {

  6.     void OnTriggerEnter(Collider other)
  7.     {
  8.         if (other.name == "FPSController")
  9.         {
  10.             if (other.GetComponent<Player>().PlayerHealth < 5)
  11.             {
  12.                 other.GetComponent<Player>().PlayerHealth += 1;
  13.                 //计算方法: 把左边的变量和第一个符号移到右边, 变量1 = 变量1 + 表达式运算结果)
  14.                 //如:i += 1           则是: i = i + 1
  15.                 //i += 1 + 2 * 3  则是: i = i + (1 + 2 * 3)
  16.             }
  17.         }
  18.     }
  19. }
复制代码

6、我们只完成了给人物增加血量,但人物一开始血量是满的,我们再增加一个减血瓶,效果是接触后减3滴血,观看效果

  1. using UnityEngine;

  2. public class blood_down : MonoBehaviour {

  3.     void OnTriggerEnter(Collider other)
  4.     {
  5.         if (other.name == "FPSController")
  6.         {
  7.             other.GetComponent<Player>().PlayerHealth -= 3;
  8.         }
  9.     }
  10. }
复制代码

减血、加血过多是因为碰撞后未立即销毁对象,出现多次减血加血现象,这对我们观察无影响。读者可自行尝试在代码里添加Destroy(gameObject)销毁目标


四、玩家用激光对NPC造成伤害
本节用到的关键代码是Physics.Raycast,可回顾上篇文章——Physics.Raycast()知识点讲解,和我们之前做过的动画项目——Unity动画射线Physics.Raycast()

本节设计思路:准星位于屏幕中央,即从屏幕中央处开火。运用Physics.Raycast()方法,当按下鼠标左键时发射射线,返回射线检测到的物体。如果是机器人,则更改机器人的血量值,使其减少展现出造成伤害的效果

当然,这要求我们不断检测是否按下鼠标左键,若写在Update函数中,会很消耗计算资源。我们运用协程方法StartCorotine()方法,来不断执行该命令,减少资源消耗

1、本项目是有准星来瞄准的,但我们发现捡到枪后准星并没有出现,我们将HUDCanvas—GamePanel—ReticleImage的Scalex、y、z设置成2,放大准星

2、本项目玩家发射子弹是采用了开火动画+射线检测方式,代码位于Gun中,Gun作为组件放在FPSController—FirstPersonCharacter—GunWithHand上。当射线碰撞检测到Robot,会调用Robot代码中的RobotHealth,使RobotHealth--使其受伤。下面展示的Robot中的代码,保证当Robot生命值为0时,调用RobotDie()方法
  1.     private float robotHealth;
  2.     public float RobotHealth
  3.     {
  4.         get
  5.         {
  6.             return robotHealth;
  7.         }

  8.         set
  9.         {
  10.             robotHealth = value;

  11.             healthImage.localScale = new Vector3(value / 5, 1, 1);

  12.             if (robotHealth == 0)
  13.             {
  14.                 RobotDie();
  15.             }
  16.         }
  17.     }
复制代码
当然,我们发现Robot代码中也包含如下代码,我们也可在Gun中直接调用这段代码,造成机器人生命值减一的效果

  1.     public void RobotGetHurt()
  2.     {
  3.         RobotHealth -= 1;
  4.     }
复制代码

3、当Robot生命值下降后,在Robot代码的RobotHealth属性set中,本项目写了healthImage.localScale = new Vector3(value / 5, 1, 1)代码,用来缩放Robot头上血条,呈现出减血的效果
  1. Transform.localScale 自身缩放
  2. //扩大物体的x轴向0.1个单位
  3. transform.localScale += Vector3(0.1,0,0);
复制代码


本项目的Gun、GunModelTrigger、HealthPackage、Robot代码包含本节内容,读者可重点观察,加深本节印象。最后新开“第九章U3D代码注解”一文记录本章重点代码,用于速查定义节省时间。如遇其他问题,可联系作者邮箱skode@foxmail.com共同讨论

回复

使用道具 举报

0条回复
跳转到指定楼层

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|赛隆网 ( 粤ICP备16067842号 )  

Copyright 2013 -̳ Ȩ All Rights Reserved.

Powered by Cylonspace ; All Rights Reserved.

QQ|Archiver|手机版|小黑屋|赛隆网 ( 粤ICP备16067842号 )  

GMT+8, 2018-10-21 21:33 , Processed in 0.114337 second(s), 27 queries.

快速回复 返回顶部 返回列表