试图让敌人在设定的秒数内造成伤害(Unity)
Trying to get enemy to deal damage every set seconds (Unity)
我正在创建一个 3D 射击游戏,我试图让敌人每隔设定的秒数对玩家造成伤害。我已经让敌人用光线投射造成伤害,但它造成伤害的速度太快了。
我认为使用 yield return new WaitForSeconds(2) 会每 2 秒从玩家身上带走 1 点伤害,但它对玩家造成伤害的速度要快得多。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMove : MonoBehaviour
{
public Transform target;
public Transform player;
public float enemySpeed;
public int moveTrigger = 1;
public int isAttacking;
public float distanceFromPlayer;
void Update()
{
distanceFromPlayer = Vector3.Distance(target.transform.position, player.transform.position);
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
transform.LookAt(target);
StartCoroutine(EnemyDamage());
}
if (distanceFromPlayer <10 && moveTrigger == 1 && distanceFromPlayer >3)
{
transform.Translate(Vector3.forward * enemySpeed * Time.deltaTime);
}
}
IEnumerator EnemyDamage()
{
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit))
{
Debug.Log(PlayerHit.transform.name);
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null)
{
yield return new WaitForSeconds(2);
GlobalHealth.playerHealth -= 1;
yield return null;
}
}
}
}
可以使用FixedUpdate
→ 设置局部变量bool alreadyShoot = false
.
在你的 EnemyDamage()
中添加一个 if(!alreadyShoot)
在损害赔偿申请之前并在损害赔偿申请之后将 alreadyShoot
设置为 true
。
在FixedUpdate
中您可以将alreadyShoot
设置为false
。
您可以选择其他解决方案将 alreadyShoot
设置为 false
而不是 FixedUpdate
(例如每秒触发的协程,...)
你在每个更新循环中启动一个协程,所以每一帧你的伤害协程都会被调用并在 2 秒后应用你的 1 伤害。
如果你想要随着时间的推移造成伤害效果,那么使用游戏滴答计时器的建议是正确的,但如果你希望你的敌人只能每 x 秒攻击一次,你需要对你的伤害函数实施某种冷却时间。例如加起来Time.deltaTime直到你想要的时间过去,然后敌人才能再次造成伤害。你可以用布尔值来做到这一点。
在更新循环中,当玩家在范围内时检查两秒后
float timeInRange = 0.0f;
bool inRange = false;
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
inRange = true;
}
else
{
inRange = false;
timeInRange = 0;
}
if (inRange)
{
timeInRange += Time.DeltaTime;
}
if (timeInRange > 2.0f)
{
GlobalHealth.playerHealth -= 1;
timeInRange = 0.0f;
}
如其他答案中所述,您每帧都在启动一个新协程。当执行退出 并重新进入 您的协同程序时,您应该在协同程序中进行所有等待和循环。这就是你如何编写它来工作
// in update
if (distanceFromPlayer <= 10 && moveTrigger == 1){
transform.LookAt(target);
if(!isAttacking)
StartCoroutine(EnemyDamage());
}
IEnumerator EnemyDamage()
{
isAttacking = true;
while(distanceFromPlayer <= 10){ // in range
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit)){
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null){
GlobalHealth.playerHealth -= 1;
yield return new WaitForSeconds(2);
}
}
}
isAttacking = false; // out of range
yield return null;
}
我正在创建一个 3D 射击游戏,我试图让敌人每隔设定的秒数对玩家造成伤害。我已经让敌人用光线投射造成伤害,但它造成伤害的速度太快了。
我认为使用 yield return new WaitForSeconds(2) 会每 2 秒从玩家身上带走 1 点伤害,但它对玩家造成伤害的速度要快得多。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMove : MonoBehaviour
{
public Transform target;
public Transform player;
public float enemySpeed;
public int moveTrigger = 1;
public int isAttacking;
public float distanceFromPlayer;
void Update()
{
distanceFromPlayer = Vector3.Distance(target.transform.position, player.transform.position);
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
transform.LookAt(target);
StartCoroutine(EnemyDamage());
}
if (distanceFromPlayer <10 && moveTrigger == 1 && distanceFromPlayer >3)
{
transform.Translate(Vector3.forward * enemySpeed * Time.deltaTime);
}
}
IEnumerator EnemyDamage()
{
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit))
{
Debug.Log(PlayerHit.transform.name);
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null)
{
yield return new WaitForSeconds(2);
GlobalHealth.playerHealth -= 1;
yield return null;
}
}
}
}
可以使用FixedUpdate
→ 设置局部变量bool alreadyShoot = false
.
在你的
EnemyDamage()
中添加一个if(!alreadyShoot)
在损害赔偿申请之前并在损害赔偿申请之后将alreadyShoot
设置为true
。在
FixedUpdate
中您可以将alreadyShoot
设置为false
。
您可以选择其他解决方案将 alreadyShoot
设置为 false
而不是 FixedUpdate
(例如每秒触发的协程,...)
你在每个更新循环中启动一个协程,所以每一帧你的伤害协程都会被调用并在 2 秒后应用你的 1 伤害。 如果你想要随着时间的推移造成伤害效果,那么使用游戏滴答计时器的建议是正确的,但如果你希望你的敌人只能每 x 秒攻击一次,你需要对你的伤害函数实施某种冷却时间。例如加起来Time.deltaTime直到你想要的时间过去,然后敌人才能再次造成伤害。你可以用布尔值来做到这一点。
在更新循环中,当玩家在范围内时检查两秒后
float timeInRange = 0.0f;
bool inRange = false;
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
inRange = true;
}
else
{
inRange = false;
timeInRange = 0;
}
if (inRange)
{
timeInRange += Time.DeltaTime;
}
if (timeInRange > 2.0f)
{
GlobalHealth.playerHealth -= 1;
timeInRange = 0.0f;
}
如其他答案中所述,您每帧都在启动一个新协程。当执行退出 并重新进入 您的协同程序时,您应该在协同程序中进行所有等待和循环。这就是你如何编写它来工作
// in update
if (distanceFromPlayer <= 10 && moveTrigger == 1){
transform.LookAt(target);
if(!isAttacking)
StartCoroutine(EnemyDamage());
}
IEnumerator EnemyDamage()
{
isAttacking = true;
while(distanceFromPlayer <= 10){ // in range
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit)){
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null){
GlobalHealth.playerHealth -= 1;
yield return new WaitForSeconds(2);
}
}
}
isAttacking = false; // out of range
yield return null;
}