(تصحيح)
أولاً ، دعنا نرى ما هو MVP (مقدم عرض النموذج).
لماذا هو مطلوب؟ أبسط إجابة هي بناء بنية مريحة وقابلة للتمديد.
يجدر بك معرفة سبب حاجتك إلى تقسيم التفاعل إلى ثلاث فئات مختلفة. أولاً ، الفصل بين الواجبات ، باتباع مبادئ سوليد. ثانيا ، لسهولة التفاعل مع الخوادم لمزامنة البيانات.
دعونا نلقي نظرة فاحصة على مسؤوليات المثال
PlayerView.cs - يمثل بشكل خاص فئة MonoBehaviour
using UnityEngine; public class PlayerView : MonoBehaviour { }
PlayerModel.cs - يمثل فئة البيانات
public class PlayerModel { }
Presenter.cs - يمثل فئة اتصال بين النموذج وطريقة العرض
public class PlayerPresenter { private PlayerView _playerView; private PlayerModel _playerModel public PlayerController(PlayerView view, PlayerModel model) { _playerView = view; _playerModel = model; } }
هذا هو النمط كله.
الآن دعونا نرى لماذا كل هذا مطلوب.
نضيف PlayerView.cs كمكون لمشغل Prefab لدينا.
يتم إنشاء الفئات المتبقية في بعض فئات التحكم. على سبيل المثال ، قم بإنشاء فئة تحكم.
قم بإنشاء كائن فارغ على المسرح وقم بتعليق مكون GameManager
GameManager.cs
public class GameManager : MonoBehaviour { public GameObject _playerPrefab; private PlayerPresenter _playerController; private PlayerModel _playerModel; public void Start(){ _playerModel = new PlayerModel(); var playerObject = Instantiate(_playerPrefab, Vector3.zero,Quaternion.identity); var playerView = playerObject.GetComponent<Playerview>(); _playerPresenter = new PlayerPresenter(playerView, _playermodel) } }
حسنًا ، الآن في بداية اللعبة ، سنقوم بإنشاء لاعب. لكن ماذا بعد؟
في الواقع ، هذا هو ميكانيكي الخيال. حسنًا ، على سبيل المثال ، دعنا نوسع نموذج المشغل بإضافة الصحة.
PlayerModel.cs
public class PlayerModel { public event Action Death; public event Action<float> ChangedHealth; private float _maxHp = 100; private float _currentHp; public PlayerModel(){ _currentHp = maxHp; } public void SetNewHealth(float damage) { _currentHp -= damage; if(_currentHp > 0) ChangedHealth?.Invoke(_currentHp); else Death?.Invoke(); } }
الآن لدينا لاعب لديه الصحة وحدثان لتغيير الصحة والموت. أي ، Model - يمثل تركيز جميع بيانات اللاعب ويقرر ما يجب فعله عند تغيير أي بيانات.
الآن قم بتوسيع Playercontroller حتى نتمكن من التفاعل مع البيانات
PlayerPresenter.cs
public class PlayerPresenter { private PlayerView _playerView; private PlayerModel _playerModel public PlayerPresenter(PlayerView view, PlayerModel model) { _playerView = view; _playerModel = model; } public void Enable() { _playerModel.Death += Death; _playerModel.ChangedHealth += ChangeHealth; } private void ChangeHealth(float health){ _playerView.Changehealth(health); } private void Death(){ _playerView.Death(); Disable(); } public void Disable() { _playerModel.Death -= Death; _playerModel.ChangedHealth -= ChangeHealth; } }
لذلك ، دعونا توسيع و PlayerView
PlayerView.cs
public class PlayerView : MonoBehaviour { public void Changehealth(float health) {
لذلك ، حصلنا على بنية ملائمة للغاية لإنشاء وحدة (أو أي كائن آخر) ، والتي يمكن توسيعها بواسطة أي ميكانيكا. تحتاج مانا؟ أو حركة؟ إضافة تعويم مانا ، موقف Vector3 إلى النموذج.
ما ينبغي أن يكون الاستنتاج؟ لا تتداخل مع عرض البيانات (MonoBehaviour) مع التقديرات الخاطئة البسيطة.
يوجد مقدم العرض في حالتنا أعلى مستوى PlayerView و PlayerModel ويرصد ما إذا كان هناك شيء ما يتغير هناك ويستجيب للتغيرات. في الوقت نفسه ، يمكن لـ PlayerController أيضًا مراقبة أحداث المشاهدة ، مثل التصادمات أو المشغلات.