创建一个2d正方形(9-Sliced)命名为Player,在Player下面新建一个画布(Canvas)命名为PlayerHealthUI,在画布下面新建一个滑动条(Slider)命名为HealthBar
把PlayerHealthUI脚本挂载到PlayerHealthUI上,拖拽情况如图所示
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealthUI : MonoBehaviour
{
[SerializeField] private Slider healthBar;
[SerializeField] private Health health;
//更新血条方法(注意要写成公有的)
public void UpdateUI()
{
healthBar.value = health.Value;
}
//进入游戏的时候开启
private void Awake()
{
//起始值:血条UI的起始值=health的初始值
healthBar.maxValue = health.Value;
//更新:血条UI的现在值=health的初始值
healthBar.value = health.Value;
}
}
把playerMovement脚本,Health脚本,Damageable脚本,挂载到Player对象上,拖拽情况如图所示
using UnityEngine;
using UnityEngine.InputSystem;
using DG.Tweening;
public class playerMovement : MonoBehaviour
{
[SerializeField]private Rigidbody2D rb;
private Vector2 _inputDirection;
[SerializeField]private float _speed;
public void Move(InputAction.CallbackContext context)
{
_inputDirection = context.ReadValue<Vector2>();
}
private void FixedUpdate()
{
var position = (Vector2)transform.position;
var targetPosition = position + _inputDirection;
if (position == targetPosition) return;
rb.DOMove(targetPosition, _speed).SetSpeedBased();
}
}
using UnityEngine;
using UnityEngine.Events;
public class Health : MonoBehaviour
{
[SerializeField] private int health;
[SerializeField] private UnityEvent<int> healthchange;
public int Value
{
get { return health; }
}
//减少血量
public void DreaseHealth(int amount)
{
//血量减去被传进来的值
health -= amount;
healthchange.Invoke(health);
}
}
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Damageable : MonoBehaviour
{
[SerializeField]private Health health;
//想要实现被伤害时变红闪烁一下
[SerializeField]private SpriteRenderer spriteRenderer;
public void TakeDamage(int damage)
{
health.DreaseHealth(damage);
//在DG.Tweening包中,记得引入
//DOColor()需要的两个arguement:第一个是确定颜色,第二个是完成变换所需要的时间
//再变回去需要SetLoops(),两个arguemengt,一个是变换几圈,一个是以什么方式变
//红色到白色是一圈,红色到白色是另一圈
//Yoyo:慢慢变换
//还需要用ChangeStartValue()给一个起始颜色
spriteRenderer.DOColor(Color.red,0.2f)
.SetLoops(2,LoopType.Yoyo)
.ChangeStartValue(Color.white);
}
}
把Attack脚本和EnemyMovement脚本,挂载到Enemy对象上
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
[SerializeField] private Rigidbody2D rb;
[SerializeField] private float _speed;
[SerializeField]private PlayerManager playerManager;
private void FixedUpdate()
{
//玩家当前位置
var playPosition = playerManager.position;
//敌人自己当前位置坐标
var position=(Vector2)transform.position;
//当前距离距玩家位置(移动的方向)
var direction=playPosition-position;
//数字规范(方便计算)
direction.Normalize();
//目的坐标
var targetPosition = position + direction;
//向目的地移动
rb.DOMove(targetPosition, _speed).SetSpeedBased();
}
}
using UnityEngine;
using Timers;
public class Attack : MonoBehaviour
{
private bool _canAttack = true;
private void OnTriggerEnter2D(Collider2D col)
{
DealDamage(col);
}
private void OnTriggerStay2D(Collider2D other)
{
DealDamage(other);
}
private void CanAttack()
{
_canAttack=true;
}
private void DealDamage(Collider2D other)
{
if (!_canAttack) return;
//Player为标签
if (other.CompareTag("Player"))
{
var damageable = other.GetComponent<Damageable>();
damageable.TakeDamage(10);
//三个argument
TimersManager.SetTimer(this, 1, CanAttack);
_canAttack = false;
}
}
}
PlayerManager脚本挂载到空物体Manager上面
using UnityEngine;
//获取玩家位置
public class PlayerManager:MonoBehaviour
{
[SerializeField] private Transform playerTransform;
//任何脚本呼叫PlayerManager时,都可以获得玩家位置
public Vector2 position
{
get { return playerTransform.position; }
}
}