敌人AI在一定距离内阻止敌人



你好,我试图让我的敌人停在玩家面前使用if(Vector2.Distance(transform.position, player.position) > minDistance)

但这并没有像我预期的那样工作。敌人应该开始在一定范围内跟随玩家,而不是停在他面前。这对if(Vector2.Distance(transform.position, player.position) <= range)很有效

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public int Health;
public Transform player;
public float range;
public float speed;
public Animator anim;
public Transform goblinRange;
public float attackRangeGoblin;
public LayerMask whatIsPlayer;
public int damage;
private float timeBtwAttack;
public float startTimeBtwAttack;
// Update is called once per frame
void Update()
{
if (Vector2.Distance(transform.position, player.position) <= range)          
{
anim.SetBool("GWalking", true);
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * 
Time.deltaTime);
Collider2D[] playerToDamage = Physics2D.OverlapCircleAll(goblinRange.position, 
attackRangeGoblin, whatIsPlayer);
for (int i = 0; i < playerToDamage.Length; i++)
{
playerToDamage[i].GetComponent<PlayerMovement>().TakeDamage(damage);               
} 
}
else
{
Idle();
} 
} 
private void FixedUpdate()
{
if (Health <= 0)
{
Destroy(gameObject);
}
}
private void Idle()
{
anim.SetBool("GWalking", false);        
}
public void TakeDamage(int Damage)
{
Health -= Damage;
Debug.Log("Damage Taken");
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(goblinRange.position, attackRangeGoblin);
}
private void Attack()
{
anim.SetTrigger("goblinAttack");        
}     
}

所以我需要敌人停在我的播放器前面并开始攻击动画,但我不知道如何在不删除"<= 范围"的情况下实现对我的代码的if(Vector2.Distance(transform.position, player.position) > minDistance)。任何帮助将不胜感激。

您可以将minDistance检查嵌套在range检查中,如下所示:

if (Vector2.Distance(transform.position, player.position) <= range)
{
if (Vector2.Distance(transform.position, player.position) <= minDistance)
{
//Attack
}
else
{
//Chase
}
}

这样,只要玩家在追逐范围内,但距离还不够近,敌人就会追逐玩家。一旦进入攻击范围,它就会停止追逐并开始攻击。

rangeminDistance检查不是互斥的("一个或另一个"(。它们可以存在并共存:

//Avoid redundancy, write less, and make things more readable
var distance = Vector2.Distance(transform.position, player.position);
//If within range..
if (distance <= range) {
//If not within minDistance..
if(!(distance <= minDistance)) {
//Move
}
//If within minDistance (incl. after moving, above)..
if (distance <= minDistance) {
//Attack
}
}
//If not within range..
else {
//Idle
}

代码还有其他几个问题:

  1. 应遵循命名约定:

    • 如果你的变量和参数是驼峰大小写,那么Health应该是health的,GWalking应该是gWalking的,Damage应该是damage的。
  2. 名称应具有描述性:

    跳过几个字符进行键入不值得您或其他人(例如我们(不得不解密您的代码。

    • 避免歧义。anim可以指动画动画器。使用animator.
    • 避免使用首字母缩略词。在GWalkingG代表什么?---G·奥布林。我知道。问题是:我从其余代码的推理中知道;不是从名称本身。请改用goblinWalking
    • 避免使用类似首字母缩略词的缩短,例如Btw而不是Between。它们很糟糕,原因与"G"相同。
  3. 保持一致:

    • 对类似的东西使用相同的命名结构。决定一个方案,并遵循它。不要把GWalking放在一个地方,goblinAttack放在另一个地方。如果"subjectAction"是结构,则使用goblinWalkinggoblinAttack等。
    • 在名称中使用相同的结构顺序。如果你的主题要放在开头,就像在goblinRange中一样,那么不要把它放在其他地方的末尾,就像在attackRangeGoblin一样。使用goblinAttackRange.
    • 如果职业是"敌人","哥布林"的东西就不应该存在。所有的哥布林都可能是敌人,但不是所有的敌人都是哥布林。你的职业可能是所有敌人的通用职业,也可能是哥布林特有的;不能两者兼而有之。将其命名为Goblin;或者从它的元素中删除"妖精"的东西。
  4. 命名变量是为了它们是什么,而不是它们的作用:

    • whatIsPlayerplayerLayerMask.
  5. 在命名时要足智多谋(又名:"描述性并不意味着冗长!

    • timeBtwAttacksattackInterval.
  6. 尝试对相关内容进行分组。

修复后,它应如下所示:

//External(?) dependencies
public Transform player;
public LayerMask playerLayerMask; //From: whatIsPlayer
//Internal dependencies
public Animator animator; //From: anim
//Settings
public int health; //From: Health
public float range;
public float speed;
public int damage;
public float attackInterval; //From: timeBtwAttack
//Gobling stuff (probably redundant/unnecessary)
public Transform goblin; //From: goblinRange
public float goblinAttackRange; //From: attackRangeGoblin
//Used in the answer, as infered from the question
public float minDistance; //Probably what 'goblinAttackRange' is.

其他修复:

  • FixedUpdate是物理方面的。 如果要遵循当前的结构,if (health <= 0) { Destroy(gameObject); }应该在Update(加上一个return(。如果没有,那么它应该对健康的变化做出反应,从而在TakeDamage.
  • 在代码中保持一致。不要在一个地方使用anim.SetBool("GWalking", true),然后在另一个地方使用Idle()。两者都应该是方法(Idle()Walk()(,或者两者都应该是SetBool调用。
  • Transform goblin是单独的转换吗?如果不是,只需像在Vector2.Distance中那样使用transform

尝试使用

if((transform.position, player.position).magnitude <range)

而不是

if(Vector2.Distance(transform.position, player.position) <= range)

最新更新