您的位置:首页 > 移动开发 > Unity3D

简单的(第一人称射击)FPS游戏

2017-07-07 20:30 281 查看
本篇文章基于上一篇文章: 使用unity3d搭建简单的场景以及第一人称角色的控制

1、给角色添加射击功能

通过射线射击,新建RayShooter.cs脚本,将该脚本添加到角色所包含的摄像机对象上,编辑代码。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RayShooter : MonoBehaviour {

private Camera _camera;

// Use this for initialization
void Start () {
_camera = GetComponent<Camera>();    //访问相同对象上附加的其他组件
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;                   //隐藏屏幕中心的光标
}

void OnGUI()
{
int size = 12;
float posX = _camera.pixelWidth / 2 - size / 4;
float posY = _camera.pixelHeight / 2 - size / 2;
GUI.Label(new Rect(posX, posY, size, size), "*");  //GUI.Label()在屏幕上显示文本
}

// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))    //响应鼠标按键
{
Vector3 point = new Vector3(_camera.pixelWidth / 2, _camera.pixelHeight / 2, 0); //屏幕中心是宽高的一半
Ray ray = _camera.ScreenPointToRay(point); //使用ScreenPointToRay()在摄像机所在位置创建射线
RaycastHit hit;
if(Physics.Raycast(ray, out hit))      //Raycast给引用的变量填充信息
{
GameObject hitObject = hit.transform.gameObject;
ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
if(target != null)
{
target.ReactToHit();
}
else
{
StartCoroutine(SphereIndicator(hit.point));   //运行协程来响应击中
}
}
}
}

private IEnumerator SphereIndicator(Vector3 pos)   //协程使用IEnumerator方法
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = pos;
yield return new WaitForSeconds(1);   //yield关键字告诉协程在何处暂停
Destroy(sphere);             //移除GameObject并清除它占用的内存
}
}

二、响应被击中

创建敌人预设,并新建响应被击中的脚本ReactiveTarget.cs,将改脚本组件添加到预设中,编辑脚本,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReactiveTarget : MonoBehaviour {

public void ReactToHit()
{
WanderingAI behavior = GetComponent<WanderingAI>();
if(behavior != null)              //检查角色是否有WanderingAI脚本
{
behavior.SetAlive(false);
}
StartCoroutine(Die());  //通过射击脚本调用的方法
}

private IEnumerator Die()
{
this.transform.Rotate(-75, 0, 0);    //推到命中物体,等待1.5秒后摧毁命中物体
yield return new WaitForSeconds(0.5f);
Destroy(this.gameObject);    //对象能销毁自己,就像一个分开独立的对象
}

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

}
}

三、让敌人走动起来

新建WanderingAI.cs脚本,添加该脚本组件到敌人对象中。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WanderingAI : MonoBehaviour {

public float speed = 3.0f;        //移动速度的值
public float obstacleRange = 5.0f;       //对墙壁做出反应的值
private bool _alive;          //用于跟踪敌人是否存活
[SerializeField] private GameObject fireballPrefab;
private GameObject _fireball;

// Use this for initialization
void Start () {
_alive = true;     //初始化值
}

// Update is called once per frame
void Update () {
if (_alive)           //只有当角色存活时才移动
{
transform.Translate(0, 0, speed * Time.deltaTime);   //每帧持续向前移动,不管旋转
Ray ray = new Ray(transform.position, transform.forward);   //和角色相同位置的射线,并且方向相同
RaycastHit hit;
if (Physics.SphereCast(ray, 0.75f, out hit))            //使用沿着射线的长度发射射线
{
GameObject hitObject = hit.transform.gameObject;
if(hitObject.GetComponent<PlayerCharacter>())
{
if(_fireball == null)
{
_fireball = Instantiate(fireballPrefab) as GameObject;
_fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
_fireball.transform.rotation = transform.rotation;
}
}
else if (hit.distance < obstacleRange)
{
float angle = Random.Range(-110, 110);    //转向一个半随机的新方向
transform.Rotate(0, angle, 0);
}
}
}
}

public void SetAlive(bool alive)     //公有方法允许外部代码影响alive的值
{
_alive = alive;
}
}

四、自动生成敌人

创建一个空对象,新建一个SceneController.cs脚本用于实例化敌人预设,并添加到空对象中。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SceneController : MonoBehaviour {

[SerializeField] private GameObject enemyPrefab;  //序列化变量,用于链接预设对象
private GameObject _enemy;    //一个私有变量,跟踪场景中敌人的实例

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
if(_enemy == null)    //只用当场景中没有敌人时才产生一个新敌人
{
_enemy = Instantiate(enemyPrefab) as GameObject;      //这个方法复制了预设对象
_enemy.transform.position = new Vector3(0, 1, 1);
float angle = Random.Range(0, 360);
_enemy.transform.Rotate(0, angle, 0);
}
}
}

五、让敌人主动发起攻击,角色响应攻击

创建制单预设,新建Fireball.cs脚本,用于敌人发起攻击,新建PlayerCharacter.cs脚本,用于角色响应攻击。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
a7c9

public class Fireball : MonoBehaviour {

public float speed = 10.0f;
public int damage = 1;

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
transform.Translate(0, 0, speed * Time.deltaTime);
}

void OnTriggerEnter(Collider other)
{
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
if(player != null)
{
player.Hurt(damage);
}
Destroy(this.gameObject);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCharacter : MonoBehaviour {

private int _health;

// Use this for initialization
void Start () {
_health = 5;
}

public void Hurt(int damage)
{
_health -= damage;
Debug.Log("Health: " + _health);
}

// Update is called once per frame
void Update () {

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息