创建三个空物体,当作敌人生成地点,注意:三个空物体必须要在NavMeshAgent寻路系统烘培的网格路面内,否则即使创建了敌人,敌人也无法自动寻路进行巡逻。(这里就只制作一波怪了,若是要制作三波怪,可使用协程使创建敌人的方法在调用一次后,等待n秒后再次执行,血量的改变可用传参的方式。)
代码如下(GenerateEnemy脚本,仅供参考):
private void CreateEnemy()
{
int index = 0;
Vector3 vec = new Vector3(2, 2, 2);
enemy = new GameObject[3];
nav = new NavMeshAgent[3];
ani = new Animator[3];
enemyLoc = new Vector3[3];
for (int i = 0; i < 3; i++)
{
enemy[i] = Instantiate(EnemyType[Random.Range(0,3)], EnemyBirthLocal[i].position, Quaternion.identity);
nav[i] = enemy[i].AddComponent<NavMeshAgent>();
enemy[i].transform.localScale = vec;
enemyLoc[i] = enemy[i].transform.position;
//获取角色的Animator组件
ani[i] = enemy[i].GetComponent<Animator>();
}
}
private IEnumerator NavFindRoad()
{
int num = IsFindRole();
bool jude = false;
for (int x = 0; x < 3; x++)
{
if (findNum[x] == num)
{
jude = true;
}
}
if (!jude && num != -1)
{
findNum[num] = num;
jude = false;
}
for (int i = 0; i < nav.Count; i++)
{
if (findNum[i] != i)
{
//Debug.Log(Vector3.Distance(enemy[i].transform.position, EnemyBirthLocal[i].position));
if (Vector3.Distance(enemy[i].transform.position, EnemyBirthLocal[i].position) < 0.5f)
{
nav[i].SetDestination(Target[i].position);
}
yield return new WaitForSeconds(3);
if (Vector3.Distance(enemy[i].transform.position, Target[i].position) < 0.5f)
{
nav[i].SetDestination(EnemyBirthLocal[i].position);
}
}
else nav[i].SetDestination(role.transform.position-new Vector3(0,0,3));
}
}
向量点乘
private int IsFindRole()
{
Vector3 target = role.transform.position;
Vector3 enemyPos;
for (int i = 0; i < enemy.Count; i++)
{
enemyPos = enemy[i].transform.position;
target -= enemyPos;
float angle = Vector3.Dot(enemy[i].transform.forward.normalized, target.normalized) * Mathf.Rad2Deg;
//如果角度小于60度,那么就进行距离的判断
if (angle < 60)
{
float distance = Vector3.Distance(enemyPos, role.transform.position);
if (distance < 3)
{
//所有条件都满足,将敌人的寻路目标更改为角色
return i;
}
}
}
return -1;
}
public static int Blood { get; set; }
在生成敌人脚本(GenerateEnemy)当中添加一个静态属性血量
public static int[] Blood { get; set; }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SetBlood : MonoBehaviour
{
//角色血量
public int RoleBlood;
private int nowBlood;
//敌人血量,用于外部设置
public int[] EnemyBlood;
//敌人血量,用于传递给RoleCollier脚本,设置血条
public static int[] defEnemyBlood;
private int[] nowEnemyBlood;
private Slider roleSlider;
//当设置为不启用时,Find方法是无法查找的,所以添加一个静态方法返回
private static Slider enemySlider;
///
/// 获取默认血量,即初始最大血量
///
/// 血量数量,即敌人数量
///
private static void SetdefEnemyBlood(int Bloodsize,int[] Blood)
{
defEnemyBlood = new int[Bloodsize];
for (int i=0;i<Bloodsize;i++)
{
defEnemyBlood[i] = Blood[i];
}
}
public static int[] GetdefEnemyBlood()
{
return defEnemyBlood;
}
public static Slider GetEnemySlider()
{
return enemySlider;
}
private void Start()
{
roleSlider = GameObject.Find("RoleBlood").GetComponent<Slider>();
//只有当角色和敌人发生碰撞,血量才显示,所以获取组件设置为不启用
enemySlider = GameObject.Find("EnemyBlood").GetComponent<Slider>();
enemySlider.gameObject.SetActive(false);
SetdefEnemyBlood(EnemyBlood.Length,EnemyBlood);
SetRoleBlood();
}
private void Update()
{
SetNowBlood();
}
//设置初始血量
private void SetRoleBlood()
{
//设置角色血量
CreateRole.Blood = RoleBlood;
roleSlider.maxValue = RoleBlood;
roleSlider.value = RoleBlood;
//设置敌人血量
// yield return new WaitForSeconds(2);
for (int i=0;i<EnemyBlood.Length;i++)
{
GenerateEnemy.Blood[i] = EnemyBlood[i];
}
}
//设置目前血量,受到攻击开始减血
private void SetNowBlood()
{
//设置目前角色血量
nowBlood = CreateRole.Blood;
roleSlider.value = nowBlood;
//设置目前敌人血量(被攻击的敌人)
//当角色与敌人发生碰撞时,才会显示出此敌人的血量
//所以敌人血量的设置,我们将它放在碰撞接触方法当中
}
}
Unity3D----物理引擎(刚体、碰撞器、触发器)
enemy[i].name = enemy[i].name + i;
//给敌人添加刚体和碰撞器组件,并勾选isKinematic属性
//在GenerateEnemy脚本中的生成敌人方法中添加
box = enemy[i].AddComponent<Rigidbody>();
enemy[i].AddComponent<BoxCollider>();
box.isKinematic = false;
box = enemy[i].AddComponent<Rigidbody>();
BoxCollider b= enemy[i].AddComponent<BoxCollider>();
//调整碰撞体位置,防止和地面接触
b.center = new Vector3(0, 0.6f, 0);
box.isKinematic = false;
//不约束的话,敌人会被你直接撞飞
box.constraints = RigidbodyConstraints.FreeAll;
//在CreateRole脚本中的生成角色方法中添加
//给创建的角色添加碰撞器组件,刚体组件
ro.AddComponent<BoxCollider>();
Rigidbody rig=ro.AddComponent<Rigidbody>();
rig.useGravity = false;
rig.isKinematic = false;
rig.constraints = RigidbodyConstraints.FreezeAll;
//调整碰撞体位置,避免与地面发生碰撞
ro.GetComponent<BoxCollider>().center = new Vector3(0,1.5f,0);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RoleCollier : MonoBehaviour
{
//角色攻击力
private int attack = 1;
//敌人名字
private string enemyName;
//获取敌人血量组件Slider
private Slider enemySlider;
//用于存储敌人默认血量
private int[] defaultEnemyBlood;
private Animation ani;
//骷髅动画组件
private Animator ator;
//当角色与骷髅发生碰撞时,并且角色在播放攻击动画,那么骷髅扣血
private void OnCollisionEnter(Collision collision)
{
//获取敌人名字的最后一个字符,并将其转换为int型
enemyName = collision.gameObject.name;
ator = collision.gameObject.GetComponent<Animator>();
int enemyNum;
//只有当播放攻击动画时,才能够进行扣血,所以要获取动画组件
if (enemyName.Contains("skelet")&&ani.IsPlaying("Attack01"))
{
enemyNum=int.Parse(enemyName.Substring(enemyName.Length - 1));
Debug.Log(GenerateEnemy.Blood[enemyNum]);
GenerateEnemy.Blood[enemyNum] -= attack;
Debug.Log(GenerateEnemy.Blood[enemyNum]);
enemySlider.maxValue = defaultEnemyBlood[enemyNum];
enemySlider.value = GenerateEnemy.Blood[enemyNum];
enemySlider.gameObject.SetActive(true);
//当骷髅血量为0时,播放死亡动画,且销毁骷髅
if (GenerateEnemy.Blood[enemyNum]<=0)
{
ator.SetBool("died",true);
AnimatorStateInfo animatorInfo;
animatorInfo = ator.GetCurrentAnimatorStateInfo(0);
if (animatorInfo.normalizedTime>=1.0f)
{
//在销毁敌人物体后,可以添加掉落物品加buff功能(未实现)
//有兴趣的可以自行实现
Destroy(collision.gameObject);
}
}
}
}
private void Start()
{
enemySlider = SetBlood.GetEnemySlider();
defaultEnemyBlood = new int[GenerateEnemy.Blood.Length];
ani = this.GetComponent<Animation>();
//设置敌人默认血量
int[] Blood = SetBlood.GetdefEnemyBlood();
for (int i=0;i<defaultEnemyBlood.Length;i++)
{
defaultEnemyBlood[i] = Blood[i];
}
}
}
EnemyCollier脚本,仅供参考
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyCollier : MonoBehaviour
{
private Animator ani;
private int attack = 1;
private void Start()
{
ani = GetComponent<Animator>();
}
private void OnCollisionEnter(Collision collision)
{
//自身位置与角色距离小于2进行攻击
float distance = Vector3.Distance(transform.position,collision.transform.position);
if (distance<2)
{
ani.SetLayerWeight(1,1.0f);
CreateRole.Blood -= attack;
}
}
}
所有代码