- Moim zdaniem tego typu komentarze na początku pliku są złą praktyka:
//GameInput.cs
//Created by: <Name Surname>
Czemu? Pierwsza linia totalnie nic nie wnosi. Druga linia, też bardzo tak sobie.
Od sprawdzenia kto jest autorem kodu jest git blame
(nazywane czasem annotate albo history w różnych okienkowych gitach).
Czasem można się spotkać, że na początku pliku źródłowego umieszcza się notę licencyjną - i takie coś pewnie byłoby ok,
ale np. Github sugeruje, żeby dorzucić plik z licencją do repozytorium.
- Pliki mają pomieszane wcięcia ze spacjami. Łatwo to zaobserwować edytując je w czymś co domyślnie zamienia tabulator na 8 spacji, wtedy pliki przykładowo wyglądają tak:
namespace Arkanoid.Game
{
/// <summary>
/// GameInput is responsible for defining and updating game input.
/// </summary>
public class GameInput : MonoBehaviour
{
public GameInputButton Left = null;
Chyba całe summary powinno być na tym samym poziomie co public class ...
.
Pewnie warto przelecieć wszystkie pliki jakąś kombinacją klawiszy w VS która takie rzeczy poprawi.
public void Init()
iprotected void Update()
- czy napewno potrzebujemy specyfikować klasyfikatory dostępu? Może bez nich kod dalej będzie ok, ze względu na dziedziczenie (bo np. Update jest dziedziczone z MonoBehaviour). Przykładowo w dokumentacji nie piszą dostępu: https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html
To ofc bardzo dyskusyjna kwestia... pytanie czy jest sens pisać coś co i tak jest generowane. Bycie eksplicit zazwyczaj nie jest złe, ale może sprawić że kod będzie rozwlekły albo że będzie mniej czytelny.
- Nie jestem pewien czy:
/// <summary>
/// GameInput is responsible for defining and updating game input.
/// </summary>
to najlepszy możliwy opis. Warto zobaczyć jakie są konwencje pisania takich rzeczy w C# lub w projektach Unity. Być może czasem nie warto robić stringa dokumentacyjnego (bardzo dyskusyjna kwestia).
Może: /// Defines and updates game inputs.
- ale tak jak mówię, nie znam się na konwencjach Unity/C#.
- W
GameInput.Update
jest podwójneFire.UpdateState()
i brakujeEnter.UpdateState()
(oj, testy by to wykryły :P).
- Opis:
/// <summary>
/// BlockManager is responsible for reciving events from dispatcher and reacting for them (sending request to BlocksGenerator to create new level or load saved level),
/// counting blocks on map and dispatching event WIN_ROUND when last block on map is beated by ball.
/// It has accessor for BlocksPoolController.
/// </summary>
Uwagi:
- Typo
reciving
->receiving
react for them
- raczej -react to them
, ale tu nie jestem pewien.WIN_ROUND event
zamiastevent WIN_ROUND
- Gdy powtarzamy
on map
to powinno raczej byćon the map
. - Wydaje mi się, że powinno być
is hit by the ball
zamiastis beated by the ball
. Samobeated
jest złą odmianą. Kolejne odmiany słowabeat
tobeat beat beaten
. It has an accessor
zamiastIt has accessor
Być może lepiej to napisać w takiej formie:
Receives events from dispatcher and reacts to them by:
- sending request to BlocksGenerator to create new or load saved level
- counting bloks on map and dispatching WIN_ROUND event when last block on the map is hit by the ball
Nie jestem przekonany co do pisania o It has an accessor for BlocksPoolController.
- użytkownik - tu, inny programista - może znaleźć to dość szybko przeglądająć listę pól/metod/akcesorów danego obiektu w IDE.
-
Tak patrząc koncepcyjnie, to jest sens trzymać stan gracza z wyłącznie dwoma stanami
Reset
iRunning
? Nie patrzyłem na resztę kodu jeszcze, ale wydaje się to zbędne, jakby można było to zastąpić przezbool _gameRunning = false;
czy coś podobnego. -
Regiony w VS nie używało się w ten sposób:
#region nazwa
? Tbh nie podoba mi się to zakomentowanie i te myślniki/kreski. -
Heh,
[SerializeField]
jak widzę w Unity dalej jest dziwnie określane. Via dokumentacja:
You will almost never need this.
A w tutorialach do Unity i wszelkich forach używają tego do pokazywania zmiennych w inspektorze np. https://unity3d.com/learn/tutorials/topics/tips/show-private-variables-inspector.
Anyway, w takim razie być może warto więcej zmiennych tym uwzględnić, jak na przykład:
private int _blocksOnMap = 0;
private int _numberOfRows = 2;
private int _numberOfColumns = 18;
a przynajmniej trochę wydaje się, że może się to przydać jakiemuś programiście/designerowi/testerowi gry.
Powyższe skreśliłem, bo widzę, że dalej wykorzystywane jest DesignDataSettings
i tam są te opcje. Domyślam się, że ich edycja jest przyjemna.
Wydaje się to rozsądnym rozwiązaniem :).
- Podoba mi się to całe
OnValidate
, chociaż dziwne że wymaga to aż tyle kodu.
-
FireBallOnStartRound
orazBounceFromTheRocket
współdzielą tą samą logikę - może metoda pomocnicza, która zostanie zawołana? -
Dwie pierwsze linie
OnResetToNewRound
iOnPrepareNewGame
również; ale nie wiem czy bym to wyciągał do osobnej metody; chyyba tak. -
Gdzieś się też przewija taki kod, który być może warto wrzucić do jakiegoś
private void _resetPosition()
this.transform.position = _resetPosition.position;
_rigidbody.velocity = ConstantValues.VECTOR2_ZERO;
- english:
/// BlocksPoolController provides object pooling for NormalBlock prefabs which has BlockController.
has
->have a
Returns BlockController in disabled GameObject.
in disabled
->in a disabled
albo możefrom a disabled
Swoją drogą nei weim czy nie zamieniłbym nazw metod GetBlockFromPool
i ReturnBlockToPool
na jakieś Push~
i Pop~
.
Gives back to pool BlockController passed in argument and disabling it gameobject.
- może
Pushes given BlockController back to pool and so disables its gameobject