我正在尝试进行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);
}
}
答案 0 :(得分:1)
首先,对于使用Rigidbody2D
和希望使用Collider2D
的OnTriggerEnter2D
和(希望)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)