Триггеры в игре. Название и реализация
Хочу добавить в игру триггеры, интерфейс типа ITrigger.
Вопрос первый: как правильно назвать этот интерфейс, если он может быть у: пилы которая убивает игрока, у блока на который можно встать и будет действие, у зоны в которую вошёл и будет событие. Правильно ли понимаю что лучше всего подходит слово Trigger?
Вопрос второй, реализация. Как лучше реализовать универсально.
Сейчас например так:
public interface ITrigger
{
void OnTrigger();
}
Но это если без передачи параметра. А удобно было бы передавать того кто вызвал этот триггер.
Например так:
public interface ITrigger<T>
{
void OnTrigger(T arg1);
}
Вопрос в том на сколько правильно делать так, и на сколько оптимизировано ?
collider.GetComponent<ITrigger<Player>>().OnTrigger(this);
Пугает этот участок ITrigger<Player>, не идет ли кастование, распаковка?
Вопрос третий: По мимо триггера обычного с одним методом, нужен триггер зоны / области, где будет вызов при входе и при выходе. Сейчас сделал так, но может можно лучше? По солид и ооп.
public interface ITriggerArea
{
void OnTriggerAreaEnter();
void OnTriggerAreaExit();
}
Ответы (2 шт):
Реализовывать интерфейс не нужно. Столкновения обрабатывается магическими методоми юнити. Для получения событий столкновения у обоих тел должен быть Collider и хотя-бы у одного Rigidbody которое двигается по физике (не ручным изменение transform).
Косаемо твёрдых тел (например пила)
void OnCollisionEnter (Collider other) {
Destroy(other.gameObject);
}
Косаемо тригеерных зон (isTrigger в компанентах типа Collider)
void OnTriggerEnter (Collider other) {
if (other.gameObject.layer == 10) {
// Коснулся триггера
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.layer == 10) {
// Вышел из триггера
}
}
Я бы рекомендовал воспользоваться событиями и выстраивать пользовательские события относительно сабытий. Если события подвязаны то используем, если нет то идем дальше.
К примеру создал бы основной интерфейс, от которого буду наследовать абсолютно все ингорые элементы
public interface IGameObject
{
string GetName();
event EventHandler OnCreate;
}
Интерфейс пилы наследуем от IGameObject
public interface ISawObject : IGameObject{
event EventHandler<IPlayer> OnCustomerInFireZone;
}
После чего можно уже переходить к реализации и выстариивать абстрации для упращения жизни
public abstract class AbstractGameObject : IGameObject
{
private readonly string _name;
protected AbstractGameObject(string name)
{
_name = name;
OnCreate?.Invoke(this, null);
}
public string GetName()
{
return _name;
}
public event EventHandler OnCreate;
}
public abstract class AbstractSawObject : AbstractGameObject, ISawObject
{
protected AbstractSawObject(string name, int damage) : base(name)
{
_damage = damage;
OnCreate += (sender, args) =>
{
Console.WriteLine($"Game object {GetName()} created");
};
OnCustomerInFireZone += (sender, customer) =>
{
if (customer.IsOnDistance(this))
{
// Что там происходит когда атакуют
}
};
}
private readonly int _damage;
public override void Attack(IPlayer player)
{
OnCustomerInFireZone?.Invoke(this, player);
}
public int GetDamage()
{
return _damage;
}
public event EventHandler<IPlayer> OnCustomerInFireZone;
}