Ich erstelle ein tcg (Sammelkartenspiel) und würde gerne wissen, wie ich das Layout der Karten während des Spielens ändern kann. Ich meine, dass die Karten in einer Linie auf der Mitte des Bildschirms verteilt werden, sowohl vertikal als auch horizontal, auf einer Leinwand, und wenn ich eine Karte ziehe/verlasse, möchte ich, dass die Karten das Feld ausfüllen und sich im Spiel neu ausrichten. Wie kann ich das machen? irgendwelche Ideen? Ich dachte über eine Lösung nach, wenn du an der Reihe warst (Beginne von der Mitte des Bildschirms, dann schreite die Länge eines Schritts X zurück, die Anzahl der Karten/2 und spawne die Karten nacheinander), aber ich kann nicht herausfinden wie man die Ausrichtung von Karten ändert, wenn man eine von ihnen ablehnt, ohne sie alle wieder zu laden ... Image for exampleAusrichten eines Kartenarrays im Spiel
Antwort
Mit der gleichen Methode, die Sie für die Anfangsposition verwendet haben, sollten Sie in der Lage sein, die neue Position zu bekommen. Jetzt haben Sie zwei Positionen für jede Karte: oldPos
und newPos
.
Ihre Karten sind bereits instanziiert. Ihre Positionen sind in Transform.position
gespeichert. Ihr Ziel ist es, von oldPos
zu newPos
zu bewegen. Der einfachste Weg wäre:
myCard.transform.position = newPos;
Dies wird Ihre Karten sofort auf ihre neue Position verschieben. Es ist jedoch nicht üblich, Objekte zu teleportieren, da diese den Benutzern oft keine guten Gefühle vermitteln. Eine bessere Lösung besteht darin, das Objekt sanft von einer Position zu einer anderen zu bewegen.
Um dies zu tun, können Sie ein vorhandenes Objekt um transform.Translate(new Vector3());
verschieben, wobei Vector3
seine Bewegungsgeschwindigkeit entscheidet. Die Methode Translate()
macht position += movementDirection * movementAmount
, wie Sie es erwartet hätten.
Das Verschieben eines Objekts über Frames wird Animation
genannt. Es gibt Techniken für Animationen, um Bewegungen besser aussehen zu lassen (schneller aussehen als es ist oder natürlich aussehen). Eine übliche Methode aus der Mathematik nennt man lineare Interpolation oder lerp
. Mit lerp können Sie Zwischenpunkte zwischen zwei Endpositionen einfach berechnen, und es wird natürlich und schön aussehen, wenn Sie Ihre Objekte entlang der berechneten Punkte platzieren. Ich glaube, das ist es wonach Sie suchen.
========
Edit:
Hier ist ein Beispiel dafür, wie dies erreicht werden könnte. Beachten Sie, dass sich die Karte in diesem Beispiel um den gleichen Abstand pro Bild bewegt. Mit Hilfe von Lerp (Leichtigkeit, Leichtigkeit, usw.) können Sie diese Animation noch besser machen.
Ein weiterer Punkt, den ich möchte, dass Sie beachten, ist, dass ich if (Vector2.Distance(nextPosition, transform.position) < 10)
, nicht if(oldPosition.equals(newPosition))
mache. Der Grund ist, dass equals()
nicht sicher ist, floats
zu vergleichen, weil sie oft als 0.4999999
und 0.50001
anstelle von 0.5
und 0.5
gespeichert werden. Die beste Art, floats
zu überprüfen, besteht darin, zu testen, ob sie "Close Enough" sind.
Schließlich könnten Sie den folgenden Code verbessert verbessern könnte in VIELE DIFFERNET WEGE. Für instnace:
Destroy()
undInstantiate()
ist sehr langsam Operationen und Sie solltenObject Pooling
verwenden, weil Sie wissen, führen Sie diese Operationen ständig.- Die Bewegung von
Card
könnte durch bessere Animationstechnik wielerp
verbessert werden. - Es können auch andere Möglichkeiten, von
OnCardClick()
List<Card> Cards
- Speicherung verwendet
FindObjectOfType<CardSpawner>().OnCardDeleted(this)
und dies erfordertCard
CardSpawner
darüber wissen. Dies nennt manTight Coupling
, was als böse bekannt ist. Es gibt viele Diskussionen, die Sie finden können, warum das schlecht ist. Eine empfohlene Lösung wäre die Verwendung vonevent
(besserUnityEvent
in Unity3d).
CardSpawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CardSpawner : MonoBehaviour
{
[SerializeField] GameObject CardParent;
[SerializeField] GameObject CardPrefab;
Vector2 DefaultSpawnPosition = new Vector2(Screen.width/2f, Screen.height/10f);
List<Card> Cards = new List<Card>();
public void OnClickButton()
{
SpawnNewCard();
AssignNewPositions();
AnimateCards();
}
public void OnCardDeleted(Card removedCard)
{
Cards.Remove(removedCard);
AssignNewPositions();
AnimateCards();
}
void SpawnNewCard()
{
GameObject newCard = (GameObject)Instantiate(CardPrefab, DefaultSpawnPosition, new Quaternion(), CardParent.GetComponent<Transform>());
Cards.Add(newCard.GetComponent<Card>());
}
void AssignNewPositions()
{
int n = Cards.Count;
float widthPerCard = 100;
float widthEmptySpaceBetweenCards = widthPerCard * .2f;
float totalWidthAllCards = (widthPerCard * n) + (widthEmptySpaceBetweenCards * (n-1));
float halfWidthAllCards = totalWidthAllCards/2f;
float centreX = Screen.width/2f;
float leftX = centreX - halfWidthAllCards;
for (int i = 0; i < n; i++)
{
if (i == 0)
Cards[i].nextPosition = new Vector2(leftX + widthPerCard/2f, Screen.height/2f);
else
Cards[i].nextPosition = new Vector2(leftX + widthPerCard/2f + ((widthPerCard + widthEmptySpaceBetweenCards) * i), Screen.height/2f);
}
}
void AnimateCards()
{
foreach (Card card in Cards)
card.StartMoving();
}
}
Card.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Card : MonoBehaviour
{
public Vector2 oldPosition;
public Vector2 nextPosition;
bool IsMoving;
void Update()
{
if (IsMoving)
{
int steps = 10;
Vector2 delta = (nextPosition - oldPosition)/steps;
transform.Translate(delta);
if (Vector2.Distance(nextPosition, transform.position) < 10)
IsMoving = false;
}
}
public void StartMoving()
{
IsMoving = true;
oldPosition = transform.position;
}
public void OnCardClick()
{
UnityEngine.Object.Destroy(this.gameObject);
Debug.Log("AfterDestroy");
FindObjectOfType<CardSpawner>().OnCardDeleted(this);
}
}
- 1. Ausrichtung innerhalb eines (Link-) Tags im Listenelement vertikal ausrichten
- 2. Ausgabefehler im Hangman-Spiel
- 3. Kollisionserkennung im Cocos2d Spiel?
- 4. UnboundLocalError im textbasierten Spiel
- 5. Verwenden Akteure im Spiel
- 6. C# Highscore im Spiel
- 7. Vertikales Ausrichten eines Blockebenenelements innerhalb eines Blockebenenelements
- 8. Ausrichten eines LinearLayout innerhalb eines RelativeLayout programmgesteuert
- 9. Elemente im Layout richtig ausrichten
- 10. Ausrichten von Spalten im Rasterlayout
- 11. Komponenten im Raster ausrichten: MDL
- 12. Eingabeelemente im HTML-Dokument ausrichten
- 13. dynamische Tasten im Raster ausrichten
- 14. Ausrichtung eines Schalters in horizontaler Stapelansicht ausrichten
- 15. Verspottung im Spiel! und Scala
- 16. Sicherheit im Spiel 2.2.x
- 17. Android-Release im Spiel Markt
- 18. Authentifizierung im Spiel 2.3.x
- 19. Bootstrap glyphicons im Spiel Rahmen
- 20. Evolutionskripte im Spiel regenerieren 2
- 21. Statische Vermögenswerte im Spiel java
- 22. Stream Zukunft im Spiel 2.5
- 23. Veröffentlichung Spiel im App Store
- 24. Wie Daten eines Spiel speichern
- 25. richtige Weise zum Ausrichten eines verschachtelten div?
- 26. Richtiges Ausrichten eines ListView in reaktiven nativen
- 27. Ausrichten eines in UITextView eingebetteten Bildes
- 28. Formen innerhalb eines Bereichs auswählen und ausrichten
- 29. Ausrichten eines in css gedrehten Elements
- 30. Item zum Stack im Spiel Inventar hinzufügen
Ich muss sagen, dass ich ein wenig verwirrt haben, können Sie Ihre Antwort in Form von psudo Code refrase? Und was wird die Logik der Bewegung sein? Ich meine, sagen wir, ich verlasse eine Karte aus der Mitte, wie verwende ich diese Logik für jede Karte, um sie zum "Gravitationspunkt" in der Mitte des Bildschirms zu bewegen? –
Ich habe meine Antwort oben bearbeitet. Lass es mich wissen, wenn das funktioniert! – BrokenBacon