【问题标题】:Unity3D - enemy not taking damageUnity3D - 敌人没有受到伤害
【发布时间】:2016-10-27 00:25:18
【问题描述】:

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

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

【问题讨论】:

  • 只是好奇:是否有理由从另一个类继承而不是使用像 IHittable 这样的接口?
  • @garglblarg 我不确定,我是一名在 uni 学习游戏编程的学生,这正是我们被教导的方式。
  • @jozza710 - 注意你在哪里说 gameManager = ... 在 Unity 中你通常使用不同的习语。只是FindObjectOfType 请转到this answer 并向下滚动到“幸运的是没问题...”您的代码看起来非常好,大多数在这里发帖的学生都是垃圾。
  • @JoeBlow 谢谢,我使用了你建议的使用Debug.Log 的方法(我最初应该采用的方法)并发现这实际上是因为我的敌人没有刚体,我'我不知道为什么这会阻止我的敌人受到伤害你能向我解释一下为什么需要刚体才能让敌人受到伤害吗?
  • @jozza710 刚体 .. 当然,这里有充分的解释:docs.unity3d.com/Manual/CollidersOverview.html 转到“触发动作矩阵”。这是 Unity 的一个非常烦人的方面。每次我使用对撞机和/或触发器时,我都必须参考该图表!不可能记住它或清楚地看到它为什么会这样工作。注意请不要忘记,您绝对必须在碰撞物理中使用 layers

标签: c# inheritance unity3d


【解决方案1】:

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

scriptCall = otherObject.GetComponent(EnemyScript);

scriptCall.takeDamage(损坏);

【讨论】:

    【解决方案2】:

    问题 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”教程。)

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

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


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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多