using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//使用AI命名空间
using UnityEngine.UI;//使用UI命名空间
/// <summary>
/// 玩家角色的AI实现思路:
/// 一.自动导航:
/// 1.需要using UnityEngine.AI
/// 2.需要获得玩角色身上的导航组件
/// 二、技能释放:
/// 1.技能对应的按键
/// 2.技能对应的图标(按钮)
/// 3.按键和图标的统一(按键和点击图标是一致的)
/// 4.技能的释放、销毁
/// 5.补兵
/// 三、动画控制
/// 1.需要获得角色动画控制者
/// 2.状态控制
/// 四实现上述要求的方法:
/// 1.角色状态控制
/// 2.操作者行为控制(按键、点图标)
/// </summary>
public class WarriorControl : MonoBehaviour
{
NavMeshAgent nav;//角色导航
Animator ani;//角色状态控制者
GameObject Cav_Skll;//技能按钮的父物体画布
Button Bu_Skill1;//Q技能按钮
Button Bu_Skill2;//W技能按钮
Image Im_Skill1;//Q技能的Image组件(图标)
Image Im_Skill2;//W技能的Image组件(图标
float life;//角色生命值
GameObject skill1;//技能1资源
GameObject Skill1;//生成的技能1
GameObject skill2;//技能2资源
GameObject Skill2;//生成的技能2
Transform SkillPos;//技能生成的位置
float sk1time;//技能1的冷却时间
float sk2time;//技能2的冷却时间
Vector3 TargetPos;//角色导航的下一个位置
GameObject Cv_P;//角色头顶血条、姓名的父物体画布
Image Im_Blood;//血条
// Use this for initialization
void Start()
{
//导航获取
if (GetComponent<NavMeshAgent>() == null)//如果角色身上没有导航
{
gameObject.AddComponent<NavMeshAgent>();//为角色添加导航
}
nav = GetComponent<NavMeshAgent>(); //获取角色身上导航
//动画控制者获取
if (GetComponent<Animator>() == null)//如果角色身上没有导航
{
gameObject.AddComponent<Animator>();//为角色添加导航
}
ani = GetComponent<Animator>(); //获取角色身上导航
//
Cav_Skll = GameObject.Find("CaV_Skill");
//技能按钮
Bu_Skill1 = Cav_Skll.transform.FindChild("Bu_Skill1").GetComponent<Button>();//获取技能1按钮组件
Bu_Skill1.onClick.AddListener(OnClickBu_Skill1);//响应按钮1点击事件
Bu_Skill2 = Cav_Skll.transform.FindChild("But_Skill2").GetComponent<Button>();//获取技能2按钮组件
Bu_Skill2.onClick.AddListener(OnClickBu_Skill2);//响应按钮2点击事件
//技能图标(冷却)
Im_Skill1 = Cav_Skll.transform.FindChild("Bu_Skill1").GetComponent<Image>();//Q技能图标
Im_Skill2 = Cav_Skll.transform.FindChild("But_Skill2").GetComponent<Image>();//W技能图标
//初始化角色生命值
life = 100;
//加载技能效果资源
skill1 = (GameObject)Resources.Load("MagicEffectsPackFree/prefab/skillAttack");
skill2 = (GameObject)Resources.Load("MagicEffectsPackFree/prefab/skillAttack2");
//技能产生位置
SkillPos = transform.FindChild("SkillPos");
//初始时角色播放发呆的动画
ani.Play("Idle");
//血条、昵称的父物体画布
Cv_P = transform.FindChild("Cv_P").gameObject;
//血条
Im_Blood = Cv_P.transform.FindChild("Im_blood").GetComponent<Image>();
}
// Update is called once per frame
void Update()
{
AddLifeControl();//调用生命值控制函数
AIControl();//调用角色控制函数
ReleaseSkill();//释放技能函数
Im_Blood.fillAmount = life / 100;//血条显示的血量等于生命值/100
Cv_P.transform.LookAt(Camera.main.transform.position);//血条、昵称时刻朝向主相机
}
/// <summary>
/// 技能1按钮点击事件
/// </summary>
void OnClickBu_Skill1()//点击Q技能图标(和按下Q键效果一致)
{
if (life > 0)//在角色生命值大于0的情况下
{
if (Im_Skill1.fillAmount >= 1)//如果技能1图标的fillAmount大于等于1
{
nav.Stop();//导航暂停
Im_Skill1.fillAmount = 0;//技能图标的fillAmount归零
ani.Play("Attack1");//播放攻击1动画(攻击1动画Event添加了回调函数,动画快结束时生成技能特效)
}
}
}
/// <summary>
/// 技能2按钮点击事件
/// </summary>
void OnClickBu_Skill2()
{
if (life > 0)
{
if (Im_Skill2.fillAmount >= 1)
{
nav.Stop();
Im_Skill2.fillAmount = 0;
ani.Play("Attack2");
}
}
}
/// <summary>
/// 生命值控制函数1:生命自增
/// </summary>
void AddLifeControl()
{
if (life < 100&&life>0)//如果生命值小于100大于0
{
life += Time.deltaTime * 0.01f;//生命自增
}
}
/// <summary>
/// 生命值控制函数2:生命减少
/// </summary>
public void SubLifeControl(float value)
{
life -= value;//生命值减少量
if (life<=0)//如果生命值小于0
{
ani.Play("Death");//播放死亡动画
Destroy(gameObject, 1);//1秒后销毁角色
}
}
/// <summary>
/// AI(导航)控制
/// </summary>
void AIControl()
{
if (life > 0)//在生命值大于的前提前下
{
if (Input.GetMouseButtonDown(1))//按下鼠标右键
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从相机发一条射线到鼠标的右键点击点
RaycastHit hit;
if (Physics.Raycast(ray, out hit))//如果射线碰到了(检测到了)点击点
{
if (hit.transform.tag.Equals("terian"))//如果点击点的标签是terian(地面)
{
nav.Resume();//导航恢复
ani.Play("Run");//播放跑的动画
TargetPos = hit.point;//记录射线碰撞点(鼠标点击点)的位置
nav.SetDestination(TargetPos);//导航到鼠标点击点
}
}
}
if (nav.remainingDistance <= 0.1f)//如果角色和目标点的距离小于0.1,就认为导航到了目的地
{
nav.Stop();//导航暂停
ani.Play("Idle");//播放发呆动画
}
}
}
/// <summary>
/// 释放技能函数
/// </summary>
void ReleaseSkill()
{
if (life<=100&&life>0)//在生命值小于100大于0的前提下
{
if (Input.GetKeyDown(KeyCode.Q))//如果按下Q键(点击Q技能图标效果一致)
{
print("按下Q键");
if (Im_Skill1.fillAmount >= 1)
{
nav.Stop();
Im_Skill1.fillAmount = 0;
ani.Play("Attack1");
print("释放Q技能");
}
}
if (Input.GetKeyDown(KeyCode.W))
{
if (Im_Skill2.fillAmount >= 1)
{
nav.Stop();
Im_Skill2.fillAmount = 0;
ani.Play("Attack2");
}
}
//两个技能图标的冷却显示
if (Im_Skill1.fillAmount <= 1)//如果技能1图标的fillAmount小于等于1
{
Im_Skill1.fillAmount += Time.deltaTime;//技能1图标的fillAmount自增(1秒就冷却完毕)
}
if (Im_Skill2.fillAmount <= 1)
{
Im_Skill2.fillAmount += Time.deltaTime / 3;//3秒冷却完毕
}
}
}
/// <summary>
/// 两个技能动画的回调函数
/// </summary>
void OnAttack1End()//攻击1动画的Event回调函数
{
Skill1 = Instantiate(skill1, SkillPos.position, SkillPos.rotation);//在技能生成点生成技能1
Destroy(Skill1, 1);//一秒后销毁技能1
ani.Play("Idle");//播放发呆动画
}
void OnAttack2End()
{
Skill2 = Instantiate(skill2, SkillPos.position, SkillPos.rotation);
Destroy(Skill2, 1);
ani.Play("Idle");
}
}