2016-06-24 1 views
1

В Unity3D мой враг не наносит урон при столкновении с моим взрывом снаряда.Unity3D - враг не получает урона

Хотя это не так, поскольку переменная здоровья не влияет на столкновение с моим взрывом снаряда.

Мои Enemy и Barrel классы наследуют от Entity, который обрабатывает взятие урона (вычитая переменную ущерба из переменной работоспособности). Хотя только класс ствола работает по назначению.

Теги на 100% правильные, и я предпочел бы продолжать использовать наследование, поэтому, пожалуйста, не предлагайте изменить метод, в котором мои классы получают урон.

класс, Enemy и Barrel унаследуют от

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

Извините, что это немного длинный, и все равно помечены правильно, так что это не проблема, спасибо.

+0

просто любопытно: есть ли причина для наследования из другого класса вместо использования интерфейса типа 'IHittable'? – garglblarg

+1

@garglblarg Я не уверен, я студент, изучающий программирование игры в uni, и это именно то, как нас учили делать. – jozza710

+0

Что именно не работает? не влияет ли ценность здоровья вашего врага при вызове 'takeDamage'? –

ответ

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

В частности, в Сущности и Enemy.

Вопросы, подобные этому, мгновенно отвечают на отслеживание с помощью Debug.Log.


Задача 2.

Это PITA получение отношения между триггерами, RigidBody и т.д.

Это очень вероятно, что проблема здесь.

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

Перейти вниз к раздражающей «матрицы триггера действия» и работать оттуда.


Задача 3.

Как правило, никогда не используйте функцию «теги» в Unity. (Они только добавили теги, чтобы помочь «привет мир» учебники.)

На практике вы используете слои всегда и везде:

enter image description here

(Слои особенно важно при съемке игр: каждая категория нуждается в слой.)


Задача 4.

код, показанный, безусловно, выглядит хорошо. Вот пример кода, который мало чем отличается от ваших советов.

Простой пример, обратите внимание на отколовшийся код (возврат) внутри OnTrigger, вы должны это сделать).

Кроме того,

использование Extentions

везде и всегда в единстве. Quick tutorial

это совет № 1, если вы действительно хотите профессионально работать.

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

    } 
0

является более легким, если в ExplosionAOE/OnTriggerEnter функции вы вызываете функцию takeDamage:

scriptCall = otherObject.GetComponent (EnemyScript);

сценарийCall.takeDamage (повреждение);

Смежные вопросы