第二章_2.6_3D射击游戏实现
前言
由于工作用的电脑配置太低了,在优快云中编写的笔记字数一多就会卡,所以这段时间的笔记就一直没有上传。
这个项目是我在学习的Unity开发中认为一个比较好且非常适合新手做的项目,所以在这里分享给大家。
本项目参考自《Unity3D 脚本编程和游戏开发》中的第二章,强烈建议大家阅读,是本很适合新手入门的书。
本项目的资源文件:资源下载
文章目录
2.6.0 效果

2.6.1 实现功能
- 玩家移动
- 摄像机跟随
- 武器系统和子弹
- 敌人角色
- 子弹击中逻辑
- 人物死亡效果
2.6.2 创建主角以及玩家移动
创建主角主要由一个胶囊体作为主体,一个方体作为面部,其效果如下:

另外,我们将一个平面作为地板,其大小放大四倍。
主角移动逻辑代码
代码逻辑:
- 获取玩家输入,将输入封装为一个向量
- 在玩家角色并未死亡的前提下,根据玩家输入向量设置玩家的移动速度
- 根据玩家的输入向量设置玩家朝向
- 限制玩家的移动范围,超出范围将玩家修改为范围内
void Update()
{
inputVector = GetInputVector();
if (!isDead)
{
Move();
}
}
/// <summary>
/// 获取玩家输入向量
/// </summary>
/// <returns>玩家输入向量</returns>
private Vector3 GetInputVector()
{
float horizontalInput = Input.GetAxisRaw("Horizontal");
float verticalInput = Input.GetAxisRaw("Vertical");
return new Vector3(horizontalInput, 0, verticalInput);
}
/// <summary>
/// 玩家移动方法
/// </summary>
private void Move()
{
//设置移动速度
AdjustVelocity();
//设置玩家朝向
AdjustForward();
//设置边界
BorderLimit();
/// <summary>
/// 设置玩家速度
/// </summary>
void AdjustVelocity()
{
//将输入向量归一化,向量的模长为1,保证每个方向的速度相同
inputVector = inputVector.normalized;
rb.velocity = inputVector * speed;
}
/// <summary>
/// 设置玩家朝向
/// </summary>
void AdjustForward()
{
//如果输入的值不是很小的话,将物体转向前进方向
if (inputVector.magnitude > 0.1f)
{
transform.forward = inputVector;
}
}
/// <summary>
/// 限制玩家移动范围
/// </summary>
void BorderLimit()
{
//限制玩家的移动范围
Vector3 temp = transform.position;
//Math.Clamp(value,min,max) : 在最大最小范围中间取值,如果超过范围,则返回最大/最小值
temp.x = Mathf.Clamp(temp.x, -BORDER, BORDER);
temp.z = Mathf.Clamp(temp.z, -BORDER, BORDER);
transform.position = temp;
}
}
知识点
①:向量归一化
向量归一化,即将向量的长度改为1。
假设
vector为一个向量,可以使用vector.normalized来获取这个向量的归一化向量,或者使用vector.Normalize()来将这个向量归一化。②:Mathf.Clamp(value,min,max)
使value在min和max中间取值,如果value大于最大值在返回max,如果小于最小值那么返回min
③:内部方法
在方法内部的方法,C#的特性,允许我们在一个方法的内部再编写方法。
但是编写的方法仅仅可以在方法内部被调用。
目前貌似不推荐使用这个方法,因为这样限制了方法的复用度,以后不用了。
④:transform.forward
物体面朝方向,长度为1,初始情况下是面向Z轴方向,此时transform.forward为(0,0,1)。之后随着物体旋转而改变。
2.6.3 摄像机跟随
我们创建一个2D Camera,并且将其跟随的目标设置为Player物体即可。

注意:我们必须创建2D Camera,如果创建的物体是Virtual Camera的话,摄像机会随着玩家转向也一起转向。
2.6.4 实现武器系统
书中的武器系统较为简陋,没有创建武器对应的类,不利于以后添加新的武器。所以在此我做出了一点小调整:
-
创建
Gun类,其中包括武器的相关信息(包括开火位置、射速、子弹数等) -
在人物物体(GameObject)之下创建一个名为
WeaponBag的物体,其中子物体是武器物体。- 武器物体包括几个简单物体拼接而成的武器模型
- 武器物体挂载
Gun脚本的组件,以此设置武器的属性 - 武器物品必须要有一个名为
FirePosition的空物体,此物体表示该武器的开火位置,也就是“子弹从哪里打出来”
-
WeaponBag物体上挂载了一个对应的脚本,其脚本的作用是获取WeaponBag的所有子物体中的所有子物体的Gun组件 -
所有武器的操作由
WeaponController操控,WeaponController目前实现了武器开火以及武器切换这两个重要功能 -
当然最后还有创建子弹相关的脚本以及物体
Gun类代码
代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 枪械类
/// </summary>
public class Gun : MonoBehaviour
{
/// <summary>
/// 射出的子弹
/// </summary>
public GameObject bulletPerfab;
/// <summary>
/// 射击间隔
/// </summary>
public float fireCD;
/// <summary>
/// 是否持续射击
/// </summary>
public bool isHoldToFire;
/// <summary>
/// 一次射击的子弹个数
/// </summary>
public int onceFireBulletNumber;
/// <summary>
/// 子弹射出间隔角度(当子弹个数为复数时使用)
/// </summary>
public float bulletAngle;
/// <summary>
/// 每个子弹伤害
/// </summary>
public float damage;
/// <summary>
/// 子弹飞行速度
/// </summary>
public float bulletVelocity;
/// <summary>
/// 子弹持续时间
/// </summary>
public float bulletLifeTime;
/// <summary>
/// 子弹射出位置
/// </summary>
public Transform fireTransform;
}
一个简单的Gun物体示例:

WeaponBag功能实现
实现原理如图:

为了代码的灵活性,我们并不需要手动设定规定一个人物物品持有几个武器。所以就需要在WeaponBag的组件中使用GetComponentsInChildren()方法,获取子物体中的所有Gun组件,并且将他们存放在一个数组中。
实现代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponBag : MonoBehaviour
{
public List<Gun> guns;
// Start is called before the first frame update
void Awake()
{
//获取所有子物体的Gun组件
Gun[] gunsInBag = GetComponentsInChildren<Gun>();
guns = new List<Gun>(gunsInBag);
}
}
如此一来,我们的WeaponController只需要获取WeaponBag组件,就可以“知道”这个人物有多少种枪械了。
WeaponController实现
WeaponController主要实现了武器开火和武器切换功能。
- 武器切换
武器切换的逻辑:设置一个int类型的变量curGun,当切换武器时curGun在weaponBag的guns列表中增加,如果超出列表下标则回到最初的0下标;当武器切换时,先将当前武器(旧武器)设置为未激活状态,再等curGun增加后,将目前武器(新武器)设置为激活状态。
另外:在WeaponContoller启动时会将除了curGun之外的所有武器都设置为未激活状态。
实现代码:
/// <summary>
/// 切换武器
/// </summary>
/// <returns>当前武器序号</returns>
/// <remarks>
/// 将当前武器设置为未激活,然后将列表中的下一个武器激活
/// </remarks>
public int ChangeWeapon()
{
DeactiveCurrentWeapon()


最低0.47元/天 解锁文章
5959

被折叠的 条评论
为什么被折叠?



