项目文件找出来了,老版本的脚本有报错,我在新版2019.4.21f1c1下解决了报错,战斗场景可以正常跑的。
需要的同学点下面地址下载(关注就行啦不用积分),祝大家都早日学成
————————————————————————
今天没有做太多内容,只是在昨天的基础上增加了战斗伤害数值的显示及动画,因为又涉及到了之前UI控制相关的脚本,就顺便把这一块做了优化,效果请看Gif
接下来就是本文主要内容:集中介绍血条及伤害数值的实现及脚本
1. 血条
首先是制作一个血条的预制体,由底图、血条图和文本组成,其中文本用来显示单位名字,如下图,其中血条图片的Image Type设置成Filled
之前是用一个BattleUIManager完成了血条的所有操作,内容比较乱,这边做了优化,只用它来负责实例化脚本,并给脚本设置好“主人”,之后的血条状态由它自身的BloodUpdate函数根据主人的状态来更新。
新的BattleUIManager如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class BattleUIManager : MonoBehaviour {
//把做好的预制体赋给这个变量
public GameObject bloodBar;
//玩家和怪物的数组
private GameObject[] playerUnits;
private GameObject[] enemyUnits;
//统一调整血条的偏移量
public float bloodXOffeset;
public float bloodYOffeset;
public float bloodZOffeset;
void Start ()
{
//搜索所有参战的玩家对象,逐个创建血条
playerUnits = GameObject.FindGameObjectsWithTag("PlayerUnit");
foreach (GameObject playerUnit in playerUnits)
{
GameObject playerBloodBar = Instantiate(bloodBar) as GameObject;
//实例化后设置到正确的画布分组里,便于管理也保证能正常显示
playerBloodBar.transform.SetParent(GameObject.Find("BloodBarGroup").transform, false);
//设置血条的主人,BloodUpdate将根据这个主人的状态来更新血条
playerBloodBar.GetComponent<BloodUpdate>().owner = playerUnit;
}
//搜索所有参战的怪物对象,逐个创建血条
enemyUnits = GameObject.FindGameObjectsWithTag("EnemyUnit");
foreach (GameObject enemyUnit in enemyUnits)
{
GameObject enemyBloodBar = Instantiate(bloodBar) as GameObject;
enemyBloodBar.transform.SetParent(GameObject.Find("BloodBarGroup").transform, false);
//设置血条的主人,BloodUpdate将根据这个主人的状态来更新血条
enemyBloodBar.GetComponent<BloodUpdate>().owner = enemyUnit;
}
}
//供按钮调用的函数,此处可忽略
public void GoToScene(string name)
{
SceneManager.LoadScene(name);
}
}
血条预制体上挂的BloodUpdate脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BloodUpdate : MonoBehaviour {
//血条的主人,在创建时会通过BattleUIManager赋值
public GameObject owner;
//血条的长度数值,1为满格
private Image ownerBloodFill;
//获取UI控制脚本的引用,要从它那里获取统一的偏移量
private BattleUIManager uiManager;
//主人的3D空间位置
private Vector3 playerBlood3DPosition;
//将主人的3D位置映射到屏幕之后的2D位置
private Vector2 playerBlood2DPosition;
void Start()
{
//显示血条主人的名字
Text ownerText = gameObject.transform.Find("OwnerName").GetComponent<Text>();
ownerText.text = owner.name;
//获取UI控制脚本的引用
uiManager = GameObject.Find("BattleUIManager").GetComponent<BattleUIManager>();
}
void Update()
{
if (owner.tag=="PlayerUnit" || owner.tag == "EnemyUnit")
{
//更新血条长度
ownerBloodFill = gameObject.transform.Find("BloodFill").GetComponent<Image>();
ownerBloodFill.fillAmount = owner.GetComponent<UnitStats>().bloodPercent; //bloodPercent在每个单位的UnitStats脚本中存储
//更新血条位置
//获取当前主人的空间位置,然后转换为2D屏幕位置
playerBlood3DPosition = owner.transform.position + new Vector3(uiManager.bloodXOffeset, uiManager.bloodYOffeset, uiManager.bloodZOffeset);
playerBlood2DPosition = Camera.main.WorldToScreenPoint(playerBlood3DPosition);
gameObject.GetComponent<RectTransform>().position = playerBlood2DPosition;
}
//如果主人死了,则设置为未激活状态
if (owner.GetComponent<UnitStats>().IsDead())
{
gameObject.SetActive(false);
}
}
}
这样血条的生成、跟随和更新就全部实现了。
2. 伤害数值
伤害值的实现跟血条类似,也是先完成预制体,然后我给伤害文本制作了一个放大出现,并渐变消失的过程动画,字体的移动是通过脚本来实现的。
伤害值的生成直接放到了回合控制脚本中,在执行ReceiveDamage之后立即生成;
//被攻击者承受伤害
currentActUnitTarget.GetComponent<UnitStats>().ReceiveDamage(attackData);
//实例化伤害字体并设置到画布上(字体位置和内容的控制放在它自身的脚本中)
GameObject thisText = Instantiate(bloodText) as GameObject;
thisText.transform.SetParent(GameObject.Find("BloodTextGroup").transform, false);
还是跟血条一样的管理,生成后立即设置到正确的画布分组中;
以下是挂在伤害值预制体上的DamageFloatUp脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DamageFloatUp : MonoBehaviour {
private BattleTurnSystem turnScript; //回合控脚本的引用
//受到伤害单位的位置
private Vector3 takeDamageUnit3DPosition;
private Vector2 takeDamageUnit2DPosition;
void Start ()
{
turnScript = GameObject.Find("BattleManager").GetComponent<BattleTurnSystem>(); //查找引用
//计算伤害者的3D位置并转化为屏幕2D位置
takeDamageUnit3DPosition = turnScript.currentActUnitTarget.transform.position + new Vector3(0,1,0); //适当上移修正位置
takeDamageUnit2DPosition = Camera.main.WorldToScreenPoint(takeDamageUnit3DPosition);
gameObject.GetComponent<RectTransform>().position = takeDamageUnit2DPosition;
//设置数字内容
gameObject.GetComponent<Text>().text = "-"+ turnScript.attackData;
//延迟销毁自身
StartCoroutine("WaitAndDestory");
}
void Update () {
//向上漂浮控制
gameObject.GetComponent<RectTransform>().anchoredPosition = gameObject.GetComponent<RectTransform>().anchoredPosition + new Vector2(0, 1);
}
//延迟销毁
IEnumerator WaitAndDestory()
{
yield return new WaitForSeconds(1.5f);
Destroy(gameObject);
}
}
以上