VR נייד ללא בקרים — שיטת האינטראקציה היחידה היא כיוון המבט. זה נראה פשוט: מסתכלים על כפתור והוא נלחץ. בפועל, מבט שיושם בצורה גרועה מרגיז משתמשים מהר יותר מכל דפוס UI אחר. במהלך השנים פיתחנו מחסנית טכנולוגית וגישות שמבטיחות אינטראקציה נוחה. הניסיון שלנו: 5+ שנים בפיתוח VR נייד, מעל 20 פרויקטים עם ממשק מבט. אנו מציעים פתרון סוהר: מ-raycast ועד מחוון התקדמות. אנו מיישמים את המערכת הבסיסית תוך 3–5 ימים, מערכת מלאה תוך 1–2 שבועות. לפי התיעוד של Google Cardboard, אינטראקציה מבוססת מבט היא שיטת הקלט הסטנדרטית ל-VR נייד ללא בקרים.
איך עובד raycast ממרכז המבט?
המבט נקבע לפי כיוון התצוגה של המצלמה. ה-ray מוקרן ממיקום המצלמה קדימה לאורך Camera.main.transform.forward:
void FixedUpdate()
{
Ray gazeRay = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
if (Physics.Raycast(gazeRay, out RaycastHit hit, maxGazeDistance, interactableLayer))
{
var target = hit.collider.GetComponent<IGazeTarget>();
if (target != null)
{
HandleGazeHit(target, hit.point);
}
else
{
HandleGazeMiss();
}
}
else
{
HandleGazeMiss();
}
}void FixedUpdate() { Ray gazeRay = new Ray(Camera.main.transform.position, Camera.main.transform.forward); if (Physics.Raycast(gazeRay, out RaycastHit hit, maxGazeDistance, interactableLayer)) { var target = hit.collider.GetComponent<IGazeTarget>(); if (target != null) { HandleGazeHit(target, hit.point); } else { HandleGazeMiss(); } } else { HandleGazeMiss(); } } במקום FixedUpdate() — תדירות קריאה יציבה שאינה תלויה ב-FPS. במכשירים חלשים עם ירידות ל-30 FPS, Update() נותן תגובה לא אחידה. ה-Update() הוא חובה: raycasting על כל הסצנה הוא יקר, והמשתמש לא צריך להפעיל בטעות colliders בלתי נראים.
איך ליישם reticle (סמן מבט)?
Reticle הוא אינדיקטור חזותי לנקודת המבט. הוא ממוקם במרחב העולם על פני השטח של האובייקט שנמצא במבט. המרחק הוא דינמי: ה-reticle "נדבק" לנקודת הפגיעה.
void UpdateReticle(Vector3 hitPoint, Vector3 hitNormal)
{
reticleTransform.position = hitPoint + hitNormal * RETICLE_OFFSET;
reticleTransform.rotation = Quaternion.LookRotation(-hitNormal);
// Масштаб постоянный в угловых единицах (constant apparent size)
float dist = Vector3.Distance(Camera.main.transform.position, hitPoint);
reticleTransform.localScale = Vector3.one * dist * ANGULAR_SIZE;
}הערה: כאשר אין אובייקט במבט — reticle במרחק ברירת מחדל (3–5 מטרים). אנחנו לא מסתירים אותו: המשתמש צריך תמיד לראות לאן הוא מסתכל.
הפעלת Dwell ומחוון התקדמות
המשתמש מסתכל על אובייקט למשך N שניות — מתרחשת הפעלה. זמן dwell אופטימלי: 1.2–2.0 שניות. פחות משנייה אחת מוביל להפעלות מקריות בעת סריקת הסצנה, יותר משתי שניות מעייף. ההתקדמות חייבת להיות מורגשת. טבעת מתמלאת סביב ה-reticle היא הסטנדרט:
public class GazeDwellController : MonoBehaviour
{
[SerializeField] private float dwellTime = 1.5f;
[SerializeField] private Image progressRing;
private float dwellProgress = 0f;
private IGazeTarget currentTarget;
private bool isActivated = false;
public void OnGazeEnter(IGazeTarget target)
{
currentTarget = target;
dwellProgress = 0f;
isActivated = false;
progressRing.gameObject.SetActive(true);
}
public void OnGazeStay()
{
if (isActivated) return;
dwellProgress += Time.deltaTime / dwellTime;
progressRing.fillAmount = dwellProgress;
if (dwellProgress >= 1f)
{
isActivated = true;
currentTarget?.OnGazeActivate();
StartCoroutine(ResetAfterDelay(0.5f));
}
}
public void OnGazeExit()
{
currentTarget = null;
progressRing.gameObject.SetActive(false);
dwellProgress = 0f;
}
}לאחר ההפעלה — קירור קצר לפני ההפעלה הבאה של אותו אובייקט (0.5–1.0 שניות). אחרת המשתמש לא יכול להסיר את המבט בזמן והכפתור "נלחץ" פעמיים.
מצב Hover: משוב לפני הפעלה
הערה: כאשר המשתמש מסתכל על אובייקט אך dwell עדיין לא הושלם, יש צורך במשוב חזותי מיידי. האובייקט צריך להגיב ב-interactableLayer — לפני שזמן ההפעלה חולף. אפשרויות:
- הדגשה: שינוי צבע פליטת החומר
- קנה מידה: האובייקט גדל מעט (
void UpdateReticle(Vector3 hitPoint, Vector3 hitNormal) { reticleTransform.position = hitPoint + hitNormal * RETICLE_OFFSET; reticleTransform.rotation = Quaternion.LookRotation(-hitNormal); // Масштаб постоянный в угловых единицах (constant apparent size) float dist = Vector3.Distance(Camera.main.transform.position, hitPoint); reticleTransform.localScale = Vector3.one * dist * ANGULAR_SIZE; }מספיק) - אנימציה: אייקון מגיב למבט
- קול: לחיצה קצרה כאשר dwell מתחיל
ללא זה, המשתמש לא יודע אם היישום "רואה" אותו.
כפתור Cardboard כאישור
ל-Cardboard יש כפתור פיזי (טריגר מגנטי). אנו מוסיפים אותו כשיטת הפעלה חלופית במקום dwell — למשתמשים מתקדמים זה מהיר ונוח יותר:
// Cardboard SDK trigger event void Update() { if (CardboardInput.GetButtonDown()) { TriggerCurrentGazeTarget(); } } הכפתור אינו תחליף ל-dwell, אלא תוספת. לא כל מארזי Cardboard כוללים כפתור מגנטי תקין.
אילו שגיאות אופייניות מתרחשות עם אינטראקציית מבט?
Collider קטן מדי על אובייקט אינטראקטיבי — המשתמש "מפספס" את הכפתור. ה-collider צריך להיות גדול ב-10–20% מהאובייקט הנראה. מהירות המבט (מהירות זוויתית) משפיעה על הדיוק: במהלך סריקה מהירה, סף מהירות מאפס את dwell. Reticle רועד עקב גירוסקופ — Lerp עם זמן של 20 ms מבטל את הרעידות. השתמש בשכבה נפרדת ל-raycast כדי למנוע הפעלות מקריות ולחסוך בביצועים.
| שגיאה | פתרון |
|---|---|
| Collider קטן מדי | הגדל collider ב-10–20% יחסית לויזואלי |
| הפעלות מקריות | סף מהירות זוויתית של הראש בעת התחלת dwell |
| רעידות Reticle | Lerp למיקום reticle עם זמן ~20ms |
השוואת שיטות הפעלה
| פרמטר | הפעלת Dwell | כפתור Cardboard |
|---|---|---|
| זמינות בכל המכשירים | כן | לא (לא כולם עובדים) |
| עייפות | בינונית | נמוכה |
| דיוק | טוב | גבוה |
| כוונון זמן | כן (1.2–2.0 שניות) | לא |
מה כלול בעבודה
- תיעוד ארכיטקטורת מערכת המבט
- קוד מקור: raycast, reticle, בקר dwell, מצב hover
- אינטגרציה עם Cardboard SDK וטריגרים חלופיים
- בדיקות על מכשירים (iOS/Android) עם גרסאות Cardboard שונות
- תמיכה למשך שבועיים לאחר המסירה
תהליך העבודה
- ניתוח אלמנטים אינטראקטיביים: סוגי אובייקטים, תרחישי אינטראקציה.
- יישום מערכת raycast עם שכבות ו-colliders מתאימים.
- Reticle במרחב העולם עם גודל נראה קבוע.
- בקר dwell עם מחוון התקדמות, מצב hover, קירור.
- כפתור Cardboard כטריגר חלופי.
- בדיקת נוחות: זמן dwell, גדלי כפתורים, משוב.
הערכות זמנים
מערכת אינטראקציית מבט בסיסית עם reticle ו-dwell — 3–5 ימים. מערכת מלאה עם סוגים מרובים של אובייקטים אינטראקטיביים, אנימציות, קול ופרמטרים הניתנים להגדרה — 1–2 שבועות.
אנו מבטיחים אינטראקציה נוחה. מפתחי Unity ו-Android/iOS מוסמכים. צרו קשר כדי לדון בפרויקט שלכם — ניישם ממשק מבט עבור יישום ה-VR הנייד שלכם.







