当前Unity最新版本5.6.3f1,我使用的是5.5.1f1
场景搭建
1: 导入人物模型, 手持一把枪;
2: 导入碎片模型;
3: 创建一个平面;
4: 创建一个障碍物;
5: 导入人物模型;
6: 配置一个十字瞄准器, 设想机对准的中心就是瞄准的中心, 屏幕中心;
7: 配置一个第一人称的摄像机,做人的眼睛;
开枪射击
1: 鼠标左键按下开火;
2: 从摄像机位置开始,根据摄像机的正前方,在一定的射击距离内如果碰撞到了某个物体,那么就表示这个物体被子弹射击;
3: 播放射击的子弹碎片: 在射击碰撞点产生碎片物体,并给这些碎片物体一个反弹力(100)
方向是设计的反方向;
4: Physics.Raycast (起点, 发射方向向量, out hit, 最大有效距离(子弹的距离));
5: 播放开枪的声音
PlayOneShot 固定时间播完你的audio文件;
用PlayOneShot,就能够听到连续的枪声了;
人物的行走
1: 定义移动的速度;
2: 玩家在自己的坐标空间内向前(W),后(S), 左(A), 右(D);
3: 前后 Translate(0, 0, 距离, Space.Self);
4: 左右 Translate(距离, 0, 0, Space.Self);
5: 播放人物行走的脚步声;
枪的上下左右移动
1: 枪的左右瞄准;
(1)计算绕Y轴旋转的欧拉角 GetAxis(Mouse Y) * 移动的灵敏度(5);
(2)在转向的时候,角色也要跟着转,那么我们旋转角色就可以了, 摄像机也会跟着转;
修改角色的欧拉角;
(3) 给这个枪绕Y轴一个转动范围[-360, 360]
(4) Mathf.Clamp(value, min, max);
2: 枪的上下移动: localEulerAngles
(1)枪的上下移动,角色不动,所以不能作用到角色上;
(2)计算绕X轴旋转的欧拉角 GetAxis(Mouse X) * 移动的灵敏度(5);
(3)只作用在瞄准上(eye),所以修改摄像机的相对欧拉角;
(4)同时手中的枪也要移动对应的欧拉角(right hand);
(5)抬头低头有一个范围,我们在[-45, 45]的范围内;
FPS第一人称射击类游戏实例
场景搭建
1.创建Unity项目工程和文件目录,保存场景
2.导入人物模型和子弹碎片的资源包charactor.unitypackage(第74)
3.创建一个平面plane,X和Z拉长10倍,把主角模型Assets\Prefabs\person拉近Hierarchy视图中
4.把走路的声音Step.mp3,射击的声音Shot.mp3,平面贴图Ground.jpg,瞄准的准心贴图Crosshairs.png(第74)导入Resources文件夹
5.把Crosshairs.png直接拖进Scene视图的平面plane上,自动帮我们生成了平面的材质并关联
6.创建一个cube,放大4倍,放在主角模型的正前方,Z设置为20
7.配置一个十字瞄准器,UI和摄像机是成比例对应的,所以摄像机对准的中心就是等下Crosshairs瞄准的中心,屏幕中心,右键---->UI---->Image,命名为Crosshairs,再把Crosshairs.png的Texture Type设置为Sprite(2D and UI)
8.把Crosshairs.png拖进Crosshairs节点的Image组件的Source Image属性中,调整Crosshairs的position为(0,0,0),屏幕正中央,Set Native Size
9.配置一个第一人称的摄像机,做人的眼睛。就是把Main Camera拖到person下作为子节点重命名为eye,这样可以跟随主角移动。然后把摄像机的position设置为(0,1.5,0),正好在人物头部
开始射击
10.创建一个脚本open_fire,挂载在person节点下,里面实现开枪的逻辑。
a.查看虚拟按键Edit---->Project Settings---->Input---->Fire1---->mouse 0,可以用Fire1代替mouse 0
b.枪口喷火的特效如果喷的很分散的话,可以设置FireEffect---->Particle System---->Shape---->Shape---->类型设置为Mesh
c.FPS游戏通常不会有真的子弹在天空中飞来飞去的,一般是用射线实现,有真的子弹也没关系。
打开open_fire.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class open_fire : MonoBehaviour { private ParticleSystem fire_effect;//特效节点person---->RightHand---->FireEffect public Transform eye;//摄像机节点person---->eye public GameObject piece;//碎片节点Prefabs文件夹---->piece //开枪的声音Resources文件夹---->Shot,给person节点加一个AudioSource组件,关联Shot,再把person节点拖进shoot_audio //AudioSource组件的Play On Awake打钩去掉 public AudioSource shoot_audio; // Use this for initialization void Start () { //获得开枪的特效节点的特效组件 this.fire_effect = this.transform.Find("RightHand/Pistol/FireEffect").GetComponent<ParticleSystem>(); } //生成枪打到障碍物的碎片特效 void play_pieces_effect(Vector3 w_pos) { for (int i = 0; i < 5; i++) { GameObject p = GameObject.Instantiate(this.piece); p.transform.position = w_pos;//坐标设置在碰撞点处 p.GetComponent<Rigidbody>().AddForce(-this.eye.forward * 100f);//撞到后给一个反弹力,方向和摄像机Z轴方向相反 // Component.Destroy(p, 0.3f);//在0.3s后删除该组件 // MonoBehaviour.Destroy(p, 0.3f);//在0.3s后删除该组件,MonoBehaviour继承自Component //Destroy(p, 0.3f);//在0.3s后删除节点,调用静态函数Destroy GameObject.Destroy(p, 0.3f);//在0.3s后删除节点 } } //枪发射子弹 void shoot_fire() { // 播放枪发射子弹时枪口的火焰 this.fire_effect.Play(); // end // 播放开枪的声音 // this.shoot_audio.Play();//用这个播的比较慢,因为shot声音前面一小段没声音 this.shoot_audio.PlayOneShot(this.shoot_audio.clip);//用这个播的速度比较快,固定时间内播完 // end // 当前这个枪打到了哪个物体 // 从这个eye的位置,沿着eye的前方方向,发射一条射线,看谁被命中了 // 子弹是有有效的射击距离的,所以,我们要传入子弹的最大距离 RaycastHit hit; // 命中的对象 //从this.eye.position出发,向this.eye.forward(Z轴方向)发射一条射线,撞到hit,射线最大距离100米,最后再out带出hit命中对象 if (Physics.Raycast(this.eye.position, this.eye.forward, out hit, 100)) { // 枪打到了哪个障碍物,打印出障碍物的碰撞器的节点的名字 Debug.Log(hit.collider.gameObject.name); // .....其他的游戏逻辑 // end // 播放这个碎片特效,传入碰撞点世界坐标hit.point this.play_pieces_effect(hit.point); // end } // end } // Update is called once per frame void Update () { //鼠标左键按下,在Edit---->Project Settings---->Input里面有配置Fire1就是鼠标左键mouse 0 if (Input.GetButtonDown("Fire1")) { this.shoot_fire(); } } }