Unity3D - 没有受到伤害的敌人

时间:2016-06-24 11:34:00

标签: 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);
        }
    }
}

Enemy上课

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

Barrel上课

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

对不起,这是一个冗长的,一切都被正确标记,所以这不是问题,谢谢。

2 个答案:

答案 0 :(得分:4)

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

特别是在实体和敌人中。

通过使用Debug.Log跟踪即可立即解答此问题。

问题2。

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

这很可能是一个问题。

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

转到讨厌的“触发动作矩阵”并从那里开始工作。

问题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;
        }

    }

答案 1 :(得分:0)

如果在ExplosionAOE / OnTriggerEnter函数中调用takeDamage函数,则更容易:

scriptCall = otherObject.GetComponent(EnemyScript);

scriptCall.takeDamage(损伤);