2016-06-24 11 views
1

In Unity3D nimmt mein Gegner keinen Schaden, wenn er mit meiner Projektil-Explosion kollidiert.Unity3D - Gegner nimmt keinen Schaden

Obwohl dies nicht der Fall ist, da die Gesundheitsvariable bei Kollision mit meiner Projektilexplosion nicht betroffen ist.

Meine Klassen Enemy und Barrel erben von Entity, die den Schaden übernehmen (Subtrahieren der Schadensvariable von der Health-Variable). Obwohl nur die Fassklasse wie vorgesehen funktioniert.

Die Tags sind zu 100% korrekt und ich würde lieber die Vererbung verwenden, also bitte keine Vorschläge, um die Methode zu ändern, in der meine Klassen Schaden erleiden.

die Klasse, die Enemy und Barrel vererben

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 Klasse

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 Klasse

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 die Klasse, die den Schaden sendet

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

Entschuldigung, das ist ein bisschen langwierig und ALLES ist richtig getaggt, also ist das nicht das Problem, danke.

+0

nur neugierig: Gibt es einen Grund für die Erben von einer anderen Klasse anstelle einer Schnittstelle wie 'IHittable'? – garglblarg

+1

@garglblarg Ich bin mir nicht sicher, ich bin ein Student, der Spielprogrammierung an der Uni studiert und das ist genau die Art und Weise, wie wir es gelernt haben. – jozza710

+0

was genau funktioniert nicht? Verliert der Gesundheitswert deines Gegners nicht, wenn 'takeDamage' aufgerufen wird? –

Antwort

4

Problem 1.

Use "debug.log" überall

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

Insbesondere in Entity und Feind.

Fragen wie diese werden sofort durch das Tracking mit Debug.Log beantwortet.


Problem 2.

Es ist ein PITA die Beziehungen zwischen den Auslöser, Starrkörper bekommen usw.

Es ist sehr wahrscheinlich, dass ein Problem hier.

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

Runter zu der lästigen "Trigger-Aktion Matrix" und von dort aus arbeiten.


Problem 3.

Verwenden Sie in der Regel nie die Funktion "Tags" in Unity. (Sie nur Tags hinzugefügt „Hallo Welt“ Tutorials zu helfen.)

In der Praxis verwenden Sie Schichten überall und immer:

enter image description here

(Schichten sind besonders wichtig in Shootern: jede einzelne Kategorie muss ein Schicht.)


Problem 4.

Der Code auf jeden Fall gezeigt, sieht gut aus. Hier ist ein Beispielcode, der für Tipp-Tipps deinem nicht unähnlich ist.

Trivial Beispiel, beachten Sie die Ausreißer-Code (die Rückkehr) innerhalb der OnTrigger, sollten Sie das tun). Auch

,

Verwendung extentions

überall und immer in der Einheit. Quick tutorial

es ist der Tipp # 1, wenn Sie wirklich professionell arbeiten möchten.

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

ist leichter, wenn in ExplosionAOE/OnTriggerEnter Funktion können Sie die takeDamage Funktion aufrufen:

scriptCall = otherObject.GetComponent (EnemyScript);

scriptCall.takeDamage (Schaden);