unity3d
Vector3
Szukaj…
Wprowadzenie
Vector3
reprezentuje współrzędną 3D i jest jedną ze struktur szkieletowych biblioteki UnityEngine
. Struktura Vector3
znajduje się najczęściej w komponencie Transform
większości obiektów gry, gdzie jest używana do utrzymywania pozycji i skalowania . Vector3
zapewnia dobrą funkcjonalność do wykonywania typowych operacji wektorowych. Możesz przeczytać więcej o strukturze Vector3
w Unity API.
Składnia
- public Vector3 ();
- public Vector3 (float x, float y);
- public Vector3 (float x, float y, float z);
- Vector3.Lerp (Vector3 startPosition, Vector3 targetPosition, float ruchFraction);
- Vector3.LerpUnclamped (Vector3 startPosition, Vector3 targetPosition, float ruchFraction);
- Vector3.MoveTowards (Vector3 startPosition, Vector3 targetPosition, odległość zmiennoprzecinkowa);
Wartości statyczne
Struktura Vector3
zawiera niektóre zmienne statyczne, które zapewniają często używane wartości Vector3
. Większość reprezentuje kierunek , ale nadal można ich twórczo wykorzystywać w celu zapewnienia dodatkowej funkcjonalności.
Vector3.zero
i Vector3.one
Vector3.zero
i Vector3.one
są zwykle używane w połączeniu ze znormalizowanym Vector3
; to znaczy Vector3
którym wartości x
, y
i z
mają wielkość 1. W związku z tym Vector3.zero
reprezentuje najniższą wartość, podczas gdy Vector3.one
reprezentuje największą wartość.
Vector3.zero
jest również powszechnie używany do ustawiania domyślnej pozycji przekształceń obiektów.
Następująca klasa używa Vector3.zero
i Vector3.one
do nadmuchiwania i Vector3.one
kuli.
using UnityEngine;
public class Inflater : MonoBehaviour
{
<summary>A sphere set up to inflate and deflate between two values.</summary>
public ScaleBetween sphere;
///<summary>On start, set the sphere GameObject up to inflate
/// and deflate to the corresponding values.</summary>
void Start()
{
// Vector3.zero = Vector3(0, 0, 0); Vector3.one = Vector3(1, 1, 1);
sphere.SetScale(Vector3.zero, Vector3.one);
}
}
Kierunki statyczne
Kierunki statyczne mogą być przydatne w wielu zastosowaniach, z kierunkiem wzdłuż dodatniego i ujemnego wszystkich trzech osi. Należy zauważyć, że Unity stosuje lewy układ współrzędnych, który ma wpływ na kierunek.
Następująca klasa używa statycznych kierunków Vector3
do przemieszczania obiektów wzdłuż trzech osi.
using UnityEngine;
public class StaticMover : MonoBehaviour
{
<summary>GameObjects set up to move back and forth between two directions.</summary>
public MoveBetween xMovement, yMovement, zMovement;
///<summary>On start, set each MoveBetween GameObject up to move
/// in the corresponding direction(s).</summary>
void Start()
{
// Vector3.left = Vector3(-1, 0, 0); Vector3.right = Vector3(1, 0, 0);
xMovement.SetDirections(Vector3.left, Vector3.right);
// Vector3.down = Vector3(0, -1, 0); Vector3.up = Vector3(0, 0, 1);
yMovement.SetDirections(Vector3.down, Vector3.up);
// Vector3.back = Vector3(0, 0, -1); Vector3.forward = Vector3(0, 0, 1);
zMovement.SetDirections(Vector3.back, Vector3.forward);
}
}
Indeks
Wartość | x | y | z | Równoważna new Vector3() |
---|---|---|---|---|
Vector3.zero | 0 | 0 | 0 | new Vector3(0, 0, 0) |
Vector3.one | 1 | 1 | 1 | new Vector3(1, 1, 1) |
Vector3.left | -1 | 0 | 0 | new Vector3(-1, 0, 0) |
Vector3.right | 1 | 0 | 0 | new Vector3(1, 0, 0) |
Vector3.down | 0 | -1 | 0 | new Vector3(0, -1, 0) |
Vector3.up | 0 | 1 | 0 | new Vector3(0, 1, 0) |
Vector3.back | 0 | 0 | -1 | new Vector3(0, 0, -1) |
Vector3.forward | 0 | 0 | 1 | new Vector3(0, 0, 1) |
Tworzenie wektora 3
Strukturę Vector3
można utworzyć na kilka sposobów. Vector3
jest strukturą i dlatego zwykle musi zostać utworzony przed użyciem.
Konstruktory
Istnieją trzy wbudowane konstruktory do tworzenia instancji Vector3
.
Konstruktor | Wynik |
---|---|
new Vector3() | Tworzy strukturę Vector3 o współrzędnych (0, 0, 0). |
new Vector3(float x, float y) | Tworzy Vector3 strukturę z podanych x i y współrzędnych. z zostanie ustawione na 0. |
new Vector3(float x, float y, float z) | Tworzy strukturę Vector3 z podanymi współrzędnymi x , y i z . |
Konwersja z Vector2
lub Vector4
Rzadko zdarza się, że trzeba traktować współrzędne struktury Vector2
lub Vector4
jak Vector3
. W takich przypadkach możesz po prostu przekazać Vector2
lub Vector4
bezpośrednio do Vector3
, bez uprzedniej jego instancji. Jak należy założyć, struktura Vector2
przekaże tylko wartości x
i y
, podczas gdy klasa Vector4
Vector2
swoje w
.
Widzimy bezpośrednią konwersję w poniższym skrypcie.
void VectorConversionTest()
{
Vector2 vector2 = new Vector2(50, 100);
Vector4 vector4 = new Vector4(50, 100, 200, 400);
Vector3 fromVector2 = vector2;
Vector3 fromVector4 = vector4;
Debug.Log("Vector2 conversion: " + fromVector2);
Debug.Log("Vector4 conversion: " + fromVector4);
}
Stosowanie ruchu
Struktura Vector3
zawiera pewne funkcje statyczne, które mogą zapewnić użyteczność, gdy chcemy zastosować ruch do Vector3
.
Lerp
i LerpUnclamped
Funkcje lerp zapewniają ruch między dwiema współrzędnymi w oparciu o podaną frakcję. Tam, gdzie Lerp
zezwala tylko na ruch między dwiema współrzędnymi, LerpUnclamped
dopuszcza ułamki, które poruszają się poza granicami między dwiema współrzędnymi.
Ułamek ruchu zapewniamy jako float
. Przy wartości 0.5
znajdujemy punkt środkowy między dwiema współrzędnymi Vector3
. Wartość 0
lub 1
zwróci pierwszy lub drugi Vector3
, odpowiednio, ponieważ wartości te albo korelują z brakiem ruchu (zwracając w ten sposób pierwszy Vector3
), albo zakończonym ruchem (co zwraca drugi Vector3
). Należy zauważyć, że żadna funkcja nie dostosuje się do zmiany frakcji ruchu. Jest to coś, co musimy ręcznie uwzględnić.
W przypadku Lerp
wszystkie wartości są z zakresu od 0
do 1
. Jest to przydatne, gdy chcemy zapewnić ruch w kierunku i nie chcemy przekraczać celu. LerpUnclamped
może przyjąć dowolną wartość i mogą być wykorzystane do zapewnienia ruchu z dala od miejsca przeznaczenia, lub obok miejsca przeznaczenia.
Poniższy skrypt używa Lerp
i LerpUnclamped
do przemieszczania obiektu w stałym tempie.
using UnityEngine;
public class Lerping : MonoBehaviour
{
/// <summary>The red box will use Lerp to move. We will link
/// this object in via the inspector.</summary>
public GameObject lerpObject;
/// <summary>The starting position for our red box.</summary>
public Vector3 lerpStart = new Vector3(0, 0, 0);
/// <summary>The end position for our red box.</summary>
public Vector3 lerpTarget = new Vector3(5, 0, 0);
/// <summary>The blue box will use LerpUnclamped to move. We will
/// link this object in via the inspector.</summary>
public GameObject lerpUnclampedObject;
/// <summary>The starting position for our blue box.</summary>
public Vector3 lerpUnclampedStart = new Vector3(0, 3, 0);
/// <summary>The end position for our blue box.</summary>
public Vector3 lerpUnclampedTarget = new Vector3(5, 3, 0);
/// <summary>The current fraction to increment our lerp functions by.</summary>
public float lerpFraction = 0;
private void Update()
{
// First, I increment the lerp fraction.
// delaTime * 0.25 should give me a value of +1 every second.
lerpFraction += (Time.deltaTime * 0.25f);
// Next, we apply the new lerp values to the target transform position.
lerpObject.transform.position
= Vector3.Lerp(lerpStart, lerpTarget, lerpFraction);
lerpUnclampedObject.transform.position
= Vector3.LerpUnclamped(lerpUnclampedStart, lerpUnclampedTarget, lerpFraction);
}
}
MoveTowards
MoveTowards
zachowuje się bardzo podobnie do Lerp
; podstawowa różnica polega na tym, że zapewniamy rzeczywistą odległość do przemieszczenia, zamiast ułamka między dwoma punktami. Ważne jest, aby pamiętać, że MoveTowards
nie przejdzie poza docelowy Vector3
.
Podobnie jak w przypadku LerpUnclamped
, możemy podać ujemną wartość odległości, aby oddalić się od docelowego Vector3
. W takich przypadkach nigdy nie przechodzimy obok docelowego Vector3
, a zatem ruch jest nieokreślony. W takich przypadkach możemy traktować docelowy Vector3
jako „przeciwny kierunek”; tak długo, jak Vector3
wskazuje w tym samym kierunku, względem początkowego Vector3
, ruch ujemny powinien zachowywać się normalnie.
Poniższy skrypt wykorzystuje MoveTowards
aby przesunąć grupę obiektów w kierunku zestawu pozycji przy użyciu wygładzonej odległości.
using UnityEngine;
public class MoveTowardsExample : MonoBehaviour
{
/// <summary>The red cube will move up, the blue cube will move down,
/// the green cube will move left and the yellow cube will move right.
/// These objects will be linked via the inspector.</summary>
public GameObject upCube, downCube, leftCube, rightCube;
/// <summary>The cubes should move at 1 unit per second.</summary>
float speed = 1f;
void Update()
{
// We determine our distance by applying a deltaTime scale to our speed.
float distance = speed * Time.deltaTime;
// The up cube will move upwards, until it reaches the
//position of (Vector3.up * 2), or (0, 2, 0).
upCube.transform.position
= Vector3.MoveTowards(upCube.transform.position, (Vector3.up * 2f), distance);
// The down cube will move downwards, as it enforces a negative distance..
downCube.transform.position
= Vector3.MoveTowards(downCube.transform.position, Vector3.up * 2f, -distance);
// The right cube will move to the right, indefinetly, as it is constantly updating
// its target position with a direction based off the current position.
rightCube.transform.position = Vector3.MoveTowards(rightCube.transform.position,
rightCube.transform.position + Vector3.right, distance);
// The left cube does not need to account for updating its target position,
// as it is moving away from the target position, and will never reach it.
leftCube.transform.position
= Vector3.MoveTowards(leftCube.transform.position, Vector3.right, -distance);
}
}
SmoothDamp
Pomyśl o SmoothDamp
jako o wariancie MoveTowards
z wbudowanym wygładzaniem. Według oficjalnej dokumentacji funkcja ta jest najczęściej używana do płynnego śledzenia kamery.
Wraz ze współrzędnymi początkowym i docelowym Vector3
, musimy również zapewnić Vector3
do reprezentowania prędkości, a liczba float
reprezentuje przybliżony czas potrzebny do ukończenia ruchu. W przeciwieństwie do poprzednich przykładów podajemy prędkość jako punkt odniesienia , który należy zwiększyć wewnętrznie. Ważne jest, aby wziąć to pod uwagę, ponieważ zmiana prędkości poza funkcją, gdy wciąż wykonujemy funkcję, może mieć niepożądane skutki.
Oprócz wymaganych zmiennych możemy również zapewnić float
reprezentujące maksymalną prędkość naszego obiektu oraz float
reprezentujące odstęp czasowy od poprzedniego wywołania SmoothDamp
do obiektu. Nie musimy podawać tych wartości; domyślnie nie będzie maksymalnej prędkości, a przerwa będzie interpretowana jako Time.deltaTime
. Co ważniejsze, jeśli wywołujesz funkcję jeden na obiekt w funkcji MonoBehaviour.Update()
, nie musisz deklarować przerwy czasowej.
using UnityEngine;
public class SmoothDampMovement : MonoBehaviour
{
/// <summary>The red cube will imitate the default SmoothDamp function.
/// The blue cube will move faster by manipulating the "time gap", while
/// the green cube will have an enforced maximum speed. Note that these
/// objects have been linked via the inspector.</summary>
public GameObject smoothObject, fastSmoothObject, cappedSmoothObject;
/// <summary>We must instantiate the velocities, externally, so they may
/// be manipulated from within the function. Note that by making these
/// vectors public, they will be automatically instantiated as Vector3.Zero
/// through the inspector. This also allows us to view the velocities,
/// from the inspector, to observe how they change.</summary>
public Vector3 regularVelocity, fastVelocity, cappedVelocity;
/// <summary>Each object should move 10 units along the X-axis.</summary>
Vector3 regularTarget = new Vector3(10f, 0f);
Vector3 fastTarget = new Vector3(10f, 1.5f);
Vector3 cappedTarget = new Vector3(10f, 3f);
/// <summary>We will give a target time of 5 seconds.</summary>
float targetTime = 5f;
void Update()
{
// The default SmoothDamp function will give us a general smooth movement.
smoothObject.transform.position = Vector3.SmoothDamp(smoothObject.transform.position,
regularTarget, ref regularVelocity, targetTime);
// Note that a "maxSpeed" outside of reasonable limitations should not have any
// effect, while providing a "deltaTime" of 0 tells the function that no time has
// passed since the last SmoothDamp call, resulting in no movement, the second time.
smoothObject.transform.position = Vector3.SmoothDamp(smoothObject.transform.position,
regularTarget, ref regularVelocity, targetTime, 10f, 0f);
// Note that "deltaTime" defaults to Time.deltaTime due to an assumption that this
// function will be called once per update function. We can call the function
// multiple times during an update function, but the function will assume that enough
// time has passed to continue the same approximate movement. As a result,
// this object should reach the target, quicker.
fastSmoothObject.transform.position = Vector3.SmoothDamp(
fastSmoothObject.transform.position, fastTarget, ref fastVelocity, targetTime);
fastSmoothObject.transform.position = Vector3.SmoothDamp(
fastSmoothObject.transform.position, fastTarget, ref fastVelocity, targetTime);
// Lastly, note that a "maxSpeed" becomes irrelevant, if the object does not
// realistically reach such speeds. Linear speed can be determined as
// (Distance / Time), but given the simple fact that we start and end slow, we can
// infer that speed will actually be higher, during the middle. As such, we can
// infer that a value of (Distance / Time) or (10/5) will affect the
// function. We will half the "maxSpeed", again, to make it more noticeable.
cappedSmoothObject.transform.position = Vector3.SmoothDamp(
cappedSmoothObject.transform.position,
cappedTarget, ref cappedVelocity, targetTime, 1f);
}
}