Arsitektur yang kompeten memainkan peran kunci dalam pengembangan produk perangkat lunak apa pun. Masalah kinerja, ekstensibilitas, atau pemahaman yang paling umum berakar pada ketidakhadirannya. Kurangnya struktur proyek yang didefinisikan secara ketat membuat pengembang kehilangan kemampuan untuk berpikir dalam abstraksi, memahami kode yang ditulis oleh kolega secara sekilas, dan memprediksi di mana kesalahan terjadi. Dan dalam beberapa kasus, seseorang dapat menjadi bingung bahkan dalam kodenya sendiri, terlalu jenuh dengan entitas dan komponen. Tetapi hampir setiap programmer cepat atau lambat, baik sendiri atau dengan bantuan buku yang cerdas, berkenalan dengan solusi yang baik terlepas dari konteksnya. Mereka sangat efektif dan serbaguna sehingga mereka menemukan tempat dalam memecahkan banyak masalah, dan ... Ya, saya tahu, Anda tidak dapat melanjutkan, semua orang sudah mengerti yang saya bicarakanpola desain. Beberapa berdoa untuk mereka, yang lain menemukan sepeda mereka di antara mereka. Beberapa orang mengklaim dalam wawancara bahwa mereka mempelajarinya di dalam dan luar dan terjebak dalam kesia-siaan total. Tapi setiap orang, dengan satu atau lain cara, mendengar tentang mereka. Hari ini kita akan berbicara tentang salah satu pola - "Negara" . Lebih tepatnya, tentang mesin negara hingga. Meskipun Anda termasuk yang terakhir dari grup yang tercantum di atas, Anda mungkin pernah menemukan alat berikut:
Animator dalam Unity dibangun di atas mesin negara. Setiap animasi dari sekelompok objek direpresentasikan sebagai status. Kondisi dan urutan transisi di antara keduanya ditentukan di animator, yang merupakan mesin status. Juga, topik penggunaan mesin keadaan hingga untuk mendeskripsikan logika kerja objek dengan perilaku kompleks telah berulang kali dimunculkan. Bot AI, kontrol karakter utama, itu saja.
. . , - , . , , , . , . , - :
. , , . , Play . - , . , isPaused, , .
, . , , , .
, , . , , , , , AI.
, . Play, WaitMatch "match_ready", , , "room_left" .
. , , , . , , "" .
. , . . . . , .
- . , . , .
, . :
FSM |
AState |
- public FSM(AState initState) - public void Signal(string name, object data = null) - private void ChangeState(AState newState) |
- void Enter() - void Exit() - AState Signal() |
, 2 :
. . , , . , . Exit
Enter
. , :
public class FSM
{
private AState currentState;
public FSM(AState initState) => ChangeState(initState);
private void ChangeState(AState newState)
{
if (newState == null) return;
currentState?.Exit();
currentState = newState;
currentState.Enter();
}
public void Signal(string name, object arg = null)
{
var result = currentState.Signal(name, arg);
ChangeState(result);
}
}
. , , .
public class AState
{
public virtual void Enter() => null;
public virtual void Exit() => null;
public virtual AState Signal(string name, object arg) => null;
}
public class SLoad : AState
{
public override void Enter()
{
Game.Data.Set("loader_visible",true);
var load = SceneManager.LoadSceneAsync("SceneGameplay");
load.completed+=a=>Game.Fsm.Signal("scene_loaded");
}
public override void Exit()
{
Game.Data.Set("loader_visible",false);
}
public override AState Signal(string name, object arg)
{
if (name == "scene_loaded")
return new SLobby();
return null;
}
}
, , . , , . 3 , . - , - . ! , , . , , ,
public class SMessage : AState
{
private string msgText;
private AState next;
public SMessage(string messageText, AState nextState)
{
msgText = messageText;
btnText = buttonText;
next = nextState;
}
public override void Enter()
{
Game.Data.Set("message_text", msgText);
Game.Data.Set("window_message_visible",true);
}
public override void Exit()
{
Game.Data.Set("window_message_visible",false);
}
public override AState Signal(string name, object arg)
{
if (name == "message_btn_ok")
return next;
return null;
}
}
, c , .
...
case "iap_ok":
return new SMessage("Item purchased! Going back to store.", new SStore());
...
Game.Data
, , , , "". , , UI, . , . , .
public class ButtonFSM : MonoBehaviour, IPointerClickHandler
{
public string key;
public override void OnPointerClick(PointerEventData eventData)
{
Game.Fsm.Signal(key);
}
}
Dengan kata lain, saat kami mengklik tombol (sebenarnya, ke CanvasRenderer mana pun), kami mengirimkan sinyal yang sesuai ke mesin. Saat bertransisi antar negara bagian, kami dapat mengaktifkan dan menonaktifkan Canvas yang berbeda dengan cara apa pun yang nyaman bagi kami, mengubah topeng yang digunakan Physics.Raycast
dan bahkan terkadang mengubah Time.timeScale! Betapapun mengerikan dan tidak beradabnya hal itu pada pandangan pertama, selama apa yang dilakukan di dalam Enter
dibatalkan Exit
, dijamin tidak akan menimbulkan ketidaknyamanan, jadi lanjutkanlah! Hal utama adalah jangan berlebihan.