为什么我的攻击功能会破坏所有对象,包括攻击者?

时间:2019-06-06 19:13:32

标签: c# unity3d

我们正在一些2D项目中工作。我们得到了一块棋盘,看起来像国际象棋棋盘(8x8),并且一些物体在此棋盘的上方产生,例如俄罗斯方块。 当物体到达棋盘底部或其他物体时,它将在所有棋盘上向四个方向进攻-向上,向下,向左和向右。

我有3个脚本,Spawn,Obj_Controller和Personal_Attack。 Spawn脚本附着在spawnzone空对象上,两个不同的脚本都附着在我们生成的objet上。对象具有标签-敌人,我用它来检测需要攻击的对象之间的差异,例如Spawnzone和Bonuses(仍然不是准备)。希望我提供有关项目的足够信息,所以让我们看一下代码。

在游戏开始时以及每次攻击结束后,我都会使用生成的对象

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,每个对象的transform.position ==单元的中心)。


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;

    }
}

因此,由于某种原因,在攻击对象销毁后,它不仅可以通过其攻击到达目标,而且也销毁自身,并且游戏停止(不生成任何事件,因为攻击者对象无法调用spawn函数,因为它已经被销毁了)。 _。)。我不明白我犯了什么错误。

2 个答案:

答案 0 :(得分:1)

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

已更新:

因此,看来您在攻击者身上带有“敌人”标签,如果您确实出于某种原因需要在此处使用它,则可以通过以下方式简单地对其进行修复:

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

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

答案 1 :(得分:0)

看起来您的敌人对撞机足够大,可以延伸到相邻正方形的边界,并且在边界处可能会稍微重叠。我会将您的OverlapCircleAll通话的半径缩小一小部分(例如Mathf.Epsilon),以使正方形的边界不会被触及:

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