一、游戏场景
二、创建怪物
CreateMonster
using UnityEngine;
using System.Collections;
public class CreateMonster : MonoBehaviour {
//产生的怪物预制体
public GameObject Monster;
//目标位置
public Transform TargetPositon;
//创建时播放的声音文件
public AudioClip CreateClip;
AudioSource AudioSource;
//最长刷怪时长
float MaxColdDownTime = 10;
//最短帅怪时长
float MinColdDownTime = 4;
float CurrentColdDownTime;
void Start()
{
//初始化下次刷怪事件
CurrentColdDownTime = MinColdDownTime;
//获取AudioSource属性
AudioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update () {
//通过Time.deltaTime来获取每一帧执行的时间
CurrentColdDownTime -= Time.deltaTime;
//当冷却时间完成后创建怪物并减少刷怪冷却时间
if (CurrentColdDownTime <= 0)
{
InstantiateMonster();
CurrentColdDownTime = MaxColdDownTime;
if (MaxColdDownTime > MinColdDownTime)
{
MaxColdDownTime -= 0.5f;
}
}
}
void InstantiateMonster()
{
//播放怪物吼叫声音
AudioSource.PlayOneShot(CreateClip);
//根据预制体创建怪物
GameObject go = Instantiate(Monster);
//将创建出来的怪物放置到自己下面,方便管理
go.transform.parent = this.transform;
//通过Random类随机放置怪物在传送门口
go.transform.position = this.transform.position + new Vector3(Random.Range(-5, 5), 0, Random.Range(-2.5f, 2.5f));
go.GetComponent<EnermyController>().TargetTransform = TargetPositon;
}
}
三、给怪物添加自动寻路
四、给怪物添加动画
五、怪物行为控制
using UnityEngine;
using System.Collections;
public class EnermyController : MonoBehaviour {
//目标位置
public Transform TargetTransform;
//总血量
int HP = 2;
//导航组件
UnityEngine.AI.NavMeshAgent NavMeshAgent;
//动画组件
Animator Animator;
// Use this for initialization
void Start () {
//初始化变量
NavMeshAgent = GetComponent<UnityEngine.AI.NavMeshAgent>();
NavMeshAgent.SetDestination(TargetTransform.transform.position);
Animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
//死亡直接返回
if (HP <= 0)
{
return;
}
//获取当前动画信息
AnimatorStateInfo stateInfo = Animator.GetCurrentAnimatorStateInfo(0);
//判断当前的动画状态是什么,并进行对应的处理
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Run") && !Animator.IsInTransition(0))
{
Animator.SetBool("Run", false);
//玩家有移动重新检测,目前不会移动
if (Vector3.Distance(TargetTransform.transform.position, NavMeshAgent.destination) > 1)
{
NavMeshAgent.SetDestination(TargetTransform.transform.position);
}
//进入攻击距离跳转到攻击动画,否则继续跑动
if (NavMeshAgent.remainingDistance < 3)
{
Animator.SetBool("Attack",true);
}
else
{
Animator.SetBool("Run", true);
}
}
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Attack") && !Animator.IsInTransition(0))
{
Animator.SetBool("Attack", false);
//玩家有移动重新检测,目前不会移动
if (Vector3.Distance(TargetTransform.transform.position, NavMeshAgent.destination) > 1)
{
NavMeshAgent.SetDestination(TargetTransform.transform.position);
}
//进入攻击距离跳转到攻击动画,否则继续跑动
if (NavMeshAgent.remainingDistance < 3)
{
Animator.SetBool("Attack", true);
NavMeshAgent.Stop();
}
else
{
Animator.SetBool("Run", true);
}
//if (stateInfo.normalizedTime >= 1.0f)
//{
// Manager.Instance.UnderAttack();
//}
}
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.Damage") && !Animator.IsInTransition(0))
{
Animator.SetBool("Attack", false);
Animator.SetBool("Run", false);
//玩家有移动重新检测,目前不会移动
if (Vector3.Distance(TargetTransform.transform.position, NavMeshAgent.destination) > 1)
{
NavMeshAgent.SetDestination(TargetTransform.transform.position);
}
//进入攻击距离跳转到攻击动画,否则继续跑动
if (NavMeshAgent.remainingDistance < 3)
{
Animator.SetBool("Attack", true);
NavMeshAgent.Stop();
}
else
{
Animator.SetBool("Run", true);
}
}
}
//当被枪击中时调用
public void UnderAttack()
{
//扣血并判断是否死亡,如果死亡则直接跳到死亡动画,否则跳到受伤动画
HP--;
if (HP <= 0)
{
Animator.Play("Death");
Destroy(GetComponent<Collider>());
Destroy(GetComponent<UnityEngine.AI.NavMeshAgent>());
}
else
{
Animator.Play("Damage");
}
}
//怪物攻击由动画事件调用
public void Attack()
{
Manager.Instance.UnderAttack();
}
}
六、游戏管理类
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour {
//Manager单例
public static Manager Instance;
//当前玩家HP
public int CurrentHP = 10;
//添加传送门和重玩引用
public GameObject Portals;
public GameObject Replay;
// Use this for initialization
void Awake () {
//实现单例
if (Instance == null)
{
Instance = this;
}
else
{
Debug.LogError("仅有一个Manager");
}
}
//收到怪物攻击
public void UnderAttack () {
CurrentHP--;
//如果血量小于0游戏失败
if(CurrentHP < 0)
{
EndGame();
}
}
void EndGame()
{
Destroy(Portals);
Replay.SetActive(true);
}
//重新开始游戏
public void ReStartGame()
{
SceneManager.LoadScene("FPS");
//Application.LoadLevel("FPS");
}
}
七、怪物攻击
八、主角攻击
1、添加手枪模型
2、剩余子弹
3、添加开枪动画
4、实现开枪逻辑
using UnityEngine;
using System.Collections;
public class GunShoot : MonoBehaviour {
//添加引用
public Animator Animator;
public Transform GunPoint;
public GameObject Spark;
public TextMesh textMesh;
public AudioClip Fire;
public AudioClip Reload;
AudioSource AudioSource;
bool isReloading = false;
int maxBullet = 12;
int currnetBullet;
SteamVR_TrackedController SteamVR_TrackedController;
// Use this for initialization
void Start () {
//创建监听
SteamVR_TrackedController = GetComponent<SteamVR_TrackedController>();
SteamVR_TrackedController.TriggerClicked += TriggerClicked;
SteamVR_TrackedController.Gripped += Gripped;
currnetBullet = maxBullet;
AudioSource = GetComponent<AudioSource>();
}
//扳机扣下时的开枪逻辑
void TriggerClicked(object sender, ClickedEventArgs e)
{
//如果在换弹中直接返回
if (isReloading)
{
return;
}
//如果没有子弹也直接返回
if (currnetBullet > 0)
{
currnetBullet --;
textMesh.text = currnetBullet.ToString();
}
else
{
return;
}
//播放开枪声音
AudioSource.PlayOneShot(Fire);
Animator.Play("PistolAnimation");
Debug.DrawRay(GunPoint.position, GunPoint.up*100, Color.red, 0.02f);
Ray raycast = new Ray(GunPoint.position, GunPoint.up);
RaycastHit hit;
//根据Layer来判断是否有物体击中
LayerMask layer = 1<<( LayerMask.NameToLayer("Enermy"));
bool bHit = Physics.Raycast(raycast, out hit,10000,layer.value);
//击中扣血逻辑
if (bHit)
{
Debug.Log(hit.collider.gameObject);
EnermyController ec = hit.collider.gameObject.GetComponent<EnermyController>();
if (ec != null)
{
ec.UnderAttack();
GameObject go = GameObject.Instantiate(Spark);
go.transform.position = hit.point;
Destroy(go, 3);
}
else
{
Manager.Instance.ReStartGame();
}
}
}
//手柄握下的逻辑
void Gripped(object sender, ClickedEventArgs e)
{
if (isReloading)
{
return;
}
isReloading = true;
Invoke("ReloadFinished", 2);
AudioSource.PlayOneShot(Reload);
}
//换弹结束
void ReloadFinished()
{
isReloading = false;
currnetBullet = maxBullet;
textMesh.text = currnetBullet.ToString();
}
}
5、设置怪物层级
九、游戏重新开始
Paste_Image.png
网友评论