本教程适合Unity新手或对Raycast不甚了解的开发者,主要介绍Raycast的用途并绘制出射击游戏的射线轨迹。

最终效果

本课程包括鼠标控制相机旋转、射击物体、显示射线轨迹及准星三个部分,最终实现效果如下:
160748jxesmgrngslc3xgs.jpg

下面就来为大家讲解实现步骤。

第一步 准备工作

首先下载本课程所需的工程资源并导入Unity项目中:

下载地址

找到Let’s Try Shooter > Scenes文件夹下的ShootingWithRaycasts场景并双击打开。其中已经设置好了本课程所需的游戏环境,FPSController来自Unity自带的Standard Assets资源包,下面新增了Gun游戏对象:

161110xzj53j53l0309jor.jpg

第二步 添加射击脚本

下面来添加射击脚本。在Scripts目录下新建C#脚本命名为RaycastShoot,将该脚本拖拽至层级视图的Gun游戏对象上,然后双击脚本进行编辑。RaycastShoot脚本的主要作用是发出射线,射击物体并造成伤害,播放射击音效,显示射击轨迹并等待一段时间后消失。脚本代码如下:

[C#] 纯文本查看 复制代码using UnityEngine; using System.Collections; public class RaycastShoot : MonoBehaviour { // 设置枪击带来的伤害值 public int gunDamage = 1; // 设置两次枪击的间隔时间 public float fireRate = 0.25f; // 设置玩家可以射击的Unity单位 public float weaponRange = 50f; // 设置枪击为物体带来的冲击力 public float hitForce = 100f; // GunEnd游戏对象 public Transform gunEnd; // FPS相机 private Camera fpsCam; // 设置射击轨迹显示的时间 private WaitForSeconds shotDuration = new WaitForSeconds(0.07f); // 枪击音效 private AudioSource gunAudio; // 射击轨迹 private LineRenderer laserLine; // 玩家上次射击后的间隔时间 private float nextFire; void Start () { // 获取LineRenderer组件 laserLine = GetComponent<LineRenderer>(); // 获取AudioSource组件 gunAudio = GetComponent<AudioSource>(); // 获取Camera组件 fpsCam = GetComponentInParent<Camera>(); } void Update () { // 检测是否按下射击键以及射击间隔时间是否足够 if (Input.GetButtonDown(Fire1) Time.time > nextFire) { // 射击之后更新间隔时间 nextFire = Time.time + fireRate; // 启用ShotEffect携程控制射线显示及隐藏 StartCoroutine (ShotEffect()); // 在相机视口中心创建向量 Vector3 rayOrigin = fpsCam.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, 0.0f)); // 声明RaycastHit存储射线射中的对象信息 RaycastHit hit; // 将射击轨迹起点设置为GunEnd对象的位置 laserLine.SetPosition (0, gunEnd.position); // 检测射线是否碰撞到对象 if (Physics.Raycast (rayOrigin, fpsCam.transform.forward, out hit, weaponRange)) { // 将射击轨迹终点设置为碰撞发生的位置 laserLine.SetPosition (1, hit.point); // 获取被射中对象上的ShootableBox组件 ShootableBox health = hit.collider.GetComponent<ShootableBox>(); // 如果组件存在 if (health != null) { // 调用组件的Damage函数计算伤害 health.Damage (gunDamage); } // 检测被射中的对象是否存在rigidbody组件 if (hit.rigidbody != null) { // 为被射中的对象添加作用力 hit.rigidbody.AddForce (-hit.normal * hitForce); } } else{ // 如果未射中任何对象,则将射击轨迹终点设为相机前方的武器射程最大距离处 laserLine.SetPosition (1, rayOrigin + (fpsCam.transform.forward * weaponRange)); } } } private IEnumerator ShotEffect() { // 播放音效 gunAudio.Play (); // 显示射击轨迹 laserLine.enabled = true; // 等待0.07秒 yield return shotDuration; // 等待结束后隐藏轨迹 laserLine.enabled = false; } }

注意,射线应该从玩家眼睛所处位置向眼镜前方射出,玩家眼睛即相机所在位置。

上述代码涉及到还未添加的脚本与游戏对象,下面的步骤将一一说明。

第三步 添加LineRenderer组件

为Gun游戏对象添加LineRenderer组件,用于在运行时的游戏视图中绘制出射击轨迹,只有发出时才会显示轨迹,所以默认是隐藏的,取消勾选组件名左侧的复选框隐藏组件。另外这里并未指定材质,所以绘制出来的射线会是粉红色的,你也可以自行添加材质。

162611s59fq22vdqoknodv.jpg

第四步 创建GunEnd

这里需要一个空的游戏对象作为枪头处的位置标记,在层级视图中选中Gun游戏对象,右键单击在弹出菜单中选择Create Empty新建游戏对象,重命名为GunEnd。为GunEnd添加标签以便在场景中显示更明显,然后调整GunEnd的坐标至枪头处,这里设置为(0.36, -0.18, 1):

162648rtjzrgjle6zjebj0.jpg

将创建好的GunEnd游戏对象拖拽至Gun对象的RaycastShoot脚本的GunEnd字段。

第五步 添加RayViewer脚本

上面提到了,瞄准物体并进行碰撞检测的射线并非我们需要绘制的射击轨迹。需要绘制的射击轨迹已经在RaycastShoot脚本中完成了,接下来添加RayViewer脚本,使用Debug功能在场景中绘制用于瞄准的射线,也就是从相机位置发出的射线。

新建C#脚本重命名为RayViewer,将脚本拖拽至Gun游戏对象上,双击脚本进行编辑。RayViewer脚本代码如下:

[C#] 纯文本查看 复制代码using UnityEngine; using System.Collections; public class RayViewer : MonoBehaviour { // Debug.DrawRay绘制的Unity单位 public float weaponRange = 50f; // FPS相机 private Camera fpsCam; void Start () { // 获取Camera组件 fpsCam = GetComponentInParent<Camera>(); } void Update () { // 创建相机位置至视口中心点的向量 Vector3 lineOrigin = fpsCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 0.0f)); // 在场景视图中绘制lineOrigin到相机前方武器射程处的射线 Debug.DrawRay(lineOrigin, fpsCam.transform.forward * weaponRange, Color.green); } }

到此射线的处理与绘制就差不多了,运行场景会看到场景视图出现了两条射线:

162857c080777z9cj8dja0.jpg

找到层级视图中Environment > Targets下,有两个TargetBox对象,选中对象会发现上面已经绑定了ShootableBox脚本。ShootableBox脚本的功能非常简单,CurrentHealth表示对象当前血量,初始总血量为3,脚本代码如下:

[C#] 纯文本查看 复制代码using UnityEngine; using System.Collections; public class ShootableBox : MonoBehaviour { // 总血量 public int currentHealth = 3; public void Damage(int damageAmount) { // 调用Damage时总血量要减去伤害值 currentHealth -= damageAmount; // 检测总血量是否小于等于0 if (currentHealth <= 0) { // 隐藏对象 gameObject.SetActive (false); } } }

在上方的RaycastShoot脚本中已经添加了射击处理的逻辑,当射中立方体时,此时运行场景,已经可以进行射击了,但还是比较难进行瞄准。下面来添加准星。

第六步 添加UI

在层级视图右键单击,弹出菜单中依次选择UI > Image新建Image,点击Color右边的颜色选取按钮,将Image的颜色设置为红色:

163028izwp4ky4vs1hh4ih.jpg

然后点击Rect Transform的锚点设置按钮,按下Alt/Option键同时选择中心点,让准星永远出现在屏幕中心位置:

163123z7559527er5he5ec.gif

设置好后再次点击运行,大功告成啦!

163225xhtvbjjwlkbk46ct.gif u3d, unity3d, raycast, 官方教程锐亚教育

锐亚教育 锐亚科技 unity unity教程