有AI队友的大型第一人称射击游戏戏

   关于第一人称射击的游戏,想起了我玩过的第一款第一人称射击网游,当时很火热的《反恐精英Online》,当时也是玩这个游戏的时候只能说是感觉好玩才去玩,现在再次玩起这种第一人称射击类游戏的时候,可以说多了一个目的,带着欣赏的目的去玩,或者说我更想知道其中的原理,也就是说这个动作或者这种效果是怎么实现的,做游戏开发的不仅要知其然还要知其所以然,我想带着这样一种的学习态度我们才能在学习的过程中获取更多的知识,这一点很重要。
    在练习做这个第一人称设计游戏的过程中学到了很多的东西,其中也有自己不足的地方,下面将在做这个游戏的过程中遇到的问题和学到的东西记录下来。
  (一)首先从玩家类来说
  在这个练习中,玩家类是一个比较重要类,里面定义了玩家的一些基本的数据,注意这里定义变量的过程中如果那个变量或者方法在以后的开发中要调用的话,最好设置为共有的变量,这样就不会发生获取不到的情况了,记得在学习c++课程的时候,老师经常说要用面向对象的思想去编程,这里我想可以把用到的变量设置为属性,例如将playerLife玩家的生命值设置为私有的变量,可以通过方法的方式来初始化或者改变这个生命值,还有就是通过属性的方式,例如public static Life{get{return playerLife};set{playerLife=value} },这样的例子
using UnityE
using System.C
public class Player : MonoBehaviour
//玩家的transform
public Transform playerT
//获取玩家身上的charactercontrol组件
CharacterController playerCC;
//定义玩家的移动速度
public float playerSpeed= //射击部分变量
//***口tranform
Transform shootP
//射击射到的碰撞层
public LayerMask shootM
//射击射中后的粒子效果
public Transform shootFX;
//射击De 音效
AudioSource shootM
public AudioClip shootC
//射击的间隔时间
float shootTime = 0f;
//子弹伤害
public int shootPower = //初始化玩家的
GameManager.Instance.SetLife((int)playerLife);
void Update()
//判断生命值是否为0
if(playerLife&= //播放射击的音效
shootMusic.PlayOneShot(shootClip);
//减少弹药数量
GameManager.Instance.SetAmout( //如果射中
if(hit.pareTo("Enemy")== float v = Input.GetAxis("Mouse Y");
//旋转摄像机设置
camRot.x -=
camRot.y +=
camTransform.eulerAngles = camR
//设置主角的朝向与摄像机一致
Vector3 playerRot = camTransform.eulerA
playerRot.x = playerTraform.eulerAngles = playerR
//主要玩家的移动控制
//定义三个变量
float x = 0f, y = 0f, z = 0f;
//前后左右的移动
if(Input.GetKey(KeyCode.W))
z += playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.S))
z -= playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.A))
x -= playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.D))
x += playerSpeed * Time.deltaT
//当玩家跳起来的时候,角色控制器会自动检测玩家的跳起
y -= playerGravity * Time.deltaT
playerCC.Move(playerTraform.TransformDirection(new Vector3(x,y,z)));
//摄像机的位置和主角位置一致
Vector3 pos = playerTraform.
pos.y += camH
camTransform.position =
/// &summary&
///用来显示游戏中主角的位置
/// &/summary&
void OnDrawGizmos()
Gizmos.DrawIcon(this.transform.position,"Spawn.tif");
public void OnDamage(int damage)
playerLife -=
GameManager.Instance.SetLife((int)playerLife);
//判断生命值是否为0
if (playerLife &= float v = Input.GetAxis("Mouse Y");
//旋转摄像机设置
camRot.x -=
camRot.y +=
camTransform.eulerAngles = camR
//设置主角的朝向与摄像机一致
Vector3 playerRot = camTransform.eulerA
playerRot.x = playerTraform.eulerAngles = playerR
//主要玩家的移动控制
//定义三个变量
float x = 0f, y = 0f, z = 0f;
//前后左右的移动
if(Input.GetKey(KeyCode.W))
z += playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.S))
z -= playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.A))
x -= playerSpeed * Time.deltaT
if(Input.GetKey(KeyCode.D))
x += playerSpeed * Time.deltaT
//当玩家跳起来的时候,角色控制器会自动检测玩家的跳起
y -= playerGravity * Time.deltaT
playerCC.Move(playerTraform.TransformDirection(new Vector3(x,y,z)));
//摄像机的位置和主角位置一致
Vector3 pos = playerTraform.
pos.y += camH
camTransform.position =
    (二)控制脚本,
  这个脚本主要处理屏幕的UI方面,和游戏的一些逻辑处理
using UnityE
using System.C
using UnityEngine.UI;
public class GameManager : MonoBehaviour
public static GameManager Instance = null;
//游戏得分
int score = //弹药数量
int amout = canvasTranform = GameObject.FindGameObjectWithTag("UI").GetComponent&Transform&();
//依次获取canvas 下面的UGUI的内容
foreach(Transform t in canvasTranform.GetComponentsInChildren&Transform&())
if(pareTo("boot")== //更新分数
public void SetScore( int _score)
score += _
if(score&highScore)
highScore =
txtScore.text="Score &color=yellow&"+score+"&/color&";
txtHighScore.text = "HighScore " + highS
txtHighScore.color = Color.
//更新弹药
public void SetAmout(int _amout)
amout -= _
//如果弹药为负数,填充
if(amout&= txtAmout.text = amout.ToString() + "/100";
//更新生命值
public void SetLife(int _life)
txtLife.color = Color.
txtLife.text = _life.ToString();
void OnGUI()
if(player.playerLife&= //显示GameOver
GUI.Label(new Rect( //设置按钮文字大小
GUI.skin.label.fontSize = //重新读入
Application.LoadLevel( //敌人旋转速度
float enemyRotate = 30f;
float enemyTime = 2f;
float enemyLife = 5f;
//获取动画组件
Animator enemyA
void Start()
enemyTransform = this.
//获取主角
player = GameObject.FindGameObjectWithTag("Player").GetComponent&Player&();
//获取寻路组件
enemyAgent = this.gameObject.GetComponent&NavMeshAgent&();
//改变敌人的移动速度
enemyAni = this.gameObject.GetComponent&Animator&();
enemyAgent.speed = enemyS
//设置寻路的目标 即敌人的目标玩家
enemyAgent.SetDestination(player.playerTraform.position);
//用于旋转敌人,使敌人面向玩家
void RotaeToPlayer()
//获取目标方向
Vector3 targetDir = player.playerTraform.position - enemyTransform.
//计算出新的方向
Vector3 newDir = Vector3.RotateTowards(enemyTransform.forward, targetDir, enemyRotate * Time.deltaTime, //获取当前动画状态
AnimatorStateInfo stateInfo = enemyAni.GetCurrentAnimatorStateInfo( //待机一定时间
enemyTime -= Time.deltaT
if(enemyTime&= enemyAni.SetBool("attack", true);
//重置定时器
enemyTime = 1f;
//设置目标
enemyAgent.SetDestination(player.playerTraform.position);
//进入跑步的动画
enemyAni.SetBool("run",true);
//处于跑步的状态
if(stateInfo.fullPathHash==Animator.StringToHash("First.run")&&!enemyAni.IsInTransition( //每隔一秒定位一次
enemyTime -= Time.deltaT
if(enemyTime&= //距离小于1.5
if(Vector3.Distance(enemyTransform.position,player.playerTraform.position)& //当处于攻击状态
if(stateInfo.fullPathHash==Animator.StringToHash("First.attack")&&!enemyAni.IsInTransition( //如果动画播放完,重新待机
if(stateInfo.normalizedTime&= enemyTime = ////这里有一个Bug,不能进入death中,,,,,,,
//当播放死亡的动画的时候
if(stateInfo.fullPathHash==Animator.StringToHash("First.death"))
Debug.Log("进入");
enemyTime-=Time.deltaT
//播放完死亡的动画
if(enemyTime&= //摧毁自身
Destroy(this.gameObject);
Debug.Log("播放了死亡");
//计算伤害的函数
public void OnDamage(int damage)
enemyLife -=
if(enemyLife&= public void Init(EnemySpawn scirpt)
enemyspawn =
//增加敌人数量
enemyspawn.enemyCount++;
 (四)一些用到的类
    1.自动销毁类
using UnityE
using System.C
public class AutoDestroy : MonoBehaviour
public float timer = //得到下一轮敌人的生成时间
enemyTimer = Random.Range( GameObject tar = (GameObject)Instantiate(enemyObj, thisTransform.position, Quaternion.identity);
Enemy enemyScript = tar.GetComponent&Enemy&();
enemyScript.Init(this);
void OnDrawGizmos()
Gizmos.DrawIcon(transform.position,"item.png");
  3.小窗口的创建和显示,这里主要通过不同摄像机显示不同的layer来实现
using UnityE
using System.C
[AddComponentMenu("Game/MiniCamera")]
public class MiniCamera : MonoBehaviour
// Use this for initialization
void Start()
float ratio = (float)Screen.width / Screen.
this.GetComponent&Camera&().rect = new Rect(( 阅读(...) 评论()

参考资料

 

随机推荐