物品若无法拾取也不会阻碍人物行动,所以设置为Is Trigger。
上代码
Helper.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 帮助类
/// </summary>
public class Helper : MonoBehaviour
{
// 获取Collider2D collision所对应的PlayerHealthChange
public static PlayerHealthChange GetPlayerByCollider2D(Collider2D collision)
{
return collision.gameObject.GetComponent<PlayerHealthChange>();
}
// 调整GameObject obj的不透明度为a
public static void SetOpaquenessOfGameObject(GameObject obj, float a)
{
Color c = obj.GetComponent<SpriteRenderer>().material.color;
c.a = a;
obj.GetComponent<SpriteRenderer>().material.color = c;
}
}
Resource.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 可拾取资源
/// </summary>
public class Resource : MonoBehaviour
{
private int healthChangeValue;
void Start()
{
if (tag == "Pepper") healthChangeValue = -1;
else if (tag == "Mushroom") healthChangeValue = 1;
}
void Update()
{
}
// 触碰玩家
private void OnTriggerEnter2D(Collider2D collision)
{
PlayerHealthChange p = Helper.GetPlayerByCollider2D(collision);
if (p == null)
return;
if (healthChangeValue >= 0)
{
if (p.GetHealth == p.GetMaxHealth)
return;
p.HealthChange(healthChangeValue);
Destroy(gameObject);
}
else
{
p.HealthChange(healthChangeValue);
Destroy(gameObject);
}
}
}
PlayerHealthChange.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 人物血量变化
/// </summary>
public class PlayerHealthChange : MonoBehaviour
{
float maxHealth;
float health;
public float GetHealth { get { return health; } }
public float GetMaxHealth { get { return maxHealth; } }
bool invincible;
float invincibleTime = 2f;
float invincibleTimer;
void Start()
{
invincible = false;
maxHealth = 5;
health = 3;
Debug.Log("health is " + health);
}
void Update()
{
if (invincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer <= 0)
{
ChangeToVincible();
}
}
}
public void HealthChange(float value)
{
if (value >= 0)
{
Debug.Log(health + " to " + Mathf.Clamp(health + value, 0, maxHealth));
health = Mathf.Clamp(health + value, 0, maxHealth);
}
else if(invincible)
{
return;
}
else
{
Debug.Log(health + " to " + Mathf.Clamp(health + value, 0, maxHealth));
health = Mathf.Clamp(health + value, 0, maxHealth);
invincible = true;
invincibleTimer = invincibleTime;
Helper.SetOpaquenessOfGameObject(gameObject, 0.5f);
}
}
private void ChangeToVincible()
{
invincible = false;
Helper.SetOpaquenessOfGameObject(gameObject, 1f);
}
}
上面运用了invincibleTimer -= Time.deltaTime来计时。
另外还有使用协程进行计时的方法(invoke听说不太好就不了解了):
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 人物血量变化
/// </summary>
public class PlayerHealthChange : MonoBehaviour
{
float maxHealth;
float health;
public float GetHealth { get { return health; } }
public float GetMaxHealth { get { return maxHealth; } }
bool invincible;
float invincibleTime = 2f;
void Start()
{
invincible = false;
maxHealth = 5;
health = 3;
Debug.Log("health is " + health);
}
void Update()
{
}
// 加血时检查是否满血
// 扣血后变为无敌状态,角色变为半透明,invincibleTime后恢复
public void HealthChange(float value)
{
if (value >= 0)
{
Debug.Log(health + " to " + Mathf.Clamp(health + value, 0, maxHealth));
health = Mathf.Clamp(health + value, 0, maxHealth);
}
else if(invincible)
{
return;
}
else
{
Debug.Log(health + " to " + Mathf.Clamp(health + value, 0, maxHealth));
health = Mathf.Clamp(health + value, 0, maxHealth);
invincible = true;
Helper.SetOpaquenessOfGameObject(gameObject, 0.5f);
StartCoroutine(Timer(invincibleTime));
}
}
// second秒后运行ChangeToVincible()
public IEnumerator Timer(float second)
{
while (second >= 0)
{
second -= 1f;
if (second < 0)
{
ChangeToVincible();
yield break;//停止协程
}
else
{
yield return new WaitForSeconds(1);// 等待 1 秒
}
}
}
// 变为非无敌状态
private void ChangeToVincible()
{
invincible = false;
Helper.SetOpaquenessOfGameObject(gameObject, 1f);
}
}
模板
public void TimerHelper(System.Action action, float second)
{
ObjectLibrary.gameManager.StartCoroutine(Timer(action, second));
}
/// <summary>
/// 延时启动
/// </summary>
/// <param name="action">函数</param>
/// <param name="second">延时秒数</param>
/// <param name="affectedByTimeScale">是否需要受函数影响</param>
/// <returns></returns>
public IEnumerator Timer(System.Action action, float second, bool affectedByTimeScale = true)
{
if (affectedByTimeScale)
{
yield return new WaitForSeconds(second);
}
else
{
yield return new WaitForSecondsRealtime(second);
}
action();
yield break;
}