2017-07-14 5 views
-2

私はC#の新しいプログラマーです(ショッカー、私は知っています)。Unityでの再現システムを試作しようとしましたが、統一Unityでプロトタイプをリロードしても弾薬と弾丸が正確に減少しない

問題は、リロードしても弾薬が正しく減少しないということです。私はそれを作ったので、まだ弾丸が残っている時にリロードすると、ショットから弾薬を減算するだけで、すでに1つ減算することを実装しなければならなかったのです(0120)。私はいくつかの問題(別のショッカー)に遭遇し、私の全体のプログラムがif文であることを見た。書き直しとリファクタリングの後、私はまだ問題と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

これを代わりに[コードレビューSE](https://codereview.stackexchange.com/)にすることをお勧めします。私が 'GetAudio()'で見たことの一つは、渡されたインデックスが常に使用されているインデックスより1高いことです。 'return audio [index-1];'は、ifブロックの* all *を1つのステートメントに畳ませるように動作します(ただし、範囲外を確認する必要があります)。 – Draco18s

+0

あなたはどのような問題を解決することができますか? –

答えて

0

はあなたがあまりにも多くのことをやろうとしているということです、あなたが関心を分離し、それを分割する必要がありますいくつかのクラスに分けられます。

あなたのコードでサウンドを再生するメソッドを含む新しいクラスのPlayerSoundsを作成しましたが、完全にリファクタリングするのは怠惰でしたので、コードのロジックは3つのクラスに分割する必要がありますが、 1つは撮影を管理し、もう1つはリロードを管理し、もう1つは弾薬と雑誌のために1つを管理します。また、私は完全に変更されたので、再ロードのロジックを完全に混同していました。あなたのニーズに合うようになります。

私がしたこと:ある程度マジックナンバーが削除され、それらは定数に変更されました。 NoAmmo、IsReloading、Shotsフィールドを削除しました。すべてのコメントを削除しました。どのメソッドやフィールドも自明でなければなりません。逆の負の条件 - 彼らは読みにくいです。

リロードのロジックも完全に変更されていますが、私はあなたが思ったように思っていました。if文は常に偽であるため、削除したので25と26を一定に変更しました。ショットの数に基づいて弾薬を差し引く必要がある時、あなたがしなければならないのは雑誌に記入するだけなので、私はそれを簡略化しました。必要に応じて変更してください。 コードを見ると、両方のリロード方法がほぼ同じで、1つにすることができ、if文が削除され、リロードした箇条書きの数に基づいてサウンドが再生されることがわかります。

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

いくつかのテストの後、私は音がうまく動作しなくなってしまっています...あなたの初期コードが私の最後にエラーを吐き出します。 "関数nameof-OperatorはC#4では使用できません。 – DeepQuantum

+0

申し訳ありませんが、nameofはC#6の機能です。フィールド/プロパティ/任意の文字列を名前に変更するだけで、nameof(audio)を "audio"に変更するだけで動作します。 – CrudaLilium

関連する問題