在本文中,我将展示一个简化的实现无冷却、无UI、无多个技能的冰冻系统。
首先,让我们看看主 Freeze 脚本:
public class Freeze : MonoBehaviour
{
[SerializeField] private float _duration;
public event Action FreezeActivate;
public event Action FreezeDisactivate;
public static Freeze Instance;
private void Awake()
{
if (Instance != null && Instance != this)
Destroy(gameObject);
Instance = this;
}
public void UseAbility()
{
StartCoroutine(ActivateFreeze());
}
private IEnumerator ActivateFreeze()
{
FreezeActivate?.Invoke();
yield return new WaitForSeconds(_duration);
FreezeDisactivate?.Invoke();
}
}
这个脚本只触发事件的正确顺序。
_duration 变量控制冰冻的持续时间。
接下来,有两个事件用于冻结/解冻,单例用于快速访问脚本。
要激活技能,public UseAbility() 方法被调用,它开始一个协程。
在协程内部:
FreezeActivate被触发- 游戏等待
_duration秒 FreezeDisactivate被触发
现在,我们需要在需要的对象中订阅这些事件。让我们从障碍物脚本开始,该脚本应该被冻结。
首先,创建几个变量:
// 冻结时的颜色
[SerializeField] private Color _freezeColor;
private Rigidbody _rigidbody;
// 存储对象的速度前冻结
private Vector3 _savedVelocity;
// 存储角速度
private Vector3 _savedAngularVelocity;
// 用于改变颜色的
private MeshRenderer _meshRenderer;
接下来,创建两个方法用于冻结和解冻。
在 ActivateFreeze() 内部:
// 改变物体颜色
_meshRenderer.material.color = _freezeColor;
// 保存速度和角速度
_savedVelocity = _rigidbody.linearVelocity;
_savedAngularVelocity = _rigidbody.angularVelocity;
// 将速度值设置为零
_rigidbody.linearVelocity = Vector3.zero;
_rigidbody.angularVelocity = Vector3.zero;
// 开启刚体模式
_rigidbody.isKinematic = true;
在 DisactivateFreeze() 内部,我们做相反的事情:
// 关闭刚体模式
_rigidbody.isKinematic = false;
// 恢复保存的速度
_rigidbody.linearVelocity = _savedVelocity;
_rigidbody.angularVelocity = _savedAngularVelocity;
// 恢复原来的颜色
// (如果物体原本有其他颜色,
// 最好也保存和恢复它)
_meshRenderer.material.color = Color.white;
现在,我们只需订阅事件:
private void OnEnable()
{
Freeze.Instance.FreezeActivate += ActivateFreeze;
Freeze.Instance.FreezeDisactivate += DisactivateFreeze;
}
private void OnDisable()
{
Freeze.Instance.FreezeActivate -= ActivateFreeze;
Freeze.Instance.FreezeDisactivate -= DisactivateFreeze;
}
我也有一段独立的障碍物生成脚本。
在冻结期间,不应该生成新的障碍物,所以也在那里使用事件:
private void OnEnable()
{
Freeze.Instance.FreezeActivate += StopSpawn;
Freeze.Instance.FreezeDisactivate += StartSpawn;
}
private void OnDisable()
{
Freeze.Instance.FreezeActivate -= StopSpawn;
Freeze.Instance.FreezeDisactivate -= StartSpawn;
}
private void StopSpawn()
{
_isSpawn = false;
}
private void StartSpawn()
{
_isSpawn = true;
}
然后,在生成障碍物之前,只需检查 _isSpawn 变量。
结果是,一个简单的物理对象冻结系统,它通过事件扩展得很好,游戏中看起来也很满意。
评论 (0)