第19天在Unity中创建Player Health System和Health UI

在我们目前的游戏状态下,我们可以击败敌人,但是我们永远不会失败。

今天在第19天,我们将开始处理代码以解决此问题。

第一步,我们将为玩家创建健康状况和健康状况栏,以便我们可以接收伤害并知道何时会丢失。

没有任何延迟,让我们开始吧!

创建健康系统时,我们应该做的第一件事就是为我们的健康创建UI。

就像任何UI元素一样,我们将使用Unity的UI系统来创建运行状况栏,特别是,我们将使用Unity的Slider

我们已经有一个名为UID的现有UI画布,右键单击它,然后选择UI-> Slider创建一个新的Slider。 如果我们还没有UI Canvas,Unity将自动为我们创建它。

我们将把Slider重命名为Health Bar

现在,如果我们在具有层次结构的“ 场景”选项卡中进入2D模式,您将拥有类似的内容。

我们将需要对滑块进行一些调整以使其看起来更好。

首先,我们不需要滑动条。 删除手柄滑块区域。

接下来,选择“运行状况栏”,然后在“ 滑块(脚本)”组件区域中,将“ 最大值”设置为100。

我们的值是0,但我们的小节仍然存在。 另外,如果我们将值移动到100,则整个条形也不会被填充。

我找到了一个很好的答案,关于如何使滑块变空。

要进行所需的调整,我们必须:

  1. 填充 宽度设置为0
  2. 转到“ 填充区域”并拖动栏,直到它适合背景。 在我的情况下,我的最终值为Pos X :75, Width:160 ,其余值保留为默认值。

这是现在的样子:

但是现在还有另一个问题,如果将滑块的值设置为1,则将得到以下结果:

请注意,填充栏如何位于实际栏本身的右侧。

不幸的是,似乎没有答案可以为我解决问题。 这可能是Unity问题中最重要的问题。

但是,这并不意味着我们会放弃。

我们可以像在Survival Shooter教程中可能从未注意到的那样简单地对其进行修复:我们将扩展滑块的背景,以便该条自然看起来是正确的。

为此,我们转到“ 背景” ,然后将“ 左” ,“ 上”,“右”和“下”更改为-3

之后,我们应该有如下内容:

好多了吧? 没有什么看起来不合适!

现在,我们的健康栏看起来更好了,是时候将其移到左下角了。 选择Health Bar ,转到Rect Transform组件,单击正方形,打开UI对齐方式,然后按Shift + Ctrl,然后左键单击左下角的选项将所有内容移动到左下角。

现在,所有内容都恰好位于左下角,看起来不太好。 让我们添加一些添加。

单击“运行状况栏”,然后将“点X”设置为15 ,将“点Y”设置为10。

完成后,您的游戏现在应该像这样(不要忘记将滑块值设置为100)!

现在我们有了UI健康状​​况栏,是时候编写一些代码来创建播放器的健康状况了。

首先,单击我们的Player游戏对象并创建一个名为PlayerHealth的新脚本 此脚本将在玩家受到伤害时控制他们的健康,然后在我们的健康栏中显示这些更改。

这是我们的PlayerHealth脚本的样子:

  [csharp]使用UnityEngine;
使用UnityEngine.UI;公共类PlayerHealth:MonoBehaviour
 {
    公共Slider HealthBar;
    公众持股量= 100; 私人浮点数_currentHealth; 无效开始()
     {
         _currentHealth =健康;
     } public void TakeDamage(浮动损坏)
     {
         _currentHealth-=伤害;
         HealthBar.value = _currentHealth;
     }
 }
 [/ csharp] 

这是我们脚本的工作方式:

  1. 我们创建一个公共Slider,将其作为HealthBar 。 重要的是要注意,我们需要导入UI,否则编译器会向我们抱怨我们的Slider对象。
  2. 接下来,我们创建一个公共健康代表最大健康,_currentHealth代表玩家拥有多少健康。
  3. 在Start()中,我们将_currentHealth实例化为最大健康值。
  4. 最后,我们创建public TakeDamage() ,public意味着另一个脚本可以使用此组件并调用该函数。 在此函数内,我们获得了损坏金额,并更新了_currentHealth ,并且更改了滑块的值以反映健康损失。

在继续之前,请确保将HealthBar游戏对象拖到PlayerHealth脚本组件中。

像这样:

现在我们已经完成了设置,接下来需要做的是创建调用TakeDamage()的代码

对我们来说幸运的是,我们已经有一个脚本可以处理大多数此类问题: EnemyAttack。

我们需要做的就是获取新的PlayerHealth脚本的实例,然后运行遭受损失的代码。

  [csharp highlight =“ 57”]使用UnityEngine;
使用System.Collections;
公共课程EnemyAttack:MonoBehaviour
 {
    私人Animator _animator;
    私人GameObject _player;
    私人布尔_collidedWithPlayer; 无效Awake()
     {
         _player = GameObject.FindGameObjectWithTag(“ Player”);
         _animator = GetComponent ();
     } void OnTriggerEnter(对撞机其他)
     {
        如果(other.gameObject == _player)
         {
             _animator.SetBool(“ IsNearPlayer”,true);
         }
         print(“使用_player输入触发器”);
     } void OnCollisionEnter(Collision other)
     {
        如果(other.gameObject == _player)
         {
             _collidedWithPlayer = true;
         }
        打印(“输入与_player相撞”);
     } void OnCollisionExit(Collision other)
     {
        如果(other.gameObject == _player)
         {
             _collidedWithPlayer = false;
         }
         print(“退出与_player相撞”);
     } void OnTriggerExit(Collider other)
     {
        如果(other.gameObject == _player)
         {
             _animator.SetBool(“ IsNearPlayer”,false);
         }
         print(“使用_player退出触发器”);
     } private void Attack()
     {
        如果(_collidedWithPlayer)
         {
             _player.GetComponent ()。TakeDamage(10);
         }
     }
 }
 [/ csharp] 

在脚本中,我们已经可以访问播放器并进行攻击检测,因此,我们需要做的就是抓取PlayerHealth脚本,并在EnemyAttack中调用Attack()时触发TakeDamage函数

您可能还记得以前的教程,这段代码的工作方式是:

  1. 我们有一个触发对撞机,可以检测我们的骑士何时应该开始进攻
  2. 然后我们的播放器上有一个网格碰撞器,它将检测我们何时触摸播放器
  3. 最后,在动画中,我们设置了一个时间点来调用Attack() ,当发生这种情况时,如果骑士仍然与我们的玩家接触,我们将受到伤害。

这样,我们就拥有了完整游戏所需的一切,或者您可能会认为

如果您现在要玩游戏,可能会遇到一个直到现在才意识到的新问题:

如果我们要在看游戏机时玩游戏。 每当我们撞上骑士时,我们都会击中OnColliderEnter() ,然后由于某种原因运行OnColliderExit(),即使我们不移动玩家也是如此。

结果,如果玩家永远不动,他们只会受到一次伤害。 无聊的感觉如何?

我们明天会解决这个问题,因为今天已经很晚了。

今天在第19天,我们创建了一个健康系统,使我们的玩家可以从我们现有的敌人攻击代码中受到伤害。

我们差不多完成了,但是我们遇到了一个问题,即使敌人似乎成功攻击了我们,敌人也不再伤害我们。

我知道问题是什么,但是明天我们将再讨论更多!

资料来源:第19天

访问Unity VR开发的100天主页。

访问我们的主页