玩家摧毁对撞机后,生活酒吧不会改变

时间:2020-03-18 19:35:02

标签: unity3d game-development

我正在尝试进行2D游戏,我的对象在碰撞后不会影响玩家的生命线。玩家的健康栏将有更长的寿命,但我认为脚本有问题。 (还需要检查需要破坏的对象的对撞机是否“被触发”)。我将此PowerUp放在对象上,并将角色脚本和Healthbar脚本放在播放器上。

Character.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

public class Character : MonoBehaviour
{
    Rigidbody2D rb;
    float dirX;

    [SerializeField]
    float moveSpeed = 5f, jumpForce = 600f, bulletSpeed = 500f;

    Vector3 localScale;

    public Transform barrel;
    public Rigidbody2D bullet;

    // Use this for initialization
    void Start()
    {
        localScale = transform.localScale;
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        dirX = CrossPlatformInputManager.GetAxis("Horizontal");

        if (CrossPlatformInputManager.GetButtonDown("Jump"))
            Jump();

        if (CrossPlatformInputManager.GetButtonDown("Fire1"))
            Fire();
    }

    void FixedUpdate()
    {
        rb.velocity = new Vector2(dirX * moveSpeed, rb.velocity.y);
    }

    void Jump()
    {
        if (rb.velocity.y == 0)
            rb.AddForce(Vector2.up * jumpForce);
    }

    void Fire()
    {
        var firedBullet = Instantiate(bullet, barrel.position, barrel.rotation);
        firedBullet.AddForce(barrel.up * bulletSpeed);
    }

}

HealthBar.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HealthBar : MonoBehaviour
{
    public Slider slider;
    public Gradient gradient;
    public Image fill;
    public float health = 100;

    public void SetMaxHealth(int health)
    {
        slider.maxValue = health;
        slider.value = health;

        fill.color = gradient.Evaluate(1f);
    }

    public void SetHealth(int health)
    {
        slider.value = health;

        fill.color = gradient.Evaluate(slider.normalizedValue);
    }

}

PowerUp.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PowerUp : MonoBehaviour
{
    public float multiplayer = 1.4f;
    public GameObject pickupEffect;

    private void OnTriggerEnter(Collider other)
    {
         if (other.CompareTag("Player"))
        {
            Pickup(other);
        }
    }

    void Pickup(Collider player)
    {
        //Spawn a cool effect
        Instantiate(pickupEffect, transform.position, transform.rotation);
        //Apply effect to the player
        HealthBar stats =player.GetComponent<HealthBar>();
        stats.health *= multiplayer;
        // Remove Effect
        Destroy(gameObject);
    }
}

2 个答案:

答案 0 :(得分:1)

首先,对于使用Rigidbody2D和希望使用Collider2DOnTriggerEnter2D和(希望)debug your code组件的 2D 游戏,其他人已经提到了!

Physics和Physics2D是两个完全分离的引擎,彼此之间并不了解。 3D OnTriggerEnter永远不会因碰撞等2D物理事件而被调用。


然后注意

还需要检查被摧毁物体的对撞机是否“被触发”

这完全是错误的方法。如果您的对象将跟踪OnTriggerEnter,那么进入的对象(玩家)应该启用isTrigger!在大多数情况下,您不想这样做,因为播放器应实际上与地板碰撞而不会掉落等等。

因此,您需要的是在播放器本身上放置一个额外的脚本,等待其他触发对象进入!

然后确保逐行property或添加其他日志以查看会发生什么:

开机

// 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;))


我建议宁愿实施{{3}}之类的

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);
}

答案 1 :(得分:0)

您的问题在下面,

  • 玩家将获得更长的生命
  • 也是需要摧毁的物体的对撞器

您可能会遇到什么情况

    1. 检查您的角色是否已触发,因此它会调用“ OnTriggerEnter”并检查标签。
    1. 检查您的上电项目,将其作为触发条件“ isTrigger”检查为true enter image description here
    1. 检查碰撞器或命中物体的比例是否很小,不适用于碰撞器。
    1. 如果您没有上述清单中的任何内容,则应该可以使用