[unity learning] RPG Leaning(十)
写这个文章的目的就是为了初学unity,然后更好的掌握unity中的内容【主要是代码】
学习unity的途径是Brackeys 的教程;
接上篇: unity learning RPG Leaning(九).
关于这个系列的最后一篇
目的
一、加入Player和Enemy的血条
二、把模型变成骷髅头
三、把骷髅动画导入
四、攻击时延
一、加入Player和Enemy的血条
1、创建Canvas ,设置RenderMode为World Space;
创建两个Image,设置两个Image的顺序如下图所示
设置两个Image的参数如下图所示。
设置底层的Image的ImageType为Fill来用FillAmount来控制绿色血条的进度。
设置红色的血条如下图所示
把这个变成prefab,然后删除这个Healthui。
2、需要为每一个角色创建血条,所以新建一个healthUI类;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class healthUI : MonoBehaviour
{
public GameObject uiPrefab;
public Transform target;
Transform ui;
Image healthSlider;
Transform cam;
// Start is called before the first frame update
void Start()
{
cam = Camera.main.transform;
foreach (Canvas c in FindObjectsOfType<Canvas>())
{
if (c.renderMode == RenderMode.WorldSpace)
{
ui = Instantiate(uiPrefab, c.transform).transform;
healthSlider = ui.GetChild(0).GetComponent<Image>();
break;
}
}
}
void LateUpdate()
{
ui.position = target.position;
ui.forward = -cam.forward;
}
}
然后把这个组件导入到Player和Enemy中,设置Ui Prefab为我们创建的Prefab,
在Player下面创建一个Empty物体,名字为Health UI,把这个放入到target中。
3、设置血条变化
在CharacterStats中设置委托
public System.Action<int, int> OnHealthChanged;
public void TakeDamage(int damage)
{
...
if (OnHealthChanged != null) {
OnHealthChanged(maxHealth, currentHealth);
}
}
在HealthUI中调用改委托。
...
[RequireComponent(typeof(CharacterStats))]
....
void Start()
{
...
GetComponent<CharacterStats>().OnHealthChanged += OnHealthChanged;
}
void OnHealthChanged(int max, int current) {
if (ui != null) { //由于ui会被消灭,所以这里加上了ui!=null,同时在LateUpdate中也需如此。
float healthPercent = (float)current / max;
healthSlider.fillAmount = healthPercent;
if (current < 0)
{
Destroy(ui.gameObject);
}
}
}
4、设置血条出现和消失
...
float visibleTime = 5f;
float lastChangeTime;
// Start is called before the first frame update
void Start()
{ ...
ui.gameObject.SetActive(false); //一开始设置血条为不可见
}
void OnHealthChanged(int max, int current) {
if (ui != null) {
ui.gameObject.SetActive(true);
lastChangeTime = Time.time;
...
}
}
void LateUpdate()
{
if (ui != null)
{
...
if (Time.time - lastChangeTime>visibleTime) {
ui.gameObject.SetActive(false);
}
}
}
二、把模型变成骷髅头
导入模型,设置骨架Rig
设置Idle、walk、combat_idle的LoopTime设置为开启。
三、把骷髅动画导入
create一个animator Override Controller,命名为Enemy Controll,把之前的animator Controller:PlayerController放入到animator Override Controller之中。然后把一些动画导入。设置模型的动画为PlayerController。
然后修改Player Animation。由于Player Animation中已经有了AnimatorOverrideController类,所以,我们只需要修改AnimatorOverrideController。
把它变成公开变量。
public AnimatorOverrideController overrideController;
protected virtual void Start()
{
if (overrideController == null)
{
overrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);
}
把他放到enemy中,配置Player Animation。
动画导入完成。
四、攻击时延
之前,我们设置攻击时延,使用的是
StartCoroutine(DoDamage(targetStats, attackDelay));
我们现在去掉这个时延,用动作设置的时间来造成伤害。
设置一个CharacterCombatReceiver,设置CharacterCombat为公开变量,
设置一个函数AttackEvent()来调用combat下面的AttackHit_AnimationEvent()函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterCombatReceiver : MonoBehaviour
{
public CharacterCombat combat;
public void AttackEvent() {
combat.AttackHit_AnimationEvent();
}
}
设置 AttackHit_AnimationEvent()函数,把伤害放置在AttackHit_AnimationEvent函数中:
CharacterStats oppentStats;
public void Attack(CharacterStats targetStats)
{
if (attackCoolDown <= 0f)
{
oppentStats = targetStats;
...
}}
public void AttackHit_AnimationEvent() {
oppentStats.TakeDamage(myStats.damage.GetValue());
if (oppentStats.currentHealth <= 0)
{
Incombat = false;
}
}
在Attack类的攻击动作处设置Event:
就可以调用了这个AttackEvent