tdd in unity
TRANSCRIPT
![Page 1: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/1.jpg)
?
![Page 2: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/2.jpg)
int idSurface::Split( const idPlane &plane, const float epsilon, idSurface **front, idSurface **back, int *frontOnPlaneEdges = NULL, int *backOnPlaneEdges = NULL) const;
http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-source-code
![Page 3: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/3.jpg)
Software Craftsman Game Developer
Tests
Clarity
SOLID
Speed
No Crash
Memory
![Page 4: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/4.jpg)
![Page 5: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/5.jpg)
Test Driven UnityA Sane Approach
![Page 6: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/6.jpg)
Software Craftsman Game Developer
Tests
Clarity
SOLID
Speed
No Crash
Memory
![Page 7: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/7.jpg)
![Page 8: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/8.jpg)
![Page 9: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/9.jpg)
![Page 10: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/10.jpg)
![Page 11: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/11.jpg)
QuickTime™ and aH.264 decompressor
are needed to see this picture.
![Page 12: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/12.jpg)
Eskimo!
![Page 13: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/13.jpg)
QuickTime™ and aH.264 decompressor
are needed to see this picture.
![Page 14: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/14.jpg)
Meta-Fail
![Page 15: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/15.jpg)
Is It Fun?
![Page 16: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/16.jpg)
Cubicle Wars!
![Page 17: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/17.jpg)
UnityMakes your life easier when it’s not making it
harder
![Page 18: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/18.jpg)
Scripts
![Page 19: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/19.jpg)
![Page 20: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/20.jpg)
public class NewScript : MonoBehaviour {
// Use this for initializationvoid Start () {
}
// Update is called once per framevoid Update () {
}}
![Page 21: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/21.jpg)
![Page 22: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/22.jpg)
![Page 23: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/23.jpg)
void Awake() {stateMachine = new CubicleWarsStateMachine(
new HumanPlayer("Player1"),new HumanPlayer("Player2"));
![Page 24: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/24.jpg)
[Test]public void ItAllowsAddingAUnitToAPlayer(){
var unit = Substitute.For<Unit>();
stateMachine.AddUnitToPlayer("PlayerOne", unit);stateMachine.AddUnitToPlayer("PlayerTwo", unit);
playerOne.Received().AddUnit(unit);playerTwo.Received().AddUnit(unit);
}
![Page 25: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/25.jpg)
Updating the View
![Page 26: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/26.jpg)
Update the View
public void Attack(Unit unit){ if (CurrentState == State.Attacking){ unit.AttackWith(CurrentPlayer.Weapon());
![Page 27: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/27.jpg)
Shared Interfaces
![Page 28: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/28.jpg)
C# Eventspublic delegate void GameOverEvent(String winner);
...
public event GameOverEvent GameOver = delegate { };
...
private void AnnouncePlayerWins(){GameOver(CurrentPlayer.Name);}
![Page 29: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/29.jpg)
Wiring the Events
machine.GameOver += delegate(string winner) {winMessage.SendMessage("ShowWinner", String.Format("{0} wins!", winner));};
![Page 30: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/30.jpg)
![Page 31: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/31.jpg)
Health
![Page 32: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/32.jpg)
“MVC”
![Page 33: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/33.jpg)
Demo
![Page 34: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/34.jpg)
![Page 35: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/35.jpg)
What is in the Library
•Game Models (Units, Characters)
•State Machines
•Effects
•Anything that doesn’t depend on UnityEngine
![Page 36: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/36.jpg)
State Machine
Game State Machine
StateState EventEvent ActionAction DestinatioDestinationn
WaitingForSelection ClickWeapon TryToSelectUnit Selecting
Selecting AssignWeapon SwapWaitingUnit Attacking
Attacking ClickWeapon ResolveAttack ResolvingAttack
ResolvingAttack PlayerDead PlayerWins
ResolvingAttack NextTurn SwitchPlayers SwitchingPlayers
SwitchingPlayers SwitchedPlayers WaitingForSelection
![Page 37: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/37.jpg)
Effectspublic class SineWave
{
protected float Amplitude { get; set; }
protected float Frequency { get; set; }
protected float Offset { get; set; }
public SineWave(float amplitude, float frequency, float offset)
{
Amplitude = amplitude;
Frequency = frequency;
Offset = offset;
}
public float at(float time)
{
return (Amplitude * (float)Math.Sin(Frequency * time))
+ Offset;
}
}
![Page 38: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/38.jpg)
Effects[Test]public void ItReturnsANormalSinWaveOnTime(){
var sineWave = new SineWave(1, 1, 0);
Assert.AreEqual(0, sineWave.at(0));Assert.AreEqual(1, sineWave.at((float) Math.PI /
2.0f));}
![Page 39: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/39.jpg)
Game Unitspublic StandardUnit(ConflictResolver resolver, UnityObject unity){
Resolver = resolver;Health = unity.InitialHealth;UnitName = unity.Name;
}
public void AttackWith (Unit enemy){
Health -= enemy.AttackStrengthAgainst (this);Attacked();
}
![Page 40: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/40.jpg)
Live Code!
![Page 41: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/41.jpg)
Software Craftsman Game Developer
Tests
Clarity
SOLID
Speed
No Crash
Memory
![Page 42: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/42.jpg)
The Ultimate Test
![Page 43: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/43.jpg)
![Page 44: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/44.jpg)
ControllersComponents.Add (new UnitController(this, GameData.GlobalData.PlayerOneName, (UnitData) GameData.DataFor(GameData.GlobalData.PlayerOneName).Sales));
![Page 45: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/45.jpg)
Controllerspublic class UnitController : DrawableGameComponent, UnityObject{
protected String player;protected Model model;protected UnitData initialData;protected Unit unit;
public int InitialHealth {get {
return initialData.Health;}
}
public string Name {get {
return initialData.Name;}
}
public UnitController (Game game, String player, UnitData initialData) : base(game){
var warGame = game as Startup;this.player = player;this.initialData = initialData;
unit = new StandardUnit(GameData.Resolver, this);
warGame.MouseClick += (s, args) => CheckMouseClick(s, args as ClickEventArgs);}
![Page 46: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/46.jpg)
Viewpublic UnitView (Game game, String player, Model model, UnitData initialData, Unit unit) : base(game){
this.model = model;this.unit = unit;this.initialData = initialData;this.player = player;wave = new SineWave(AMPLITUDE, FREQUENCY, OFFSET);waiting = false;
unit.Waiting += () => waiting = true;unit.DoneWaiting += () => waiting = false;
}
![Page 47: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/47.jpg)
The Ultimate Test #2
![Page 48: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/48.jpg)
Remember
•There’s no AssertPretty, and no AssertFun
•TDD needs to be fast to be effective
•Separate your concerns
•Slides with bullets suck
![Page 49: Tdd in unity](https://reader036.vdocuments.us/reader036/viewer/2022062307/55829734d8b42a94688b469f/html5/thumbnails/49.jpg)
Thanks!
@paytonruleswww.paytonrules.com
www.8thlight.comwww.github.com/paytonrules