Прежде всего, как уже упоминалось для игры 2D с Rigidbody2D
и (надеюсь) Collider2D
компонентами, которые вы хотите использовать OnTriggerEnter2D
вместо!
Физика и Физика2D - это два полностью разделенных движка, которые не знают друг друга. 3D OnTriggerEnter
никогда не будет вызываться для событий двумерной физики, таких как столкновения и т. Д. c.
Затем обратите внимание, что
Также коллайдер объекта, который должен быть Уничтожение - это "спусковой крючок" проверено
Это совершенно неверный способ. Если ваш объект должен отслеживать OnTriggerEnter
, то у входящего ( игрока ) должна быть включена isTrigger
! В большинстве случаев вы не хотите этого делать, потому что игрок должен, например, фактически сталкиваться с полом и не проваливаться сквозь него и т. Д. c.
Так что вам нужно будет скорее поставить дополнительный сценарий на Сам игрок, который ожидает ввода других триггерных объектов!
Затем, чтобы быть уверенным, либо построчно отлаживайте свой код , либо добавьте дополнительные журналы, чтобы увидеть, что происходит:
PowerUp
// put this on the pickup item
public class PowerUp : MonoBehaviour
{
// Make these private, nobody else needs access to those
// (Encapsulation)
[SerializeField] private float multiplayer = 1.4f;
[SerializeField] private GameObject pickupEffect;
public void Pickup(HealthBar stats)
{
//Spawn a cool effect
Instantiate(pickupEffect, transform.position, transform.rotation);
//Apply effect to the player
stats.health *= multiplayer;
// Remove Effect
Destroy(gameObject);
}
}
PowerUpDetector (на плеере)
// put on player!
public class PowerUpDetector : MonoBehaviour
{
// reference this via the Inspector
[SerializeField] private HealthBar healthbar;
private void Awake()
{
if(!healthBar) healthBar = GetComponent<HealthBar>();
}
private void OnTriggerEnter2D(Collider2D other)
{
// or whatever tag your powerups have
if (!other.CompareTag("PowerUp"))
{
Debug.LogWarning($"Registered a collision but with wrong tag: {other.tag}", this);
return;
}
var powerup = other.GetComponent<PowerUp>();
if(!powerup)
{
Debug.LogError($"Object {other.name} is tagged PowerUp but has no PowerUp component attached", this);
return;
}
Debug.Log("Found powerup, pick it up!", this);
powerup.Pickup(healthbar);
}
}
Ну, а то, что вы делаете, это только изменяя значение float
stats.health *= multiplayer;
, но вы никогда не обновите GUI соответственно, как это было бы при использовании
stats.SetHealth(stats.health * multiplayer)
(Кстати: я думаю, вы имеете в виду multiplier
;))
Я бы предложил реализовать свойство , например, например
public class HealthBar : MonoBehaviour
{
// Make these private, nobody else needs access to those
// (Encapsulation)
[SerializeField] private Slider slider;
[SerializeField] private Gradient gradient;
[SerializeField] private Image fill;
[SerializeField] private float health = 100;
public float Health
{
get { return health; }
set
{
health = value;
slider.value = health;
fill.color = gradient.Evaluate(slider.normalizedValue);
}
}
// be careful with variable names if you have this name already
// for a class field .. was ok this time but might get confusing
public void SetMaxHealth(int value)
{
slider.maxValue = value;
// The property handles the rest anyway
Health = value;
}
}
, поэтому теперь вместо вызова SetHealth
вы просто назначаете новый значение Health
, и его установщик также автоматически запускается, поэтому ваш GUI обновляется.
public void Pickup(HealthBar stats)
{
//Spawn a cool effect
Instantiate(pickupEffect, transform.position, transform.rotation);
//Apply effect to the player
stats.Health *= multiplayer;
Destroy(gameObject);
}