Общий скрипт для нескольких объектов в unity
Делаю 3d стрелялку в unity. У меня есть враги, которые спавнятся на сцене через каждые 10 сек и если кол-во жизней равно 0 исчезают. Возникает проблема когда пуля попадает во врага, то отнимаются жизни у всех клонов врага, находящихся на сцене. Я понимая, что это возникает из-за того, что у них один скрипт, но что сделать чтобы каждый скрипт работал не зависимо от другого.
Нанесение урона
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
private Rigidbody rb;
public float speed_bullet;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
rb.AddForce(transform.forward * speed_bullet);
}
void OnCollisionEnter(Collision coll)
{
if (coll.gameObject.tag == "Enemy")
{
enemy.heartEnemy -= 20;
}
}
}
Движение врага
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemy : MonoBehaviour
{
private GameObject hero_obj;
public float speed;
public static int heartEnemy;
void Start()
{
hero_obj = GameObject.Find("hero");
heartEnemy = 100;
}
void Update()
{
MoveEnemy();
CheckHeart();
}
void MoveEnemy()
{
transform.LookAt(hero_obj.transform.position);
transform.position = Vector3.MoveTowards(transform.position, hero_obj.transform.position, Time.deltaTime * speed);
}
void CheckHeart()
{
if (heartEnemy <= 0)
{
Destroy(gameObject);
}
}
}
Ответы (1 шт):
Можно вопрос? У тебя пули как ракеты летят с двигателем и ускоряются еще по ходу движения? Физика у тебя явно не правильная. Пуле прикладывается сила один только раз, а у тебя каждый кадр. Да и манипуляции с физикой должны делаться в FixedUpdate(). Это во первых.
Во-вторых, я не удивлюсь, что с тем, как ты ловишь попадания пуль, у тебя пули просто пролетают через врага и летят дальше. Для быстро движущихся объектов надо использовать другие методы определения попадания.. Особенно, если у тебя fps не очень высокий.
Ну, на счет того, что поле health у тебя статическое тебе уже сказали. А чтобы каждый раз не вызывать GetComponent(), что дорого, лучше бы ты кешировал всех своих Enemy в словаре где-нибудь в общем классе сцены Dictionary<Collider, Enemy> EnemyMap, тогда можно будет делать типа такого:
void OnCollisionEnter(Collision coll)
{
if(BattlController.EnemyMap.TryGetValue(coll, out var enemy)) //BattleController это первое, что пришло мне в голову в качестве класса, который был бы общим для всех объектов карты. Кстати, в этом случае словарь EnemyMap мог бы быть статическим
{
enemy.heartEnemy -= 20; // по-хорошему пуля не должна знать, как отбавлять здоровье, лучше это вынести в класс Enemy в отедльный метод.. было бы типа enemy.TakesDamage(20);
//Или вообще не связывать эти классы , а запускать событие. Но это в твоем случае пока рано..
}
// сравнивать теги больше не нужно. Да и коряво это так делать coll.gameObject.tag == "Enemy"
}
То, что ты каждый кадр проверяешь здоровье врага CheckHeart(); в Update, тоже коряво. Проверяй умер ли тогда, когда здоровье обновляется и все. Зачем каждый кадр то это делать?
Когда ты пуле придаешь силу transform.forward * speed_bullet , где гарантия, что у пули то же самое направление, что и у ствола? Если она летит в нужную сторону, то тебе просто повезло.
Destroy у врагов вряд ли надо вызывать, просто клади их в пул для повторного использования. Я не удивлюсь, если ты и пули каждый раз спаунишь, вызывая Instantiate. Короче, у тебя всё пока довольно колхозно.