为什么我的攻击函数会摧毁所有对象,包括攻击者?



我们正在做一些2D项目。我们得到了一个棋盘,看起来像棋盘(8x8),一些物体在这个棋盘之外生成,就像俄罗斯方块一样。 当物体到达板子或其他物体的底部时,它将在所有板上向 4 个方向攻击 - 向上,向下,lef 和右侧。

我有 3 个脚本,生成、Obj_Controller 和Personal_Attack。生成脚本附加到生成空对象,两种不同的脚本附加到我们生成的对象。对象有标签 - 敌人,我用它来检测我需要攻击的对象之间的差异,例如,生成区和奖励(仍然没有准备好)。希望我提供有关项目的足够信息,所以让我们看看代码。

生成我用于在游戏开始时和每次攻击结束后生成对象

public class Spawn : MonoBehaviour
{
public GameObject[] objects;
Vector3 spotSpawn;
// Start is called before the first frame update
void Start()
{
spotSpawn = transform.position;
//Debug.Log(spotSpawn);
NewSpawn();
}
// Update is called once per frame
void Update()
{
}
public void NewSpawn()
{
int random_key = Random.Range(0,objects.Length - 1);
Instantiate(objects[random_key], spotSpawn, Quaternion.identity);
}
}

Obj_Controller 我用于使对象移动,并在时机成熟时调用攻击


public class Obj_Controller : MonoBehaviour
{
public float speed; // speed (I still dont use this var)
[HideInInspector] public bool isMoved = true;   // movement flag
[HideInInspector] public bool canSpawn = false; // spawn flag
[HideInInspector] public bool attack = false; // attack flag
bool LetFall = true; // falling flag
[HideInInspector] public Animator anim; 

// Start is called before the first frame update
void Start()
{
}
private void OnEnable()
{
anim = GetComponent<Animator>();
//Debug.Log(transform.position);
}

// Update is called once per frame
void Update()
{
if (isMoved == true && canSpawn == false)
{
Collider2D[] hitDown = Physics2D.OverlapCircleAll(transform.position - new Vector3(0, 1, 0), 0.5f);
Collider2D[] hitLeft = Physics2D.OverlapCircleAll(transform.position - new Vector3(1, 0, 0), 0.5f);
Collider2D[] hitRight = Physics2D.OverlapCircleAll(transform.position + new Vector3(1, 0, 0), 0.5f);

if (hitDown.Length == 0)
{
//Check object can movew down in 1 cell
if (LetFall == true)
{
LetFall = false;
StartCoroutine(Down());
}
//Check object can move in  left or right side
if (Input.GetKeyDown(KeyCode.LeftArrow) && hitLeft.Length == 0)
{
transform.position -= new Vector3(1,0,0);
}
else if (Input.GetKeyDown(KeyCode.RightArrow) && hitRight.Length == 0)
{
transform.position += new Vector3(1, 0, 0);
}
}
else 
{
//Debug.Log(hitDown[0].name);
isMoved = false;
if(attack == false)
{
attack = true;
gameObject.SendMessage("Attack");
}
}
}
else if(canSpawn == true)
{
canSpawn = false;
GameObject spawner = GameObject.Find("SpawnZone");
Spawn spawn = spawner.GetComponent<Spawn>();
spawn.NewSpawn();
}
else
{
//Here will some functions, but later
}
}
IEnumerator Down()
{
transform.position -= new Vector3(0,1, 0);
yield return new WaitForSeconds(0.5f);
LetFall = true;
}
}

Personal_Attack是尝试在 4 个方向上查找其他对象的脚本,每次攻击的长度等于 8 个单元的板(每一步 == 1,每个对象的转换位置 == 单元格的中心)。


public class Personal_Attack : MonoBehaviour
{
Obj_Controller objcontroller;
// Start is called before the first frame update
void OnEnable()
{
objcontroller = GetComponent<Obj_Controller>();
}
// Update is called once per frame
void Update()
{
}

void Attack()
{
//Attack up
for (int i = 1; i < 9; i++)
{
Collider2D[] hitTop = Physics2D.OverlapCircleAll(transform.position + new Vector3(0, i, 0), 0.5f);
foreach (Collider2D enemy in hitTop)
{
if (enemy.tag == "Enemy")
{
Debug.Log(enemy.transform.position);
Destroy(enemy.gameObject);
}
}
}
//Attack down
for (int i = 1; i < 9; i++)
{
Collider2D[] hitDown = Physics2D.OverlapCircleAll(transform.position - new Vector3(0, i, 0), 0.5f);
foreach (Collider2D enemy in hitDown)
{
if (enemy.tag == "Enemy")
{
Destroy(enemy.gameObject);
}
}
}
//Attack left
for (int i = 1; i < 9; i++)
{
Collider2D[] hitLeft = Physics2D.OverlapCircleAll(transform.position - new Vector3(i, 0, 0), 0.5f);
foreach (Collider2D enemy in hitLeft)
{
if (enemy.tag == "Enemy")
{
Destroy(enemy.gameObject);
}
}
}
//Attack right
for (int i = 1; i < 9; i++)
{
Collider2D[] hitRight = Physics2D.OverlapCircleAll(transform.position + new Vector3(i, 0, 0), 0.5f);
foreach (Collider2D enemy in hitRight)
{
if (enemy.tag == "Enemy")
{
Destroy(enemy.gameObject);
}
}
}
objcontroller.canSpawn = true;
}
}

因此,出于某种原因,攻击对象摧毁后,它不仅可以通过攻击到达的对象,而且也会摧毁自己,并且游戏停止(没有发生生成,因为攻击者对象无法调用生成函数,因为它已经销毁了._)。我不明白我犯了什么错误。

我看到它何时发生的唯一方法是您的攻击者对象是否也具有"敌人"标签。检查所有对象上的标签。

更新:

因此,由于攻击者似乎有"敌人"标签,如果您确实出于某种原因需要它,您可以简单地通过以下方式修复它:

在带有"销毁"的循环中,您可以添加简单的检查它是否是同一对象:

if (enemy.tag == "Enemy" && enemy.gameObject != gameObject)
{
Destroy(enemy.gameObject);
}

看起来你的敌人对撞机足够大,可以延伸到相邻方块的边界,并且可能在边界处略有重叠。我会将OverlapCircleAll调用的半径缩小少量(例如Mathf.Epsilon),以便不触及正方形的边界:

Collider2D[] hitTop = Physics2D.OverlapCircleAll(
transform.position + new Vector3(0, i, 0), 
0.5f - Mathf.Epsilon);

最新更新