Saya mencoba untuk mendapatkan persegi panjang untuk bergerak di antara dua posisi yang saya sebut sebagai _positionA
dan _positionB
. Keduanya bertipe Vector3
. Persegi panjang bergerak dengan baik. Namun, ketika mencapai _positionB
itu tidak bergerak ke arah yang berlawanan, seperti seharusnya.
Saya kembali ke kode untuk melihatnya. Saya sampai pada kesimpulan bahwa ketika objek bergerak, if
pernyataan dalam kode melewatkan bingkai di mana posisi rects sama dengan _positionB
. Saya memutuskan untuk memodifikasi kode untuk membalikkan arah jika posisi rect lebih besar atau sama dengan _positionB
. Kode saya tidak terlalu panjang, jadi saya akan menampilkannya di bawah:
using UnityEngine;
using System.Collections;
public class Rectangle : MonoBehaviour
{
private Vector3 _positionA = new Vector3(-0.97f, -4.28f); //Start position
private Vector3 _positionB = new Vector3(11.87f, -4.28f); //End position
private Transform _rect_tfm;
private bool _atPosA = false, _atPosB = false;
public Vector2 speed = new Vector2(1f, 0f);
private void Start()
{
_rect_tfm = gameObject.GetComponent<Transform>();
_rect_tfm.position = _positionA;
_atPosA = true;
}
private void Update()
{
/*NOTE: Infinite loops can cause Unity to crash*/
Move();
}
private void Move()
{
if (_atPosA)
{
_rect_tfm.Translate(speed * Time.deltaTime);
if (_rect_tfm.position == _positionB)
{
_atPosA = false;
_atPosB = true;
}
}
if (_atPosB)
{
_rect_tfm.Translate(-speed * Time.deltaTime);
if (_rect_tfm.position == _positionA)
{
_atPosA = true;
_atPosB = false;
}
}
}
}
Namun ketika saya mengubahnya, itu memperingatkan saya akan pesan kesalahan berikut:
Operator> = tidak dapat diterapkan pada operan tipe Vector3 dan Vector3.
Ini membingungkan saya karena dua alasan; pertama, kedua nilai memiliki tipe data yang sama. Kedua, menggunakan operator perbandingan ( ==
) pada dua nilai berfungsi tanpa kesalahan. Mengapa saya tidak bisa menggunakan operator >=
dengan Vector3
s?
sumber
Bools
like_atPosA
dan_atPosB
. Tidak dapat dihindari, Anda akan membuat kesalahan dengan menyinkronkan keduanya, dan itu akan menyebabkan bug. Lebih baik membuat yangenum
berisi semua posisi (A, B, mungkin yang lain di masa depan), dan menggunakannya>=
artinya bagi seorangVector3
? Bandingkan komponen-bijaksana? Itu tidak akan menjadi pemesanan total. Pertimbangkan untuk menggunakanVector3.MoveTowards
var vec1 = new Vector3(1, 0, 0)
danvar vec2 = new Vector3(0, 1 ,0)
. Apakah inivec1 >= vec2
benar atau salah?Jawaban:
Untuk menyederhanakan jawaban,
Vector3
adalah kebiasaan yangstruct
disediakan olehUnityEngine
namespace. Saat kita membuat customclass
ataustruct
tipe, kita juga harus mendefinisikan operatornya . Dengan demikian, tidak ada logika default untuk>=
operator. Seperti yang ditunjukkan oleh Evgeny Vasilyev ,_rect_tfm.position == _positionB
masuk akal, karena kita dapat langsung memeriksaVector3.x
,Vector3.y
danVector3.z
nilai - nilai._rect_tfm.position >= _positionB
tidak masuk akal, karena fakta bahwa aVector3
diwakili oleh tiga nilai yang terpisah.Kita bisa membebani
Vector3
kelas untuk memuat operator yang sesuai secara teori , tapi itu agak rumit. Sebaliknya, akan lebih mudah untuk hanya memperpanjang denganVector3
kelas dengan sesuai metode . Yang sedang berkata, tampaknya Anda bermaksud menggunakan logika ini untuk gerakan. Dengan demikian, Anda mungkin merasa lebih mudah menggunakanVector3.Lerp
metode ini; jika demikian, baca lebih lanjut di bawah ini.Menambahkan metode ekstensi ke
Vector3
Seperti disebutkan sebelumnya, menerapkan
<=
atau>=
keVector3
sering tidak masuk akal. Untuk gerakan, Anda mungkin ingin membaca lebih lanjut untukVector3.Lerp
metode ini. Yang mengatakan, Anda mungkin ingin menerapkan<=
=>
aritmatika karena alasan lain, jadi saya akan memberi Anda alternatif yang mudah.Alih-alih menerapkan logika
Vector3 <= Vector3
atauVector3 >= Vector3
, saya mengusulkan memperluasVector3
kelas untuk memasukkan metode untukisGreaterOrEqual(Vector3 other)
danisLesserOrEqual(Vector3)
. Kami dapat menambahkan metode ekstensi kestruct
atauclass
dengan mendeklarasikannya distatic
kelas yang tidak diwariskan. Kami juga memasukkan targetclass
ataustruct
sebagai parameter pertama, menggunakanthis
kata kunci. Perhatikan bahwa dalam contoh saya, saya berasumsi bahwa Anda bermaksud memastikan bahwa ketiga nilai utama (x
,y
danz
) semuanya lebih besar atau sama, atau lebih rendah atau sama, masing-masing. Anda dapat memberikan logika Anda sendiri, di sini, sesuai kebutuhan Anda.Ketika kita mencoba memanggil metode ini dari
Vector3
kelas,local
akan mewakiliVector3
contoh dari mana kita memanggil metode tersebut. Anda akan mencatat bahwa metodenya adalahstatic
; metode penyuluhan harus menjadistatic
, tetapi Anda masih harus memanggil mereka dari sebuah contoh. Dengan adanya metode ekstensi di atas, Anda sekarang dapat menerapkannya langsung keVector3
jenis Anda .Pindah
Vector3
denganVector3.Lerp
Memanggil para
Vector3.Lerp
metode memungkinkan kita untuk menentukan posisi yang tepat antara duaVector3
nilai pada waktu tertentu. Manfaat tambahan dari metode ini adalah bahwa yangVector3
tidak akan overshoot target .Vector3.Lerp
membutuhkan tiga parameter; posisi awal, posisi akhir, dan posisi saat ini direpresentasikan sebagai nilai antara 0 dan 1. Ini menampilkan posisi yang dihasilkan sebagai aVector3
, yang dapat langsung kita atur sebagai posisi saat ini.Memecahkan masalah Anda, saya usulkan menggunakan
Vector3.Lerp
pindah ke atargetPosition
. Setelah memanggilMove
metode di masing-masingUpdate
, kita dapat memeriksa apakah kita telah mencapai target tersebut; tidakLerp.Vector3
akan melampaui, jadi menjadi dapat diandalkan. Kita sekarang dapat memeriksa posisi, dan mengubah ke atau untuk membalikkan gerakan.transform.position == targetPosition
targetPosition
leftPosition
rightPosition
Anda dapat melihat ini ditunjukkan dalam animasi berikut. Saya menerjemahkan cube biru
Vector3.LerpUnclamped
, yang memberi kami hasil yang mirip dengan terjemahan sederhana yang tidak dicentang. Saya menerjemahkan kubus merah menggunakanVector3.Lerp
. Bila tidak dicentang, kubus biru bergerak ke arah terlupakan; sementara kubus merah berhenti tepat di tempat saya bermaksud. Anda dapat membaca lebih lanjut tentang jenis gerakan ini di dokumentasi Stack Overflow .sumber
Mendefinisikan
>=
suatuVector3
tipe tidak masuk akal. Apa yang menentukan jika satu vektor lebih besar dari yang lain? Besarnya atau masing-masing komponen x, y, z mereka?Vektor adalah besar & arah. Jadi apa yang menentukan arah mana yang lebih besar?
Jika Anda perlu membandingkan besaran yang dapat Anda gunakan
sqrMagnitude
.Dalam hal ini
Vector3
mengganti==
untuk hanya membandingkan komponen yang berbeda untuk melihat apakah mereka sama. (dalam ambang batas)Ini adalah alasan yang sama mengalikan dua vektor menggunakan
*
tidak mungkin. Tidak ada cara matematis untuk melakukannya. Beberapa orang menggunakan*
untuk produk titik, tetapi itu adalah desain API yang tidak jelas.sumber
Vector3
astruct
, jadi paragraf tentang perbandingan referensi kurang tepat.Ini adalah pertanyaan lama tetapi untuk memasukkan ke dalam istilah yang kurang teknis, Vector3 adalah "wadah" untuk 3 nilai float - x, y, z.
Anda dapat membandingkan nilai individual, seperti membandingkan nilai x dari dua Vector3s, karena mereka hanya angka.
Namun, seluruh Vector3 tidak dapat dibandingkan dengan Vector3 lain karena tidak ada nilai tunggal yang dapat digunakan untuk membandingkan keduanya.
sumber
Hanya menambahkan apa yang diposting Gnemlock , tentang menambahkan metode ekstensi ke kelas Vector3. Ada masalah di Unity (dan saya yakin mesin game lainnya) saat menggunakan operator perbandingan tertentu (
==
,<=
dan>=
) antara dua nilai float, karena cara perhitungan titik mengambang ditangani.Mathf.Approximately
harus digunakan sebagai gantinya, sehingga metode ekstensi berikut dapat ditambahkan untuk memeriksa apakah dua vektor saling> = atau <=:sumber
Saya ingin mengusulkan cara berbeda untuk menafsirkan pertanyaan ini. Pola kode seperti ini:
pada dasarnya mencoba menggunakan
>=
/<=
operator sebagai "telah sisi kiri mencapai atau melewati sisi kanan?" tes.Menggunakan
>=
/<=
berarti "mencapai atau melewati" masuk akal dalam arti satu dimensi, jika posisi saya hanyalah pelampung:Namun dalam ruang 3D kami tidak memiliki satu garis untuk diukur, untuk menentukan sisi mana yang "tinggi / jauh" dan sisi mana yang "rendah / dekat". Misalnya, kita bisa mencoba berpatroli di antara titik-titik
Jadi sekarang kita berharap
patrolStart <= myPosition <= patrolEnd
pada sumbu X, tetapipatrolEnd <= myPosition <= patrolStart
pada sumbu Z. Operator kami "mencapai atau melewati" berbeda dari satu sumbu ke yang lain, sehingga tidak ada lagi pemetaan yang jelas antara konsep kami melewati ambang batas dan pemeriksaan ketimpangan sederhana.Tapi, ada cara kita dapat memilih hanya satu baris dalam ruang 3D, dan menjadikan
>=
/<=
berperilaku seperti kotak pelampung tunggal di sepanjang garis yang kita pilih:Sebagai bonus, jika Anda menormalkan vektor sumbu sebelum menggunakannya, maka semua produk titik mewakili jarak, sehingga Anda dapat mengukur dengan tepat seberapa jauh Anda dari kedua ujungnya, di sepanjang sumbu perjalanan.
sumber