мы работаем над каким-то 2d проектом. У нас есть доска, которая похожа на шахматную доску (8x8), и некоторые предметы появляются сверху этой доски, как в тетрисе.
Когда объект достигнет нижней части доски или каких-либо других объектов, он будет атаковать в 4 направлениях по всей доске - вверх, вниз, слева и справа.
У меня есть 3 сценария, Spawn, Obj_Controller и Personal_Attack. Сценарий Spawn прикреплен к пустому объекту spawnzone, оба сценария прикреплены к объекту, который мы порождаем. У объектов есть тег - Enemy, я использую его для обнаружения различий между объектами, на которые я хочу атаковать, и, например, Spawnzone и Bonuses (которых пока нет готовы). Надеюсь, я предоставлю достаточно информации о проекте, так что давайте посмотрим на код.
Spawn Я использую для порождения объектов в начале игры и после завершения каждой атаки
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;
}
}
Таким образом, по какой-то причине, после того, как объект атаки уничтожает не только объект, который он может достичь своей атакой, но также уничтожает сам себя, и игра останавливается (спавн не происходит, потому что объект атакующего не может вызвать функцию возрождения, потому что он уже уничтожен. _.). Я не понимаю, какую ошибку я совершил.