Jump to content
Unity Insider Forum

Garzec

Members
  • Gesamte Inhalte

    308
  • Benutzer seit

  • Letzter Besuch

  • Tagessiege

    2

Garzec hat zuletzt am 12. Januar 2021 gewonnen

Garzec hat die beliebtesten Inhalte erstellt!

Letzte Besucher des Profils

2.335 Profilaufrufe

Garzec's Achievements

Advanced Member

Advanced Member (3/3)

7

Ansehen in der Community

  1. Mein Ziel ist es ein Spiel ähnlich zu dieser Vorlage zu erstellen Das Spiel ist zwar ein Voxel Game, aber für den Code kann man es ja als 2D Grid betrachten. Wie im Video zu sehen ist das Spiel rundenbasiert. Ich gebe also Input rein, der Spieler bewegt sich und bis zum Ende der Runde ist weiterer Input deaktiviert. Zunächst gibt es Obstacles und Trigger, die auf bestimmte Dinge reagieren. Obstacles wären also Wände, Bäume, Tische, ... Diese kann ich mir in einer Liste merken oder einzeln betrachten, zumindest reicht es aus, wenn alle 4 Außenseiten ein Obstacle haben, um die Zelle vollständig zu blockieren. public class Obstacle : MonoBehaviour { [SerializeField] Vector2Int relativePosition; public Vector2Int RelativePosition { get { return relativePosition; } } } NPCs müssten aber auch Obstacles haben, damit der Spieler nicht in diese reinlaufen kann. Die Trigger sind etwas komplexer. Bei einem Loch oder Feuer, das die Bewegung der Figur stoppt und diese tötet reicht es aus, dieses optisch im Zentrum zu platzieren und wieder an alle 4 Seiten einen "Death-Trigger" anzubringen. Ein Lichtschalter kann an einer Seite angebracht sein und nur ausgelöst werden, wenn sich der Spieler auf das Feld bewegt und diesen "anschaut". Wenn also der Lichtschalter relativ zur Zellenposition "nördlich" steht, also (0|1) dann muss der Spieler diese Bewegungsrichtung haben, um ihn auszulösen. Wenn rot ein Lichtschalter ist und grün der Spieler mit einer Bewegung nach links , dann würde der Spieler den Lichtschalter nicht auslösen, da er sich ja nicht zum Schalter bewegt. Blau würde diesen auslösen Eine Druckplatte würde den Spieler nicht stoppen, dennoch eine Aktion auslösen. Steht der Spieler vor einem NPC, wird er diesen töten. Steht der Spieler neben einem NPC, wird dieser NPC von ihm weglaufen. Das gilt natürlich nur, wenn sich zwischen den beiden keine Wand befindet. Der NPC könnte natürlich auch eine Waffe haben und den Spieler töten, falls der Spieler vor dem NPC stehen bleibt. Wenn man die Obstacles nun auch einfach als Trigger betrachtet, die andere Objekte stoppen, könnte erstmal alles ein Trigger sein. Ich würde erstmal so vorgehen, dass jede Position an jeder Seite 0 - n Trigger haben kann. Je nachdem, wie eine Figur am Ende ihrer Bewegung steht, reagieren dann die umliegenden Trigger. Die Position selbst würde also erstmal so etwas speichern `Dictionary<RelativePosition, List<Trigger>>` Das einzige Problem, dass ich noch nicht gelöst habe ist: Wenn sich ein NPC bewegt, dann müsste man wissen, welche Trigger er zur neuen Zelle mitnimmt (töten, weglaufen, ...) und welche Trigger bei der Position bleiben (Wand als Obstacle, Lichtschalter an einer Seite, ...). Vielleicht hat ja jemand eine Idee oder hat vielleicht einen viel besseren Ansatz
  2. Das Problem wurde schon teilweise gelöst. Der Code ist korrekt, ebenso sind die Felder im Inspector zugewiesen. Dennoch haben die Collectables als Objektreferenz der Highscore zuerst die richtige Instanz und danach eine .. warum auch immer .. nicht existierende Instanz. Das kam wohl dadurch zustande, dass Objekte in der Szene erstellt wurden, diese dann den Collectables zugewiesen wurden. Dann wurden diese Objekte zu Prefabs gemacht und gelöscht, dann wurde alles nochmal im Asset Ordner zugewiesen und wahrscheinlich ging es dann ein wenig durcheinander bei Unity, sodass bei seiner Version keine richtige Referenz mehr durch den Inspector besteht. Nimmt man die Inspectorzuweisung weg und lässt kurz per Tag suchen, funktioniert es.
  3. Hallo, ich habe hier ein Projekt eines Unity Anfängers hochgeladen. Das Minispiel ist ein typisches "Dinge fallen vom Himmel, du musst sie einsammeln, manche Dinge bringen Punkte, manche Dinge ziehen dir Punkte ab" - Spiel. Das Projekt an sich ist extrem simpel gehalten, in 5 min. nachgebaut etc. Nun gibt es zwei Probleme: 1. Das Highscore-Text-Element updated sich trotz txt.text = currentHighscore.ToString(); nicht. Obwohl er laut Debugger immer in die Methode reingeht. Das finde ich sehr komisch, da sich der Text im Spiel eigentlich verändern sollte, der Wert ist ja erstmal egal. Aber da er in die Methode reinkommt, sollte sich da am Canvas etwas tun. 2. currentHighscore wird bei jedem Spielstart nicht wieder auf 0 gesetzt, obwohl im Code bei der Initialisierung die Variable mit 0 beginnt. Die Variable merkt sich immer den Wert des letzten Spielstandes. Ebenfalls sehr komisch, da beim Spielstart, also ein kompletter Reset, ja nirgendwo Daten gespeichert werden. Man baut das Spiel ja quasi neu. Ich selbst habe das Ganze mal bei mir am PC nachgebaut (gleicher Code) und es funktioniert wunderbar. Hat jemand Interesse, über das Projekt drüberzuschauen und möglicherweise zu entdecken, wieso diese beiden Probleme auftauchen? Ich hoffe, dass es ein ganz dummer Fehler ist, aber bei meinem nachgebauten Projekt trat dieser nicht auf. Ich selbst bin nur etwas überfragt, wieso bei ihm Werte außerhalb der Laufzeit übernommen werden und sich sein Text Element nicht updatet... Feed_Me_Fool.rar
  4. Hallo, ich habe hier den A* Algorithmus angefangen. Das Ziel wird schon angelaufen (von unten links nach oben rechts). Es gibt verschiedene Feldkosten, der Wert 0 bedeutet nicht begehbar, da werde ich noch etwas passenderes wählen, aber das soll es erst einmal sein. An manchen Stellen springt der zu bewegende Gegenstand noch ein wenig hin und her, da noch nicht die einzig relevanten Felder in der Liste stehen. Hier zuerst mal der Code dazu, das map Objekt baut die Map auf und hält alle Zellen in einem 2D Array vom Typ Cell. Jede Zelle kennt dann ihre Feldkosten, ihren Index auf der Karte muss sie ja nicht kennen. private List<Vector2Int> openCells = new List<Vector2Int>(); private List<Vector2Int> closedCells = new List<Vector2Int>(); private void CalculatePath() { openCells.Clear(); closedCells.Clear(); openCells.Add(Settings.startPosition); Vector2Int currentCellPosition = Settings.startPosition; while (!PositionEquals(currentCellPosition, Settings.targetPosition) && openCells.Count > 0) { Vector2Int cheapestCellPosition = openCells .OrderBy(x => GetCostToTarget(x, Settings.targetPosition) + GetCell(x).Cost) .First(); AddNeighbourPosition(cheapestCellPosition, Vector2Int.up); AddNeighbourPosition(cheapestCellPosition, Vector2Int.left); AddNeighbourPosition(cheapestCellPosition, Vector2Int.down); AddNeighbourPosition(cheapestCellPosition, Vector2Int.right); closedCells.Add(cheapestCellPosition); openCells.Remove(cheapestCellPosition); currentCellPosition = cheapestCellPosition; } } private void AddNeighbourPosition(Vector2Int currentPosition, Vector2Int neighbourDirection) { Vector2Int targetPosition = currentPosition + neighbourDirection; if (CellExistsOnMap(targetPosition)) { if (CellIsWalkable(targetPosition)) { if (!CellExamined(targetPosition)) { openCells.Add(targetPosition); } } } } private bool PositionEquals(Vector2Int startPosition, Vector2Int targetPosition) { return startPosition.Equals(targetPosition); } private bool CellIsWalkable(Vector2Int position) { return GetCell(position).Cost != 0; } private Cell GetCell(Vector2Int position) { return map.Cells[position.x, position.y]; } private int GetCostToTarget(Vector2Int startPosition, Vector2Int targetPosition) { return Mathf.Abs(startPosition.x - targetPosition.x) + Mathf.Abs(startPosition.y - targetPosition.y); } private bool CellExistsOnMap(Vector2Int position) { int horizontalLength = Settings.fields.GetLength(0); int verticalLength = Settings.fields.GetLength(1); Rect mapRect = new Rect(0, 0, horizontalLength, verticalLength); return mapRect.Contains(position); } private bool CellExamined(Vector2Int position) { return openCells.Contains(position) || closedCells.Contains(position); } Nun habe ich gelesen, dass man sich im Algorithmus noch merken muss, wo man hergekommen ist und sich dementsprechend noch die bisher verbrauchten Kosten merkt und verrechnet. Das habe ich aber noch nicht so ganz verstanden, könnte mir jemand beim Algorithmus weiterhelfen?
  5. Habe es gekürzt bekommen, die Rotationen stimmen aber nicht. public class InterferometricCube : MonoBehaviour { [SerializeField] private Projectile projectileLeft; [SerializeField] private Projectile projectileRight; private void OnCollisionEnter(Collision collision) { HandleProjectile(collision); } private void HandleProjectile(Collision collision) { GameObject collidingObject = collision.gameObject; Projectile projectileComponent = collidingObject.GetComponent<Projectile>(); if (projectileComponent) { Vector3 hitNormal = collision.contacts.First().normal; Vector3 other = Vector3.Cross(hitNormal, collidingObject.transform.up); SpawnProjectile(projectileRight, other); SpawnProjectile(projectileLeft, -other); SpawnProjectile(projectileComponent, -hitNormal); } } private void SpawnProjectile(Projectile projectile, Vector3 direction) { Vector3 spawnPoint = direction + transform.position; projectile.InitProjectile(spawnPoint, Quaternion.Euler(direction)); /* -- InitProjectile -- transform.position = startPosition; transform.rotation = startRotation; currentMovementDirection = transform.forward; */ } } Ich verwende eine TopDown Sicht Egal, von welcher Seite ich auf den Würfel schieße, ein Projektil fliegt immer "nach oben". Das Projektil "nach unten" bleibt im Würfel stecken, da muss ich wohl für die Projektile noch einen Abstand für ihre Achse einberechnen. Das Projektil, mit dem ich auf den Würfel schieße, fliegt idR ebenfalls "nach oben". Hat jemand eine Idee?
  6. Hallo, schieße ich mit einem Projektil auf einen Würfel, so sollen über die getroffene Seite folgende Mittelpunkte berechnet werden: gegenüberliegenden Seite linke Seite rechte Seite Die drei neuen Punkte dienen mir danach als Grundlage für Spawnpositionen. Ich habe schon einmal den Code vorbereitet: public class InterferometricCube : MonoBehaviour { [SerializeField] private Vector3 cubeScale; // Größe des Würfels private const float SPAWN_SPACING = 1.5f; // Abstand zum Würfel private void OnCollisionEnter(Collision collision) { CheckProjectile(collision); } private void CheckProjectile(Collision collision) { Projectile projectileComponent = collision.gameObject.GetComponent<Projectile>(); if (projectileComponent) // ist das kollidierende Objekt ein Projektil? { Vector3 contactPoint = collision.contacts.First().normal - transform.up; Vector3[] directions = null; if (contactPoint == new Vector3(0, -1, -1)) // transform.forward // vorne { Vector3[] targetDirections = { -transform.forward, transform.right, -transform.right }; directions = targetDirections; } else if (contactPoint == new Vector3(0, -1, 1)) // -transform.forward // hinten { Vector3[] targetDirections = { transform.forward, transform.right, -transform.right }; directions = targetDirections; } else if (contactPoint == new Vector3(1, -1, 0)) // -transform.right // links { Vector3[] targetDirections = { -transform.forward, transform.right, transform.forward }; directions = targetDirections; } else if (contactPoint == new Vector3(-1, -1, 0)) // transform.right // rechts { Vector3[] targetDirections = { -transform.forward, transform.forward, -transform.right }; directions = targetDirections; } if (directions != null) { SpawnProjectiles(directions); } } } private void SpawnProjectiles(Vector3[] directions) { for (int i = 0; i < directions.Length; i++) { Vector3 currentDirection = directions[i]; // Spawnrotation Vector3 spawnPoint = currentDirection + transform.position + cubeScale; // Spawnposition spawnPoint *= SPAWN_SPACING; // Abstand setzen Debug.Log(spawnPoint); } } } Innerhalb von CheckProjectile berechne ich anhand der Normalen die anderen drei Seiten. Leider springt mir dort der doppelte Code ins Gesicht und möglicherweise kann man dies ja viel einfacher berechnen. Wäre super, falls mir jemand ein wenig mit Mathe aushelfen könnte, falls es einfacher gehen sollte
  7. Ich habe es erstmal hinbekommen mit public void ReflectProjectile() { RaycastHit hit; Ray ray = new Ray(transform.position, currentMovementDirection); if (Physics.Raycast(ray, out hit)) { currentMovementDirection = Vector3.Reflect(currentMovementDirection, hit.normal); } }
  8. Hallo, beim Abfeuern eines Projektiles verwende ich erstmal folgenden Code private Rigidbody rigid; private Vector3 currentMovementDirection; private void FixedUpdate() { rigid.velocity = currentMovementDirection; } public void InitProjectile(Vector3 startPosition, Quaternion startRotation) { transform.position = startPosition; transform.rotation = startRotation; currentMovementDirection = transform.forward; } Dabei verwende ich InitProjectile als Startmethode, weil ich die Projektile nicht zerstöre sondern recycle (Renderer disablen). Sobald das Projektil auf ein Objekt trifft, das dieses Projektil reflektieren kann, soll das Projektil reflektiert werden. Unity scheint dafür bereits etwas zu haben, https://docs.unity3d.com/ScriptReference/Vector3.Reflect.html Wenn die Collision also getriggert wird private void OnTriggerEnter(Collider other) { if (other.gameObject == projectile) { projectileComponent.ReflectProjectile(); } } Soll das Projektil seine Richtung und Rotation ändern. public void ReflectProjectile() { // Vector3.Reflect(... , ...); } Leider verstehe ich nicht so recht, welche Parameter dort übergeben werden müssen. Ich habe es auch mal auf anderem Wege probiert, indem ich die Velocity mit -1 multipliziere, logischerweise wird dann aber einfach die Bewegungsrichtung umgekehrt. Wäre super, wenn mir jemand mit der Reflektion helfen könnte
  9. Hallo, ich würde mal gerne wissen, wie man ein Ability System aufbaut. Das Spiel selbst wäre 2D TopDown. Ich habe ein System mit Actions aufgebaut, je nachdem, welche Charakterklasse der Spieler auswählt, werden ihm dann bei Spielstart andere Fähigkeiten zugewiesen. public class Ability { public Ability(Action ability, int cooldown, Sprite icon) { AbilityToUse = ability; Cooldown = cooldown; AbilityIcon = icon; CurrentCooldown = Cooldown; } public Action AbilityToUse { get; set; } public float Cooldown { get; set; } public float CurrentCooldown { get; set; } public Sprite AbilityIcon { get; set; } public bool CheckAbilityReady() { return CurrentCooldown >= Cooldown; } public bool IsOnCooldown() { return CurrentCooldown < Cooldown; } public void ResetCooldown() { CurrentCooldown = 0; } public void IncreaseCooldown() { CurrentCooldown += Time.deltaTime; } } Die Fähigkeiten werden dann bei der Initialisierung der Charakterklasse gesetzt AbilityOne = new Ability(PlayerAbilityOne, CooldownAbilityOne, IconAbilityOne); AbilityTwo = new Ability(PlayerAbilityTwo, CooldownAbilityTwo, IconAbilityTwo); AbilityThree = new Ability(PlayerAbilityThree, CooldownAbilityThree, IconAbilityThree); AbilityFour = new Ability(PlayerAbilityFour, CooldownAbilityFour, IconAbilityFour); und durch die Wahl der Klasse definiert, hier mal als Beispiel der Cleric public class Cleric : CharacterClass { // anderes Zeug ... protected override int CooldownAbilityOne { get { return 3; } } protected override int CooldownAbilityTwo { get { return 7; } } protected override int CooldownAbilityThree { get { return 9; } } protected override int CooldownAbilityFour { get { return 35; } } protected override Sprite IconAbilityOne { get { return "PfadZumIcon"; } } protected override Sprite IconAbilityTwo { get { return "PfadZumIcon"; } } protected override Sprite IconAbilityThree { get { return "PfadZumIcon"; } } protected override Sprite IconAbilityFour { get { return "PfadZumIcon"; } } protected override void PlayerAbilityOne() { // Hier Code für Skill 1 } protected override void PlayerAbilityTwo() { // Hier Code für Skill 2 } protected override void PlayerAbilityThree() { // Hier Code für Skill 3 } protected override void PlayerAbilityFour() { // Hier Code für Skill 4 } } Und im Spiel selbst kann ich dann die Fähigkeiten nutzen und deren Cooldowns verwalten. Jetzt zu meiner Frage, macht man das so? Weil dadurch habe ich ja keine Monobehaviours und könnte im Code noch nicht auf Dinge im Spiel zugreifen, falls man mal beispielsweise 5 Projektile erzeugen will oder der Spieler sich heilen kann und man auf die HP zugreifen will. Gibt es einen besseren Weg? Mit Actions kenne ich mich leider nicht perfekt aus, sie dienen aktuell lediglich dazu, die Methoden als Parameter mitgeben zu können.
  10. Habe es gelöst bekommen, meine Berechnung der Wurfrichtung war noch nicht richtig, ebenso habe ich einen Impuls als ForceMode gesetzt Vector3 targetPoint = GetTargetPoint() - transform.position; bomb.GetComponent<Rigidbody>().AddForce(targetPoint.normalized * throwingForce, ForceMode.Impulse);
  11. Hallo, ich habe vier "Würfel"/Spawner, die sich im Uhrzeigersinn um eine Fläche bewegen (Bild). Dabei sollen diese Spawner Bomben spawnen und auf die Fläche in der Mitte werfen. Dies wiederholt sich dann in einem festgelegten Interval, das immer weiter verringert wird. Der Zielpunkt auf der Fläche wird dabei rein zufällig ermittelt, irgendwo auf der Fläche. public class BombSpawner : MonoBehaviour { [Range(0, 3)] [SerializeField] private int nextPointIndex; // der aktuelle Punkt, wo sich der Spawner hinbewegen soll private Vector3[] targetPoints = { // alle möglichen Punkte new Vector3(-15,0,15), new Vector3(15,0,15), new Vector3(15,0,-15), new Vector3(-15,0,-15)}; private float movementSpeed = 5; [SerializeField] private GameObject bombPrefab; private float spawnRate = 5; // das Intervall private float minSpawnRate = 2; private float decreasingSteps = 0.2f; // Intervall um diesen Wert verringern private Vector2 mapSize = new Vector2(25, 25); // Größe der Fläche float mapDeadZone = 2; // äußerer Rand float bombSpawnHeight = 2; // Spawnhöhe über dem Spawner float throwingForce = 10; // Die Kraft beim Wurf private void Start() { Invoke("ThrowBomb", spawnRate); // Erstes Intervall starten } private void Update() { transform.LookAt(Vector3.zero); // Immer zur Mitte der Fläche rotieren Vector3 nextPoint = targetPoints[nextPointIndex]; transform.position = Vector3.MoveTowards(transform.position, nextPoint, movementSpeed * Time.deltaTime); // Zum nächsten Eckpunkt bewegen if (transform.position == nextPoint) { if (nextPointIndex < targetPoints.Length - 1) // nächsten Punkt anwählen nextPointIndex++; else nextPointIndex = 0; // nach dem letzten Eckpunkt wieder vorne anfangen } } private void ThrowBomb() { Vector3 bombSpawnPos = transform.position; bombSpawnPos.y += bombSpawnHeight; GameObject bomb = Instantiate(bombPrefab, bombSpawnPos, Quaternion.identity); // Bombe über dem Spawner erzeugen bomb.GetComponent<Rigidbody>().AddForce(GetTargetPoint() * throwingForce); // Bombe werfen spawnRate = Mathf.Clamp(spawnRate - decreasingSteps, minSpawnRate, spawnRate); // Intervall verringern Invoke("ThrowBomb", spawnRate); // neues Intervall setzen } private Vector3 GetTargetPoint() // Zielpunkt auf der Fläche berechnen { Vector3 targetPoint = Vector3.zero; float mapLengthX = (mapSize.x - mapDeadZone) / 2; float mapLengthZ = (mapSize.y - mapDeadZone) / 2; targetPoint.x = Random.Range(-mapLengthX, mapLengthX); targetPoint.y = 1; // etwas in der Höhe landen, damit die Kugel noch runterfallen und rollen kann targetPoint.z = Random.Range(-mapLengthZ, mapLengthZ); return targetPoint; } } So, die Bewegung funktioniert, das Spawnen der Bomben funktioniert. Nicht funktionieren tut aber der Wurf. Die Bomben fliegen nicht auf die Fläche, sondern eher in die Richtung, aus der der Spawner gekommen ist. Dabei gebe ich doch den Zielpunkt bei bomb.GetComponent<Rigidbody>().AddForce(GetTargetPoint() * throwingForce); eigentlich mit. Gibt es zudem eine Möglichkeit einen parabellförmigen Flug zu simulieren? Die Bombe würde dann beim Aufprall durch ihren Rigidbody noch ein wenig rollen. Habe mal ein Beispielbild dazugepackt.
  12. So, ich habs dann mit der freundlichen Hilfe von @Sascha hinbekommen, sollte es jemanden interessieren, sieht der aktuell funktionierende Code so aus private Transform player; private List<Collectable> collectablesToCollect = new List<Collectable>(); private bool isCollecting = false; private float movementSpeed = 10; private Vector3 currentPosition; private void Start() { player = Globals.GetPlayerObject().transform; } private void Update() { if (CollectablesInRange()) MoveToCollectable(); else FollowPlayer(); } private void OnTriggerEnter(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) { if (!collectable.GetMovementState()) collectablesToCollect.Add(collectable); } } private void OnTriggerExit(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) collectablesToCollect.Remove(collectable); } private void MoveToCollectable() { Collectable collectable = collectablesToCollect.First(); StartCoroutine(CollectionMovement(collectable)); } private IEnumerator CollectionMovement(Collectable collectable) { if (isCollecting) yield break; isCollecting = true; yield return StartCoroutine(MoveToPoint(collectable.GetCollectablePosition())); if (collectable != null) collectable.StartMovingToPlayer(); yield return StartCoroutine(MoveToPoint(currentPosition)); collectablesToCollect.Remove(collectable); if (CollectablesInRange()) MoveToCollectable(); isCollecting = false; } private IEnumerator MoveToPoint(Vector3 targetPosition) { while (transform.position != targetPosition) { transform.position = Vector3.MoveTowards(transform.position, targetPosition, movementSpeed * Time.deltaTime); yield return null; } } private void FollowPlayer() { // TEST Vector3 playerPos = player.position; currentPosition = new Vector3(playerPos.x, playerPos.y + 2, playerPos.z); transform.position = currentPosition; // TEST } private bool CollectablesInRange() { return collectablesToCollect.Count > 0; } Wobei ich die schrittweise Bewegung, also dass der Follower einen Schritt nach dem anderen abarbeitet, mithilfe von den beiden Enumeratoren löse. Dadurch kann der Follower zum Item hinlaufen, ihn einsammeln und wieder zurücklaufen.
  13. Guten Abend, ich versuche die Libelle Sparx aus Spyro nachzubauen, wer nicht weiß, wer das ist hier ein Video Nähert sich Spyro (der Drache) Kristallen, so fliegt Sparx (die Libelle) zu den Kristallen und lässt diese zum Spieler fliegen. Die Logik, dass ein Kristall zum Spieler fliegt habe ich bereits, sagen wir einfach mal die Methode heißt bei mir collectable.StartMovingToPlayer(); So nun hat der Follower einen Rigidbody, damit die Items von seinem Trigger erfasst werden. Da diese Items alle von der abstracten Klasse "Collectable" erben, kann ich im Trigger prüfen, ob das Objekt ein Collectable ist und kann die benötigten Methoden des Items aufrufen. private List<Collectable> collectablesToCollect = new List<Collectable>(); // alle gefundenen Collectables private bool isCollecting = false; // sammelt der Follower aktuell schon ein Collectable ein? private float movementSpeed = 10; // Sammelgeschwindigkeit private void Update() { if (CollectablesInRange()) // Irgendwelche Collectables in Reichweite? { if (!isCollecting) // Aktuell noch nicht am Einsammeln? MoveToCollectable(); // Dann das Item einsammeln } } private void OnTriggerEnter(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) // ist das gefundene Objekt ein Collectable? { if (!collectable.GetMovementState()) // Ist das Item noch nicht "aktiviert"? collectablesToCollect.Add(collectable); // Dann der Liste zum Einsammeln hinzufügen } } private void OnTriggerExit(Collider col) { Collectable collectable = col.GetComponent<Collectable>(); if (collectable != null) collectablesToCollect.Remove(collectable); // Item aus der Liste entfernen } private void MoveToCollectable() { isCollecting = true; // Sammelprozess aktivieren Collectable collectable = collectablesToCollect.First(); // das erste Objekt der Liste nehmen Vector3 defaultPosition = transform.position; // Die Ursprungsposition des Followers CollectionMovement(transform.position, collectable.GetCollectablePosition()); // Follower zum Item bewegen collectable.StartMovingToPlayer(); // Item zum Spieler bewegen CollectionMovement(transform.position, defaultPosition); // Follower zurück bewegen collectablesToCollect.Remove(collectable); // eingesammeltes Collectable aus der Liste entfernen isCollecting = false; // Sammelprozess beenden if (CollectablesInRange()) // Noch ein weiteres Item in der Liste? MoveToCollectable(); // Weiter sammeln } private IEnumerator CollectionMovement(Vector3 startPos, Vector3 endPos) { transform.position = Vector3.MoveTowards(startPos, endPos, movementSpeed * Time.deltaTime); yield return null; } private bool CollectablesInRange() // Befinden sich irgendwelche Objekte in Reichweite / in der Liste? { return collectablesToCollect.Count > 0; } Bewege ich mich mit dem Follower zu einem Collectable, so bewegt sich dieses problemlos auf den Spieler zu und wird eingesammelt. Mein Follower bewegt sich aber nicht zum Collectable hin und wieder zurück. Ich gehe davon aus, dass ich die Routine Vector3.MoveTowards() so steuern muss, dass der restliche Code erst danach ausgeführt wird. Wie mache ich denn sowas am geschicktesten? Vielleicht gibt es auch Verbesserungsvorschläge für den Code?
  14. Garzec

    SPPRO Discord GameJam 2.0

    Hallo, da der erste Durchlauf so gut geklappt hat, jetzt ein zweites mal. Hier ein paar Daten zum GameJam Datum: 15.09. 20.00 Uhr bis 17.09. 20.00 Uhr Dauer: 48 Stunden Beginn: Freitag, 20.00 Uhr Ende: Sonntag, 20.00 Uhr Teilnehmeranzahl: unbegrenzt Teamgröße: unbegrenzt Technologien: frei wählbar Assets: frei wählbar Thema: Wird zu Beginn zufällig aus einer Themenliste ausgewählt Bewertung: Voting auf itch.io Support: Discord Server mit Text und Voice Channel pro Team Dieses mal ist die Dauer auf das ganze Wochenende verteilt, da ja manche eher Samstag / eher Sonntag Zeit haben. Sollte jemand Interesse haben, dieses mal mitzumachen, kann er mir gerne in Discord schreiben. Entweder im Discord dieses Forums oder an Garzec#2859
×
×
  • Neu erstellen...