Jump to content
Unity Insider Forum

Gegner macht keinen Schaden


ThegreenY

Recommended Posts

GELÖST!!!!!!!!!!!!!

Hallo ich bin neu hier weil ich vor kurzem erst angefangen habe mit Unity 3D Spiele zu erstellen.

Nun habe ich einen Gegner hinzugefügt und versucht das er dem Spieler Schaden zufügt (ihn verletzt). Dies scheint aber nicht zu funktionieren hoffe das mir jemand helfen kann. Habe Folgende Scripte:

 

EnemyHealth.js

var health = 100;

function ApplyDamage (damage : int)
{
  health -= damage;

  if(health <= 0)
  {
   Dead();
}
}

function Dead()
{
Destroy (gameObject);
}

 

PlayerHealth.js

 

var health = 100;

function ApplyDamage (damage : int)
{
health -= damage;

if(health <= 0)
{
Dead();
}
}

function Dead()
{
Debug.Log("Der Spieler wäre jetzt tot.");
}

 

AdvancedAI.js

 

var damage = 10;

var distance;
var target : Transform;
var lookAtDistance = 20.0;
var attackRange = 10.0;
var attackHitRange = 1.5;
var moveSpeed = 5.0;
var smoothness = 7.0;

var attackInterval = 0.5;
private var attackTime : float;

var controller : CharacterController;
var gravity : float = 20.0;
private var moveDirection : Vector3 = Vector3.zero;

function Start ()
{
attackTime = Time.time;
}

function Update ()
{
distance = Vector3.Distance(target.position, transform.position);

if (distance > lookAtDistance)
{
GetComponent.<Renderer>().material.color = Color.green;
}

if (distance < lookAtDistance)
{
GetComponent.<Renderer>().material.color = Color.yellow;
lookAt ();
}

if (distance < attackHitRange)
{
GetComponent.<Renderer>().material.color = Color.blue;
attackHit ();
}

else if (distance < attackRange)
{
GetComponent.<Renderer>().material.color = Color.red;
attack ();
}
}

function lookAt ()
{
var rotation = Quaternion.LookRotation(target.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * smoothness);
}

function attack ()
{
moveDirection = transform.forward;
moveDirection *= moveSpeed;
moveDirection += Vector3.up * -gravity;
controller.Move(moveDirection * Time.deltaTime);
}

function attackHit ()
{
if (Time.time > attackTime)
{
target.SendMessage("GetDamage", damage, SendMessageOptions.DontRequireReceiver);
attackTime = Time.time + attackInterval;
}
}

 

EnemyStats.js

 

var health = 100;
var healPoints = 20;
var target : Transform;

function ApplyDamage (damage : int)
{
health -= damage;

if (health <= 0)
{
Dead();
}
}

function Dead ()
{
target.SendMessage("increaseHealth", healPoints, SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}

 

PlayerStats.js

 

import UnityEngine.UI;

var maxHealth : float = 100;
var currentHealth : float = 0;
var bar : Image;

function Start ()
{
currentHealth = maxHealth;
}

function GetDamage (damage : int)
{
currentHealth -= damage;
healthBar ();

if (currentHealth <= 0)
{
Debug.Log("Der Spieler wäre jetzt tot.");
}
}

function healthBar ()
{
bar.fillAmount = currentHealth / maxHealth;
}

function increaseHealth (healPoints : int)
{
currentHealth += healPoints;

if (currentHealth > maxHealth)
{
currentHealth = maxHealth;
}

healthBar ();
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ohne jetzt deinen Code voll gelesen zu haben, frage ich erstmal, hast du dir den Code irgentwo aus dem Netz gehohlt? Das ist ansich zwar kein Problem nur schleichen sich dabei oft Fehler ein. So wie es aussieht übernehmen die jeweiligen Statsscripte die gleiche Funktion der Healthscripte, auch wenn diese etwas erweitert ist.

 

Kleiner Tipp von mir: Versuch die ganze Sache eigenständig zu machen. Sprich informier dich über die einzelnen Datentypen(int, string, float usw) und über die SendMassage Befehle. Dazu noch die grundsätzlichen Sachen über Funktionen und schon steht deinen eigenen Healthscript nichts mehr im weg. Falls du dann immer noch probleme hast, kannst du dich nartürlich gerne Nachfragen, die leute helfen echt gerne.

 

p.s viele Leuten hier Programmieren in C#, daher würde ich dir empfehlen auch gleich diese Sprache nutzen, auch wen javascript auf dem ersten Blick einfacher aussieht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erstmal ein herzliches Willkommen! :)

Dann zur Lesbarkeit des Codes:

Es gibt hier nette CodeTags, einfach die <> in der Menüleiste anklicken. Dadurch werden die Tags im Text erzeugt. Dann einfach den Code zwischen die beiden Tags einfügen.

Ich mach das mal für dich. :)

 

Ja und dann zu deinem Problem:

Du sendest via Sendmessage an eine Funktion mit Namen GetDamage. Die ist aber garnicht da! Deine Funktionen heissen ApplyDamage!

Da du das DontRequireReceiver bei der Sendmessage Funktion nutzt, wird dir das Problem nicht angezeigt.

Wäre das nicht da, dann würdest du in der Console eine Fehlermeldung bekommen.

DontRequireReceiver bedeutet ja auf deutsch "Scheißegal ob da ein Empfänger ist" und deswegen ist es Unity auch egal! ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Es ist egal, welche Sprache du benutzt. Dein SendMessage-Befehl macht genau das, was du ihm sagst.

Und der String "GetDamage" repräsentiert den Namen der Funktion, in die du rein springen willst.

Da muss jeder Buchstabe stimmen. Ja und wenn du eine Message an "GetDamage" sendest, aber keine Funktion mit Namen "GetDamage" da ist, dann läuft die Message ins Leere.

Du hast zwar in den Stats Scripten die GetDamage Funktion drin, aber die ist ja augenscheinlich nur für die Anzeige der Healthbar da.

Bei PlayerHealth und EnemyHealth heißt die Funktion ApplyDamage.

Also entweder machst du 2 mal Sendmessage, einmal mit Get und einmal mit Apply, oder aber du änderst den Namen der Funktion in den Health Scripten auf GetDamage ab.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was soll ich denn da für dich erledigen? Du wirst doch wohl selber ein Wort abändern können?!

Mir scheint, du hast die Scripte jetzt irgendwo her und weißt garnicht was sie machen. So wirst du aber nicht weiter kommen, denn wenn du nicht verstehst was da passiert, bleibst du genau auf dem jetzigen Wissensstand stehen.

 

2 Tipps werde ich dir geben, aber dann musst du selber weiter kommen. Und da du scheinbar wirklich am Anfang stehst, kannst du auch gleich mit c# anfangen, denn da gibt es mehr Tutorials zu, wie zum Beispiel meine auf Youtube. Ich heiße da MrMalzbie. https://www.youtube.com/user/MrMalzbie

 

Dein AI Script hat eine target Variable, die wahrscheinlich der Player sein soll. Da du im Script nirgends nach dem Player suchst und die target Variable mit dem Player bestückst, hast du ihn wahrscheinlich im Inspector einfach in den Slot gezogen.

Wie dem auch sei, das AI Script nutzt die Position des Players und wertet die Entfernung von sich zum Player aus. Je nach Entfernung wird die Farbe seines Materials geändert und es wird in unterschiedliche Funktionen gesprungen.

Wenn der Player ganz nah ist, wird in die Funktion attackHit gesprungen, wo dann der SendMessage Befehl ausgeführt wird.

 

target.SendMessage("GetDamage", damage, SendMessageOptions.DontRequireReceiver);

Jetzt wird also an das target eine Nachricht gesendet, die da heißt:

Hey target , hier ist eine Nachricht an die Funktion GetDamage, und zwar ist es der Wert, den ich selber in der Variable damage gespeichert habe. Mach was draus!

 

Das target, also dein Player, schaut jetzt in jedem Script nach, ob denn dort eine Funktion mit Namen GetDamage ist, und wenn ja, dann übergibt sie den Wert der damage-Variable an diese Funktion. Und das passiert bei jedem Script , welches auf dem Player liegt.

Wären also 2 Scripte auf dem Player die beide die Funktion GetDamage haben, dann würden auch beide Funktionen den Wert übergeben bekommen und würden mit dem Wert etwas abarbeiten.

Wenn jetzt aber in keinem Script die Funktion GetDamage zu finden ist, dann würde das target dem Sender das mitteilen.

Es würde also sagen: Hey Sender, bei mir gibt es kein GetDamage, da hast du dich wohl vertan!

Diese Meldung würdest du in der Console sehen und dir würde auffallen, dass da etwas nicht stimmt.

Jetzt hast du aber eine Sendeoption gewählt, die DontRequireReceiver heißt. Und die besagt, dass der Sender nicht wissen will, ob der Empfänger, also die Funktion GetDamage, überhaupt da ist. Tja, und weil das so eingestellt ist, sagt das target dem Sender jetzt nichts mehr. Entweder die Funktion ist da und der Wert wird übergeben, oder die Funktion ist nicht da und die Nachricht wandert stillschweigend in den Müll. Den Sender interessiert es ja nicht.

 

Du musst jetzt also sicherstellen, dass die Nachricht auch einen Empfänger hat.

Wenn der Empfänger GetDamage heisst, dann sendest du an GetDamage. Wenn der Empfänger ApplyDamage heißt, dann sendest du an ApplyDamage.

Du kannst auch 2 Nachrichten mit selben Inhalt senden, wenn es, so wie bei dir, 2 unterschiedliche Empfänger gibt.

 

target.SendMessage("GetDamage", damage, SendMessageOptions.DontRequireReceiver);
target.SendMessage("ApplyDamage", damage, SendMessageOptions.DontRequireReceiver);

Link zu diesem Kommentar
Auf anderen Seiten teilen

Da wir schon bei dem Thema Tutorials sind: Falls du ein paar Euronen übrig hast, kann ich dir das Buch ans Herz legen. Insbesondere die kompakte C# Einführung und das gute Stichwortverzeichnis sind hilfreich. Wenn man irgendwas nicht versteht oder wissen möchtest, findet man blitzschnell eine Antwort dadrin. Das Buch hat mir am Anfang sehr geholfen mich in Unity zurecht zu finden.

Den Autor findet man auch bei Youtube und ich meine er ist auch hier im Forum vertreten.

 

 

@malzbie: Sieht echt toll aus dein Kanal, werd mich da ggf auch mal durchklicken :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kenne ihn übrigens schon aber bin nicht mehr auf seinen Kanal gekommen kann ich auch was aus der 2D reihe nehmen wenn ich ein 3D Spiel erstelle??

 

Theoretisch schon, kommt aber auch drauf an was du nehmen möchtest. Und du musst ggf. Kleinigkeiten verändern können, damit es in ein 3D Spiel passt.

Den grundsätzlichen Umgang mit Unity kann man aber so oder so gut mit einer 2D Reihe lernen ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

So habe nochmal eine kurze frage!

Habe nun ein Script erstellt womit der NPC von einem zum anderen Punkt läuft.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Waypointwalker : MonoBehaviour {
   public List<Vector3> waypointPositions;
   public float speed = 1;
   int currentWaypoint = 0;
   Vector3 targetPositionDelta;
   Vector3 moveDirection = Vector3.zero;
   SpriteController spriteController;
   bool lookRight = true;
// Use this for initialization
void Start () {
    spriteController = GetComponent<SpriteController>();
}

// Update is called once per frame
void Update () {
    Waypointwalk();
    Move();
}
   void Waypointwalk()
   {
    Vector3 targetPosition = waypointPositions[currentWaypoint];
    targetPositionDelta = targetPosition - transform.position;
    if (targetPositionDelta.sqrMagnitude <= 1)
    {
	    currentWaypoint++;
	    if (currentWaypoint>=waypointPositions.Count)
		    currentWaypoint = 0;
    }
    else
    {
		 if (targetPositionDelta.x > 0)
	    {
		    lookRight = true;
	    }
		 else
	    {
		    lookRight = false;
	    }
    }
   }
   void Move()
   {
    moveDirection = targetPositionDelta.normalized * speed;
    transform.Translate(moveDirection *Time.deltaTime,Space.World);
   }
}

Geht es auch das er Random rumläuft und nicht nur nach punkten?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...