2016-03-20 4 views
-1

Update mit ...Objekte ihre eigenen einzigartigen Wegpunkte Array

First Class

using UnityEngine; 
using System.Collections; 

[System.Serializable] 
public class Wave 
{ 
    public GameObject enemyPrefab; 
    public float spawnInterval = 2; 
    public int maxEnemies = 20; 
} 

public class SpawnEnemy : MonoBehaviour 
{ 

    public GameObject[] waypoints; 
    public GameObject testEnemyPrefab; 

    public Wave[] waves; 
    public int timeBetweenWaves = 5; 

    private GameManagerBehavior gameManager; 

    private float lastSpawnTime; 
    private int enemiesSpawned = 0; 

    // Use this for initialization 
    void Start() 
    { 
     lastSpawnTime = Time.time; 
     gameManager = 
      GameObject.Find("GameManager").GetComponent<GameManagerBehavior>(); 
    } 

    // Update is called once per frame 
    void Update() 
    { 
     // 1 Get the index of the current wave, and check if it’s the last one. 
     int currentWave = gameManager.Wave; 
     if (currentWave < waves.Length) 
     { 
      // 2 If so, calculate how much time passed since the last enemy spawn and whether it’s time to spawn an enemy. Here you consider two cases. 
      // If it’s the first enemy in the wave, you check whether timeInterval is bigger than timeBetweenWaves. 
      // Otherwise, you check whether timeInterval is bigger than this wave’s spawnInterval. In either case, you make sure you haven’t spawned all the enemies for this wave. 
      float timeInterval = Time.time - lastSpawnTime; 
      float spawnInterval = waves[currentWave].spawnInterval; 
      if (((enemiesSpawned == 0 && timeInterval > timeBetweenWaves) || 
       timeInterval > spawnInterval) && 
       enemiesSpawned < waves[currentWave].maxEnemies) 
      { 
       // 3 If necessary, spawn an enemy by instantiating a copy of enemyPrefab. You also increase the enemiesSpawned count. 
       lastSpawnTime = Time.time; 
       GameObject newEnemy = (GameObject) 
        Instantiate(waves[currentWave].enemyPrefab); 
       newEnemy.GetComponent<MoveEnemy>().waypoints = waypoints; 
       newEnemy.GetComponent<MoveEnemy>().JiggleWaypoints(); 
       enemiesSpawned++; 
      } 
      // 4 You check the number of enemies on screen. If there are none and it was the last enemy in the wave you spawn the next wave. 
      // You also give the player 10 percent of all gold left at the end of the wave. 
      if (enemiesSpawned == waves[currentWave].maxEnemies && 
       GameObject.FindGameObjectWithTag("Enemy") == null) 
      { 
       gameManager.Wave++; 
       gameManager.Gold = Mathf.RoundToInt(gameManager.Gold * 1.1f); 
       enemiesSpawned = 0; 
       lastSpawnTime = Time.time; 
      } 
      // 5 Upon beating the last wave this runs the game won animation. 
     } 
     else { 
      gameManager.gameOver = true; 
      GameObject gameOverText = GameObject.FindGameObjectWithTag("GameWon"); 
      gameOverText.GetComponent<Animator>().SetBool("gameOver", true); 
     } 
    } 
} 

zweiter Klasse

using UnityEngine; 
using System.Collections; 

public class MoveEnemy : MonoBehaviour 
{ 

    [System.NonSerialized] 
    public GameObject[] waypoints; 
    private int currentWaypoint = 0; 
    private float lastWaypointSwitchTime; 
    public float speed = 1.0f; 

    // Use this for initialization 
    void Start() 
    { 
     lastWaypointSwitchTime = Time.time; 
    } 

    // Update is called once per frame 
    void Update() 
    { 
     // 1 
     Vector3 startPosition = waypoints[currentWaypoint].transform.position; 
     Vector3 endPosition = waypoints[currentWaypoint + 1].transform.position; 
     // 2 
     float pathLength = Vector3.Distance(startPosition, endPosition); 
     float totalTimeForPath = pathLength/speed; 
     float currentTimeOnPath = Time.time - lastWaypointSwitchTime; 
     gameObject.transform.position = Vector3.Lerp(startPosition, endPosition, currentTimeOnPath/totalTimeForPath); 
     // 3 
     if (gameObject.transform.position.Equals(endPosition)) 
     { 
      if (currentWaypoint < waypoints.Length - 2) 
      { 
       // 3.a 
       currentWaypoint++; 
       lastWaypointSwitchTime = Time.time; 
       RotateIntoMoveDirection(); 
      } 
      else { 
       // 3.b 
       Destroy(gameObject); 

       AudioSource audioSource = gameObject.GetComponent<AudioSource>(); 
       AudioSource.PlayClipAtPoint(audioSource.clip, transform.position); 
       //<< deduct health 
       GameManagerBehavior gameManager = 
    GameObject.Find("GameManager").GetComponent<GameManagerBehavior>(); 
       gameManager.Health -= 1; 
       //>> 
      } 
     } 
    } 

    public void JiggleWaypoints() 
    { 
     for (int i = 1; i < waypoints.Length; i++) 
     { 
      waypoints[i].transform.position = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 3), waypoints[i].transform.position.y + Random.Range(-3, 3), 0); 
     } 
    } 

    private void RotateIntoMoveDirection() 
    { 
     //1 It calculates the bug’s current movement direction by subtracting the current waypoint’s position from that of the next waypoint. 
     Vector3 newStartPosition = waypoints[currentWaypoint].transform.position; 
     Vector3 newEndPosition = waypoints[currentWaypoint + 1].transform.position; 
     Vector3 newDirection = (newEndPosition - newStartPosition); 
     //2 It uses Mathf.Atan2 to determine the angle toward which newDirection points, in radians, assuming zero points to the right. 
     // Multiplying the result by 180/Mathf.PI converts the angle to degrees. 
     float x = newDirection.x; 
     float y = newDirection.y; 
     float rotationAngle = Mathf.Atan2(y, x) * 180/Mathf.PI; 
     //3 Finally, it retrieves the child named Sprite and rotates it rotationAngle degrees along the z-axis. 
     // Note that you rotate the child instead of the parent so the health bar — you’ll add it soon — remains horizontal. 
     GameObject sprite = (GameObject) 
      gameObject.transform.FindChild("Sprite").gameObject; 
     sprite.transform.rotation = 
      Quaternion.AngleAxis(rotationAngle, Vector3.forward); 
    } 

    public float distanceToGoal() 
    { 
     float distance = 0; 
     distance += Vector3.Distance(
      gameObject.transform.position, 
      waypoints[currentWaypoint + 1].transform.position); 
     for (int i = currentWaypoint + 1; i < waypoints.Length - 1; i++) 
     { 
      Vector3 startPosition = waypoints[i].transform.position; 
      Vector3 endPosition = waypoints[i + 1].transform.position; 
      distance += Vector3.Distance(startPosition, endPosition); 
     } 
     return distance; 
    } 
} 

-Code 100% fehlerfrei funktioniert, aber. ... Nach jedem Spawn erhalten alle Objekte das gleiche Wegpunktarray. Dies ist auf dem Bildschirm zu sehen, wenn alle Objekte jedes Mal, wenn ein neues Objekt erzeugt wird, zu einem neuen Wegpunkt in einer Linie springen. Ich möchte, dass das Objekt, das bereits spawnt, das Leben mit seiner eigenen Anordnung von nur einmal erstellten Wegpunkten führt.

+0

Welche Fehler erhalten Sie? –

+0

NullReferenceException: Objektreferenz nicht auf eine Instanz eines Objekts festgelegt. MoveEnemy.Start() (unter Assets/Scripts/MoveEnemy.cs: 21) – David

+0

Mögliches Duplikat von [Fehler bei Verwendung der Variablen einer Klasse mit Instanz eines anderen] (http : //stackoverflow.com/questions/36116144/error-when-using-variable-of-one-class-with-instance-of-another) – Fattie

Antwort

2

Sie müssen jedes Mal ein neues Array von Wegpunkten erstellen, wenn Sie eines aus dem vorgefertigten Objekt erstellen. Sie zeigen nicht Ihre Instantiate Methode, aber ich vermute, dass es eine Zeile wie diese hat:

this.waypoints = prefab.waypoints; 

Dies bedeutet, dass alle Objekte, die Sie die gleiche Liste von Wegpunkten wird gemeinsam schaffen (wie Sie haben entdeckt) .

Was Sie brauchen, ist so etwas wie dies - unter der Annahme, dass die Wegpunkte haben X, Y und Z-Eigenschaften):

this.waypoints = new GameObject[5]; 
for (int i = 0; i++ ; i < 5) 
{ 
    this.waypoints[i].X = prefab.waypoints[i].X; 
    this.waypoints[i].Y = prefab.waypoints[i].Y; 
    this.waypoints[i].Z = prefab.waypoints[i].Z; 
} 

(Wenn Sie Ihre Punkte wollen eine variable Länge haben Sie vielleicht prüfen wollen mit eine Liste).

Dies bedeutet, dass jedes Objekt eine Liste von eindeutigen Punkten aufweist, auch wenn sie mit denselben Werten beginnen, die Sie unabhängig voneinander ändern können.

+0

Bitte überprüfen Sie Update – David

0

Basierend auf ChrisFs' und Joe Blows' Antworten, etwas zu tun, wie dies in Ihrem MoveEnemy Skript:

private Vector3[] myWay; 

public void JiggleWaypoints(GameObject[] waypoints) 
{ 
    myWay = new Vector3[waypoints.Length]; 
    for(int i = 1; i < waypoints.Length; i++) 
    { 
     myWay[i] = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 4), waypoints[i].transform.position.y + Random.Range(-3, 4), 0); 
    } 
} 

myWay die GameObject[] ersetzt.

In Ihrem SpawnEnemy Skript tun Sie dies:

GameObject e = (GameObject)Instantiate(enemyPrefab); 
e.GetComponent<MoveEnemy>().JiggleWaypoints(waypoints); 
Verwandte Themen