2017-07-14 135 views
-2

所以我是C#中的一名新程序員(我知道)我試圖在Unity中創建一個實時編碼系統的原型,但只是聲音和儀表在統一。Unity中的重裝原型不會正確減少子彈和子彈

問題是,當我重新加載它不會正確減少彈藥。因爲我這樣做是爲了在重新加載時仍然有子彈離開時,它只會從彈丸中減去彈藥,我已經必須實施,它將只減去一個如果(鏡頭== 0)

I while我遇到了一些問題(另一個令人震驚),並且看到我的整個程序只是if()語句。重寫和重構後,我仍然有我的問題,如果發言。我被告知不要發佈200行代碼並且具體。

我要發佈200行代碼,因爲我不知道更好。我很抱歉。

公共類射擊:MonoBehaviour {

//"CoolDown" is used to limit rate of fire of my gun 
public int CoolDown = 5; 

//used to prevent shooting while realoding 
public int ReloadCoolDown; 
public bool IsReloading = false; 

//obvious 
public int Shots = 0; 
public int TotalShots; 
public int Magazine = 25; 
public int Ammo = 125; 
public bool NoAmmo = false; 



void Start() 
{ 
    ReloadCoolDown = 150; 
} 

void Update() 
{ 
    //Checks if ammo is still present 
    CheckForAmmo(); 
    //just so i could test some stuff faster, can be ignored 
    Skip(); 
    //Also checks for ammo 
    if(!NoAmmo) 
    { 
     GameShot(); 
     ReloadEmpty(); 
     ReloadHalf(); 
     if (IsReloading == true) 
     { 
      ReloadCoolDown--; 
     } 
     if (CoolDown <= 0) 
     { 
      CoolDown = 0; 
     } 
     CoolDown--; 
    } 
    else if (NoAmmo) 
    { 
     ExecNoAmo(); 
    } 
} 

//Just getting the audio clips from unity 
AudioSource GetAudio(int index) 
{ 
    AudioSource[] audio = GetComponents<AudioSource>(); 
    if (index == 1) 
    { 
     return audio[0]; 
    } 
    else if (index == 2) 
    { 
     return audio[1]; 
    } 
    else if (index == 3) 
    { 
     return audio[2]; 
    } 
    else if (index == 4) 
    { 
     return audio[3]; 
    } 
    else 
     return null; 


} 

void GameShot() 
{ 
    //Shoots, increases total shots and shots (for that mag), plays audio, sets the cooldown for the next shot, decreases bullets in mag 
    if (Input.GetKey(KeyCode.Space) && 
     CoolDown <= 0 && IsReloading == false) 
    { 
     TotalShots++; 
     GetAudio(1).Play(); 
     CoolDown = 5; 
     Shots++; 
     Magazine--; 
    } 
} 

//Reloads if every bullet in the magazine has been fired 
void ReloadEmpty() 
{ 
    //this and ReloadHalf() is where you can find so many if statements and where most of my code is tangled up... 
    //im trying to check for ammo and if the mag is completely empty to trigger the empty reload 
    if (Magazine == 0 && Ammo > 0) 
    { 

     if(Ammo >= 25) 
     { 
      Magazine = 25; 
     } 
     else 
     { 
      Magazine = Ammo; 
     } 

     Ammo -= Shots; 
     Shots = 0; 
     ReloadCoolDown = 130; 
     GetAudio(2).Play(); 

     IsReloading = true; 
    } 
    if (ReloadCoolDown <= 0) 
    { 
     ReloadCoolDown = 150; 
     IsReloading = false; 
    } 
} 
void ReloadHalf() 
{ 
    //Again, many if statements and entaglement... 
    if ((Input.GetKeyDown(KeyCode.R) && Magazine < 26) && Ammo > 0) 
    { 
     if (Shots == 0) 
      Ammo -= 1; 
     ReloadCoolDown = 80; 
     GetAudio(3).Play(); 
     if(Ammo >= 25) 
     { 
      Magazine = 26; 
      Ammo -= Shots; 
     } 
     else if (Ammo <= 25) 
     { 
      Magazine += Ammo; 
      if(Magazine > 26) 
      { 
       int i = Magazine - 25; 
       Ammo = i; 
       Magazine = 26; 
      } 

     } 
     Shots = 0; 
     IsReloading = true; 
    } 
    if (ReloadCoolDown <= 0) 
    { 
     ReloadCoolDown = 100; 
     IsReloading = false; 
    } 
} 

void ExecNoAmo() 
{ 
    //plays no ammo sound if ammo == 0 
    if(Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.R)) 
     GetAudio(4).Play(); 

} 

void CheckForAmmo() 
{ 
    if (Ammo <= 0 && Magazine <= 0) 
     NoAmmo = true; 
} 

void Skip() 
{ 
    if (Input.GetKeyDown(KeyCode.Z)) 
    { 
     Ammo = 25; 
    } 
} 

}

+1

這裏沒有清楚的問題。你所說的只是你有問題。 – Kramb

+2

我建議將此改爲[Code Review SE](https://codereview.stackexchange.com/)。我在'GetAudio()'中看到的一件事是傳遞的索引總是比使用的索引高1。 'return audio [index-1];'會工作,將這些if塊中的所有*塊合併爲一個語句(儘管如此,仍然需要檢查是否出界)。 – Draco18s

+0

你希望我們能幫助解決什麼問題? –

回答

0

我試圖重構你的代碼,問題是,你試圖做太多的事情,你應該分開的關心和拆呢分成幾類。

我創建了一個新的類PlayerSounds,它包含播放代碼中的聲音的方法,但我懶得完全重構它,因此代碼的邏輯仍然在一個類中,儘管它應該分成3個類,一個管理射擊,一個管理重裝,一個管理彈藥和雜誌。另外,我對重新加載的邏輯完全感到困惑,所以我徹底改變了,它將取決於你的需求。

我做的事情:在一定程度上刪除了幻數,它們被改爲常量。刪除字段NoAmmo,IsReloading,Shots。刪除所有評論,任何方法和領域應該是自我解釋。逆轉的負面情況 - 他們很難閱讀。

我也徹底改變了重新加載的邏輯,我覺得你已經在過度使用它,一些if語句總是假的,所以我刪除了它們,我也把數字25和26改成了常量,我不明白爲什麼你需要根據Shots的數量減去彈藥,當你所要做的只是填充雜誌,所以我簡化了它。改變它以適應您的需要。 查看代碼後,您甚至可能會意識到兩種重新加載方法幾乎完全相同,可以合併爲一個,根據重新加載的子彈數量消除語句和播放聲音。

爲了避免ifs讓方法做你想做的事情,如果你的方法有太多的ifs,它可能做了很多事情,所以只需將它拆分並命名方法,這很容易理解什麼他們在。

class PlayerSounds 
    { 
     private const int PlayerShootingSound = 0; 
     private const int PlayerReloadingMagazineSound = 1; 
     private const int PlayerReloadingHalfOfMagazineSound = 2; 
     private const int PlayerHasNoAmmoSound = 3; 
     private AudioSource[] audio; 

     public PlayerSounds(AudioSource[] audio) 
     { 
      if (audio == null) 
       throw new ArgumentNullException(nameof(audio)); 

      this.audio = audio; 
     } 

     public void PlayerShot() 
     { 
      audio[PlayerShootingSound].Play(); 
     } 

     public void PlayerReloadingMagazine() 
     { 
      audio[PlayerReloadingMagazineSound].Play(); 
     } 

     public void PlayerRealodingHalfMagazine() 
     { 
      audio[PlayerReloadingHalfOfMagazineSound].Play(); 
     } 

     public void PlayerHasNoAmmo() 
     { 
      audio[PlayerHasNoAmmoSound].Play(); 
     } 
    } 

而且你的射擊類:

public class Shot : MonoBehaviour 
{ 
    private const int MagazineSize = 25; // to remove magic number 25 and 26, also to give this number a meaning 
    private PlayerSounds playerSounds; 

    public int CoolDown = 5; 
    public int ReloadCoolDown; 
    public int Shots = 0; 
    public int TotalShots; 
    public int Magazine = 25; 
    public int Ammo = 125; 

    void Start() 
    { 
     ReloadCoolDown = 150; 
     playerSounds = new PlayerSounds(GetComponents<AudioSource>()); 
    } 

    void Update() 
    { 
     if (playerTryingToFire()) 
     { 
      tryToShoot(); 
      playNoAmmoSoundWhenWithoutAmmo(); 
     } 
     else if (playerTryingToReload()) 
     { 
      tryToReloadHalfMagazine(); 
      playNoAmmoSoundWhenWithoutAmmo(); 
     } 

     tryToReloadEntireMagazine(); 

     if (CoolDown > 0) CoolDown--; 
     if (ReloadCoolDown > 0) ReloadCoolDown--; 
    } 

    bool playerTryingToFire() 
    { 
     return Input.GetKey(KeyCode.Space); 
    } 

    bool playerTryingToReload() 
    { 
     return Input.GetKeyDown(KeyCode.R); 
    } 

    void tryToShoot() 
    { 
     if (playerCanFire()) 
     { 
      TotalShots++; 
      playerSounds.PlayerShot(); 
      CoolDown = 5; 
      Magazine--; 
     } 
    } 

    bool playerCanFire() 
    { 
     return CoolDown == 0 && ReloadCoolDown == 0 && Magazine > 0; 
    } 

    void playNoAmmoSoundWhenWithoutAmmo() 
    { 
     if (!hasAmmo()) 
     { 
      playerSounds.PlayerHasNoAmmo(); 
     } 
    } 

    void tryToReloadHalfMagazine() 
    { 
     if (magazineIsNotFull() && hasAmmo()) 
     { 
      int missingBulletCountInMagazine = MagazineSize - Magazine; 
      transferAmmoToMagazine(missingBulletCountInMagazine); 
      ReloadCoolDown = 80; 
      playerSounds.PlayerRealodingHalfMagazine(); 
     } 
    } 

    private bool magazineIsNotFull() 
    { 
     return Magazine < MagazineSize; 
    } 

    void tryToReloadEntireMagazine() 
    { 
     if (Magazine == 0 && hasAmmo()) 
     { 
      transferAmmoToMagazine(MagazineSize); 
      ReloadCoolDown = 130; 
      playerSounds.PlayerReloadingMagazine(); 
     } 
    } 

    private void transferAmmoToMagazine(int maximumAmountToFitMagazine) 
    { 
     int possibleBulletCountToFit = Math.Min(Ammo, maximumAmountToFitMagazine); 
     Magazine += possibleBulletCountToFit; 
     Ammo -= possibleBulletCountToFit; 
    } 

    bool hasAmmo() 
    { 
     return Ammo > 0; 
    } 
} 
+0

這是我正在尋找的確切答案..我在代碼中糾結了很多,我自己也很困惑。非常感謝你。 – DeepQuantum

+0

好的,經過一些測試後,我無法使聲音工作......您的初始代碼在我的最後吐出了一個錯誤。 「在C#4中不能使用函數的名稱。」 – DeepQuantum

+0

對不起,nameof是C#6功能,它所做的只是將字段/屬性/任何內容的名稱更改爲字符串,因此只需將nameof(audio)更改爲「audio」即可。 – CrudaLilium