אירועי C# ב-Unity
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 10 מתוך 50.
כשהניקוד משתנה, כמה דברים מושפעים מכך: טקסט הניקוד, צליל, הישג. אם ScoreKeeper קורא לכל אחד מהם, הוא צריך שדה עבור כל אחד, וכל תכונה חדשה מחייבת לערוך אותו. אירוע הופך את הכיוון: ScoreKeeper מודיע על השינוי, ומי שזה חשוב לו נרשם כמנוי. את event ואת Action את/ה מכיר/ה מ-C#. ב-Unity המפרסם והמאזינים הם רכיבים, בדרך כלל באובייקטים שונים של GameObject:
using System;
using UnityEngine;
public class ScoreKeeper : MonoBehaviour
{
public event Action<int> OnScoreChanged;
private int score;
public void AddPoints(int points)
{
score += points;
OnScoreChanged?.Invoke(score);
}
}// ScoreLabel.cs, על הטקסט של ה-HUD
public ScoreKeeper keeper;
public TMP_Text label;
void Start()
{
keeper.OnScoreChanged += ShowScore;
}
void ShowScore(int score)
{
label.text = "Score: " + score;
}Action<int> פירושו שכל מאזין הוא מתודה שמקבלת int אחד, ובמקרה הזה את הניקוד החדש. Invoke קורא לכל המתודות שנרשמו כמנויות, לפי סדר ההרשמה. ללא מאזינים, האירוע הוא null, ולכן קריאה רגילה ל-OnScoreChanged(score) תגרום ל-NullReferenceException, ואילו ?. מדלג על הקריאה במקום זאת. מילת המפתח event מגבילה סקריפטים אחרים ל-+= ול--=: ב-ScoreLabel, keeper.OnScoreChanged(5) או keeper.OnScoreChanged = null לא יתקמפלו.
ל-ScoreKeeper אין שדה עבור התווית והוא לא יודע שהיא קיימת. מונה קומבו או נגן צלילים יכולים להירשם כמנויים באותה דרך, ו-ScoreKeeper נשאר כפי שהוא; סצנת בדיקה ללא HUD פועלת ללא שגיאות. מאזין מאתר את המפרסם באמצעות הפניה ב-Inspector, כמו כאן, או בכל דרך אחרת שמוכרת לך, כגון GetComponent או singleton. הסרת מאזין באמצעות -= חשובה ברגע שאובייקטים מושמדים, וזה הנושא של השיעור הבא.
אתגר
קלהשילוב של הלוחם גדל עם כל לחיצה על Space, וחוזר ל-0 לאחר comboWindow (שנייה אחת) ללא פגיעה. כרגע Fighter.cs קובע בעצמו את טקסט השילוב ואת גודל הלהבה, ולכן הוא זקוק לשדה עבור כל אחד מהם. שנה את הגישה באמצעות אירוע:
- ב-
Fighter.cs, הכרז על אירוע ציבורי בשםOnComboChangedשמעביר את השילוב (מספר שלם). הפעל אותו עם השילוב החדש בכל פעם שהשילוב משתנה, כולל האיפוס ל-0, וודא שפגיעה לא גורמת לשגיאה כשאף אחד לא מאזין. - מחק את השדות
comboTextו-flameשל Fighter ואת השורות שמשתמשות בהם: Fighter לא יודע דבר על ה-HUD. - ב-
ComboText.csוב-ComboFlame.cs, הירשם לאירוע של הלוחם עם המתודותShowו-GrowבתוךStart(). לשניהם יש שדהfighter, שמקושר בסצנה.
לחץ על Play, פגע בשק עם Space כמה פעמים, המתן שנייה, ואז לחץ על Check.
נסו בעצמכם
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class Fighter : MonoBehaviour
{
public float comboWindow = 1f;
public TMP_Text comboText;
public Transform flame;
private int combo;
private float sinceHit;
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
combo++;
sinceHit = 0f;
comboText.text = "Combo x" + combo;
flame.localScale = Vector3.one * (0.5f + 0.25f * combo);
}
else if (combo > 0)
{
sinceHit += Time.deltaTime;
if (sinceHit > comboWindow)
{
combo = 0;
comboText.text = "";
flame.localScale = Vector3.one * 0.5f;
}
}
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה ארכיטקטורת משחקים ב-Unity
1רכיבים, לא היררכיות
רכיבים קטניםסקריפט בסיס לאויברכיבים מופשטיםרכיבים שעובדים יחדסיכום: צריח מודולרי3אירועים
אירועי C# ב-Unityהירשם ב-OnEnableשדות UnityEventאירועים מניעים את ממשק המשתמשסיכום: חלונית הישג