c# - Unity3D - 敌人没有受到伤害

标签 c# inheritance unity3d

在 Unity3D 中,我的敌人在与我的射弹爆炸发生碰撞时没有受到伤害。

尽管情况并非如此,因为它的生命值变量在与我的射弹爆炸发生碰撞时不受影响。

我的 EnemyBarrel 类继承自 Entity ,它处理受到的伤害(从健康变量中减去伤害变量)。虽然只有桶类按预期工作。

标签是 100% 正确的,我更愿意继续使用继承,所以请不要建议更改我的类损坏的方法。

EnemyBarrel 继承的类

using UnityEngine;
using System.Collections;

public class Entity : MonoBehaviour {

    public float health = 25;

// Use this for initialization
void Start () {
}

// Update is called once per frame
void Update () {
}

public virtual void takeDamage(float dmg){
    health -= dmg;

    if (health <= 0){


         Destroy(this.gameObject);
        }
    }
}

敌人

using UnityEngine;
using System.Collections;

public class Enemy : Entity {
    private NavMeshAgent agent;
    public GameObject target;
    // Use this for initialization
    void Start () {
        agent = GetComponent<NavMeshAgent> ();
    }

    // Update is called once per frame
    void Update () {
        agent.SetDestination (target.transform.position);
    }
}

using UnityEngine;
using System.Collections;

public class Barrel : Entity {

    private Transform myTransform;

    //Effects
    public GameObject barrelExplosion;
    public GameObject explosionDamage;
    public GameObject explosionSound;

    // Use this for initialization
    void Start () {
        myTransform = this.transform;
    }

    // Update is called once per frame
    void Update () {
    }

    public override void takeDamage(float dmg){
        health -= dmg;

        if (health <= 0){
            Instantiate(barrelExplosion, myTransform.position, myTransform.rotation);
            Instantiate(explosionSound, myTransform.position, myTransform.rotation);
            Instantiate(explosionDamage, myTransform.position, myTransform.rotation);
            Destroy(this.gameObject);
        }
    }
}

ExplosionAOE 发送伤害的类

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

public class ExplosionAOE : MonoBehaviour {

    public float damage = 100.0f;

    public float lifeTime = 0.05f;
    private float lifeTimeDuration;

    public List<GameObject> damageTargets = new List<GameObject>();

    public float radius = 15.0f;

    GameManager gameManager;

    void Start() {
        gameManager = GameObject.FindGameObjectWithTag("GameManager").GetComponent<GameManager>();

        //Destroy (this.gameObject, lifeTime);
        lifeTimeDuration = Time.time + lifeTime;

        transform.GetComponent<SphereCollider>().radius = radius;
    }


    void Update() {

        //Explosion finishes, damage targets and remove AOE field
        if (Time.time > lifeTimeDuration) {
            foreach (GameObject target in damageTargets) {
                if (target != null) {
                    //Calculate damage based on proximity to centre of explosion
                    float thisDamage = ((radius - Vector3.Distance(target.transform.position, transform.position)) / radius) * damage;
                    print(thisDamage);
                    target.GetComponent<Entity>().takeDamage(thisDamage);
                    //target.SendMessage("takeDamage", damage);   //<< This is not good code. Let's fix this!
                }
            }
            Destroy(this.gameObject);
        }
    }


    void OnTriggerEnter(Collider otherObject) {

        if (otherObject.gameObject.tag == "Enemy") {
            damageTargets.Add(otherObject.gameObject);
        }
        if (otherObject.gameObject.tag == "Player") {
            Vector3 jumpVector = (otherObject.transform.position - transform.position).normalized;
            jumpVector *= 25;
            otherObject.GetComponent<CharacterMotor>().SetVelocity(jumpVector);
        }
    }
}

抱歉,这有点冗长,所有内容都已正确标记,所以这不是问题,谢谢。

最佳答案

问题 1.

到处使用“Debug.Log”

 void OnTriggerEnter(Collider otherObject) {
 Debug.Log("in trig");
 Debug.Log("otherObject.gameObject.tag is " + otherObject.gameObject.tag);

        if (otherObject.gameObject.tag == "Enemy") {
Debug.Log("a");
            damageTargets.Add(otherObject.gameObject);
        }
        if (otherObject.gameObject.tag == "Player") {
Debug.Log("b");
            Vector3 jumpVector = (otherObject.transform.position - 
                transform.position).normalized;
            jumpVector *= 25;
            otherObject.GetComponent<CharacterMotor>().SetVelocity(jumpVector);
        }
    }

特别是在 Entity 和 Enemy 中。

诸如此类的问题会通过使用 Debug.Log 进行跟踪来立即得到解答。


问题 2.

这是一个获取触发器、刚体等之间关系的 PITA。

这很可能是这里的问题。

http://docs.unity3d.com/Manual/CollidersOverview.html

进入烦人的“触发 Action 矩阵”并从那里开始工作。


问题 3.

通常,永远不要使用 Unity 中的“标签”功能。 (他们只添加了标签来帮助“hello world”教程。)

在实践中,你总是在任何地方都使用图层:

enter image description here

(图层在射击游戏中尤为重要:每个类别都需要一个图层。)


问题 4.

显示的代码绝对看起来不错。这里有一些示例代码与您的提示代码不同。

简单的例子,注意 OnTrigger 中的分离代码(返回值),你应该这样做。

此外,

使用扩展

无处不在,始终在 Unity 中。 Quick tutorial

如果您真的想从事专业工作,这是第一要诀。

public class Enemy:BaseFrite
    {
    public tk2dSpriteAnimator animMain;
    public string usualAnimName;
    
    [System.NonSerialized] public Enemies boss;
    
    [Header("For this particular enemy class...")]
    public float typeSpeedFactor;
    public int typeStrength;
    public int value;
    
    // could be changed at any time during existence of an item!
    
    [System.NonSerialized] public FourLimits offscreen; // must be set by our boss
    
    [System.NonSerialized] public int hitCount;         // that's ATOMIC through all integers
    [System.NonSerialized] public int strength;         // just as atomic!
    
    [System.NonSerialized] public float beginsOnRight;
    
    private bool inPlay;    // ie, not still in runup
    
    void Awake()
        {
        boss = Gp.enemies;
        }
    
..........

    protected virtual void Prepare()    // write it for this type of sprite
        {
        ChangeClipTo(bn);
        // so, for the most basic enemy, you just do that.
        // for other enemy, that will be custom (example, swap damage sprites, etc)
        }
    
    void OnTriggerEnter2D(Collider2D c)
        {
        // we can ONLY touch either Biff or a projectile. to wit: layerBiff, layerPeeps
        
        GameObject cgo = c.gameObject;
        
        if ( gameObject.layer != Grid.layerEnemies ) // if we are not enemy layer....
            {
            Debug.Log("SOME BIZARRE PROBLEM!!!");
            return;
            }
        
        if (cgo.layer == Grid.layerBiff)    // we ran in to Biff
            {
            Gp.billy.BiffBashed();
            // if I am an enemy, I DO NOT get hurt by biff smashing in to me.
            return;
            }
        
        if (cgo.layer == Grid.layerPeeps)   // we ran in to a Peep
            {
            Projectile p = c.GetComponent<Projectile>();
            if (p == null)
                {
                Debug.Log("WOE!!! " +cgo.name);
                return;
                }
            int damageNow = p.damage;
            Hit(damageNow);
            return;
            }
        
        Debug.Log("Weirded");
        }
    
    public void _stepHit()
        {
        if ( transform.position.x > beginsOnRight ) return;
        
        ++hitCount;
        --strength;
        ChangeAnimationsBasedOnHitCountIncrease();
        // derived classes write that one.
        
        if (strength==0)    // enemy done for!
            {
            Gp.coins.CreateCoinBunch(value, transform.position);
            FinalEffect();
            
            if ( Gp.superTest.on )
                {
                Gp.superTest.EnemyGottedInSuperTest(gameObject);
                boss.Done(this);
                return;
                }
            
            Grid.pops.GotEnemy(Gp.run.RunDistance);     // basically re meters/achvmts
            EnemyDestroyedTypeSpecificStatsEtc();       // basically re achvments
            Gp.run.runLevel.EnemyGotted();              // basically run/level stats
            
            boss.Done(this);                            // basically removes it
            }
        }
    
    protected virtual void EnemyDestroyedTypeSpecificStatsEtc()
        {
        // you would use this in derives, to mark/etc class specifics
        // most typically to alert achievements system if the enemy type needs to.
        }
    
    private void _bashSound()
        {
        if (Gp.biff.ExplodishWeapon)
            Grid.sfx.Play("Hit_Enemy_Explosive_A", "Hit_Enemy_Explosive_B");
        else
            Grid.sfx.Play("Hit_Enemy_Non_Explosive_A", "Hit_Enemy_Non_Explosive_B");
        }
    
    public void Hit(int n)  // note that hitCount is atomic - hence strength, too
        {
        for (int i=1; i<=n; ++i) _stepHit();
        
        if (strength > 0) // biff hit the enemy, but enemy is still going.
            _bashSound();
        }
    
    protected virtual void ChangeAnimationsBasedOnHitCountIncrease()
        {
        // you may prefer to look at either "strength" or "hitCount"
        }
    
    protected virtual void FinalEffect()
        {
        // so, for most derived it is this standard explosion...
        Gp.explosions.MakeExplosion("explosionC", transform.position);
        }
    
    public void Update()
        {
        if (!holdMovement) Movement();
        
        if (offscreen.Outside(transform))
            {
            if (inPlay)
                {
                boss.Done(this);
                return;
                }
            }
        else
            {
            inPlay = true;
            }
        }
    
    protected virtual void Movement()
        {
        transform.Translate( -Time.deltaTime * mpsNow * typeSpeedFactor, 0f, 0f, Space.Self );
        }
......



/*
(frite - flying sprite)
The very base for enemies, projectiles etc.
*/

using UnityEngine;
using System.Collections;

public class BaseFrite:MonoBehaviour
    {
    [System.NonSerialized] public float mpsNow;
    // must be set by the boss (of the derive) at creation of the derive instance!
    
    private bool _paused;
    public bool Paused
        {
        set {
            if (_paused == value) return;
            
            _paused = value;
            
            holdMovement = _paused==true;
            
            if (_paused) OnGamePause();
            else OnGameUnpause();
            }
        get { return _paused; }
        }
    
    protected bool holdMovement;
    
    protected virtual void OnGamePause()
        {
        }
    protected virtual void OnGameUnpause()
        {
        }
    
    protected string bn;
    public void SetClipName(string clipBaseName)
        {
        bn = clipBaseName;
        }
    
    }

关于c# - Unity3D - 敌人没有受到伤害,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38012453/

相关文章:

javascript - 如何在javascript中从子原型(prototype)调用父类的构造函数方法?

c# - 将 UnityScript 翻译成 C# : yield & transform. 位置

c# - 脚本中的公共(public)变量名称与检查器/编辑器中的字段显示不匹配

c# - 委托(delegate)为属性 : Bad Idea?

Java:突出显示所有派生数据成员

c# - 无法在控制台应用程序的 'async' 方法上指定 'Main' 修饰符

javascript - 使用 JS 多态性和方法重写

node.js - Node.JS 在 Unity3D 中的游戏服务器

c# - 如何在静态方法中获取当前类的名称?

c# - 生成的.TLB文件输出目录