Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
どこから始めるUnity Test
Search
いも
January 23, 2019
Programming
5
3.3k
どこから始めるUnity Test
Gotanda Unity #10 のLT資料です。
いも
January 23, 2019
Tweet
Share
More Decks by いも
See All by いも
UnityプログラミングバイブルR6号宣伝&Unity Logging小話
adarapata
0
380
Unityテスト活動のふりかえり
adarapata
1
500
Gather.townはいいぞ その後
adarapata
1
1.5k
Unityでの開発事例
adarapata
3
22k
どこのご家庭にもあるシーンマネージャーの話
adarapata
1
7.3k
Gather.townはいいぞ
adarapata
2
2.3k
宴はいいぞ
adarapata
0
1.3k
わかった気になるモブプログラミング
adarapata
1
84
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.2k
Other Decks in Programming
See All in Programming
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
130
OSSで起業してもうすぐ10年 / Open Source Conference 2024 Shimane
furukawayasuto
0
110
Click-free releases & the making of a CLI app
oheyadam
2
120
2024/11/8 関西Kaggler会 2024 #3 / Kaggle Kernel で Gemma 2 × vLLM を動かす。
kohecchi
5
930
CSC509 Lecture 11
javiergs
PRO
0
180
CSC509 Lecture 09
javiergs
PRO
0
140
ふかぼれ!CSSセレクターモジュール / Fukabore! CSS Selectors Module
petamoriken
0
150
as(型アサーション)を書く前にできること
marokanatani
10
2.7k
Amazon Qを使ってIaCを触ろう!
maruto
0
410
Jakarta EE meets AI
ivargrimstad
0
120
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
型付き API リクエストを実現するいくつかの手法とその選択 / Typed API Request
euxn23
8
2.2k
Featured
See All Featured
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Statistics for Hackers
jakevdp
796
220k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
47
2.1k
Faster Mobile Websites
deanohume
305
30k
GitHub's CSS Performance
jonrohan
1030
460k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
Imperfection Machines: The Place of Print at Facebook
scottboms
265
13k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
Building Better People: How to give real-time feedback that sticks.
wjessup
364
19k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
900
Transcript
Ͳ͔͜Β࢝ΊΔ Unity Test 2019/1/23 Gotanda Unity #10
͍Ͱ͢ • ͍(@adarapata) • https://adarapata.com • ϛΫγΟ XFLAG UnityΤϯδχΞ •
εϚϒϥੈքઓಆྗ53ສ
ࠓ͢͜ͱ • UnityͰ۩ମతʹͲ͏͍͏෩ʹςετॻ͖ਐΊ͍ͯͬͨΒ ͍͍ͷʁͱ͍͏ • ͏ͪͷήʔϜʹࠓ͔ΒೖΕΔͷͳ͊ɾɾΈ͍ͨʹ᪳ͬ ͍ͯΔਓΛޙԡ͢͠Δ • ςετ͋·Γॻ͍ͨ͜ͱͳ͍ਓ͚
ͳͥςετΛॻ͘ͷ͔ • ࣭ͷѲ/ਫ਼ਆతোนͷഉআ • աڈʹهࣄΛॻ͍ͨͷͰࢀর͍ͩ͘͞ɻ • ʮςετίʔυʹ͍ͭͯͷจॻΛॻ͍͍ͯͨʯhttp:// adarapata.hatenablog.com/entry/2018/08/16/001607
UnityͰΑ͋͘Δίʔυʹରͯ͠ ϢχοτςετΛॻ͍ͯΈΔ • MonoBehaviorʹ৭ʑॻ͍ͯΔͭ • αϯϓϧͰ͋Γͦ͏ͳSTGͷࣗػ • খنͳϓϩμΫτ ݁Λઌʹݴ͏ͱઈ͠ΜͲ͍
public class PlayerUnit : MonoBehaviour { [SerializeField] private Bullet _bulletPrefab
= null; [SerializeField] private float _interval; [SerializeField] private float _speed; [SerializeField] private int _hp; private float _reloadTime; void Update() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); transform.position += new Vector3(horizontal, vertical, 0F) * _speed * Time.deltaTime; if (Input.GetButton("Fire1") && _reloadTime < 0) { var bullet = Instantiate(_bulletPrefab, transform.position, Quaternion.identity); bullet.SetUp(Vector2.up); _reloadTime = _interval; } _reloadTime -= Time.deltaTime; } void OnTriggerEnter2D(Collider2D collider) { if (collider.tag == "Bullet") { _hp--; if (_hp <= 0) { Destroy(gameObject); } } } }
͍ͬͯͧ͘
PlayerUnitʹͬͯ΄͍͜͠ͱ Λࢥ͍ग़͢ • Ҡಈ͢Δ • Λൃࣹ͢Δ • μϝʔδΛड͚Δ
PlayerUnitʹͬͯ΄͍͜͠ͱ Λࢥ͍ग़͢ • Ҡಈ͢Δ // ࠓ͚ͩ͜͜ • Λൃࣹ͢Δ • μϝʔδΛड͚Δ
Ҡಈͷςετ • ೖྗ͕͋Δͱɺಈ͍ͯཉ͍͠ • ಈ͘ = transform.positionʹมԽ͕͋Δ
namespace Tests { public class PlayerUnitTest { [UnityTest] public IEnumrator
MoveTest() { var gameObject = new GameObject(); var playerUnit = gameObject.AddComponent<PlayerUnit>(); var beforePosition = playerUnit.transform.position; yield return null; Assert.AreNotEqual(beforePosition, playerUnit.transform.position); } } } ͜Μͳײ͡ʹॻ͚Δͱ͍͍ͳ
μϝͰ͢ • Position͕ಉҰ = ಈ͍͍ͯͳ͍ • άϦʔϯࢦͯ͠ؤுΔͧ
௨Βͳ͍ཧ༝Λߟ͑Δ public class PlayerUnit : MonoBehaviour { [SerializeField] private Bullet
_bulletPrefab = null; [SerializeField] private float _interval; [SerializeField] private float _speed; [SerializeField] private int _hp; private float _reloadTime; void Update() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); transform.position += new Vector3(horizontal, vertical, 0F) * _speed * Time.deltaTime; ~~~~ } } • _speedʹ͕ೖͬͯͳ͍ • ΩʔೖྗͰ͖ͯͳ͍ͷͰ࣮࣭0ϕΫτϧ SerializeFieldInputTest͔Βѻ͑ͳ͍
ςετ͍͢͠ͷͱ͠ʹ͍͘ͷΛ͢Δ • Unity APIʹґଘ͍ͯ͠ͳ͍Ϋϥε • Unity APIʹґଘ͍ͯ͠ΔΫϥε • RigidBody,Animator etc..
• MonoBehaviourΛܧঝͨ͠Ϋϥε • GUI෦ Unityଆʹۙͮ͘ʹͭΕͯςετͷқ্͕͍ͬͯ͘ ςετ͍͢͠ͷ ςετ͠ʹ͍͘ͷ
ςετ͍͢͠ํʹدͤΔ public class PlayerUnit : MonoBehaviour { [SerializeField] private Bullet
_bulletPrefab = null; [SerializeField] private float _interval; [SerializeField] private float _speed; [SerializeField] private int _hp; private float _reloadTime; void Update() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); transform.position += new Vector3(horizontal, vertical, 0F) * _speed * Time.deltaTime; ~~~~ } } • ܭࢉॲཧ͚ͩΓग़ͤςετॻ͚ͦ͏ • Inputʹґଘ͠ͳ͚Εςετ࣌ͷೖྗΛ༻ҙͰ͖ͦ͏ ॻ͖ͮΒ͍ͱ͜Ζॻ͔ͳ͍
public class PlayerUnitMove { private float _speed; public PlayerUnitMove(float speed)
{ _speed = speed; } public Vector3 CalculateVelocity(Vector3 direction) => direction.normalized * _speed; } namespace Tests { public class PlayerUnitMoveTest { [Test] public void CalculateVelocityTest() { var move = new PlayerUnitMove(3); Assert.AreEqual(new Vector3(0, 3F,0), move.CalculateVelocity(Vector3.up)); } } } ܭࢉॲཧ͚ͩΫϥεΛΓग़͢
public class PlayerUnit : MonoBehaviour { [SerializeField] private Bullet _bulletPrefab
= null; [SerializeField] private float _interval; [SerializeField] private int _hp; private float _reloadTime; private PlayerUnitMove _move; public void Initialize(PlayerUnitMove move) { _move = move; } void Update() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); var direction = new Vector3(horizontal, vertical, 0F); transform.position += move.CalculateVelocity(direction) * Time.deltaTime; ~~~~ } } Ҡಈܭࢉ෦Λࠩ͠ସ͑ ΦϒδΣΫτ֎෦͔ΒͤΔΑ͏ʹ͢Δ
InputґଘΛΊΔ public interface IPlayerUnitInput { Vector3 GetAxis(); } public class
IUnityInput : IPlayerUnitInput { public Vector3 GetAxis() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); return new Vector3(horizontal, vertical, 0); } } ೖྗ෦ΛΠϯλϑΣʔεʹͯ͠ɺPlayerUnitʹΩʔೖྗΛҙࣝͤ͞ͳ͍
InputґଘΛΊΔ ·ͨΦϒδΣΫτ֎෦͔ΒͤΔΑ͏ʹ͢Δ public class PlayerUnit : MonoBehaviour { [SerializeField] private
Bullet _bulletPrefab = null; [SerializeField] private float _interval; [SerializeField] private int _hp; private float _reloadTime; private PlayerUnitMove _move; private IPlayerUnitInput _input; public void Initialize(PlayerUnitMove move, IPlayerUnitInput input) { _move = move; _input = input; } void Update() { var direction = _input.GetAxis(); transform.position += move.CalculateVelocity(direction) * Time.deltaTime; ~~~~ } }
namespace Tests { public class PlayerUnitTest { class MockInput :
IPlayerUnitInput { private Vector3 _axis; public MockInput(Vector3 axis) { _axis = axis; } public Vector3 GetAxis() => _axis; } [UnityTest] public IEnumerator MoveTest() { var gameObject = new GameObject(); var playerUnit = gameObject.AddComponent<PlayerUnit>(); var mockInput = new MockInput(Vector3.up); playerUnit.Initialize(new PlayerUnitMove(1), mockInput); var beforePosition = playerUnit.transform.position; yield return null; Assert.AreNotEqual(beforePosition, playerUnit.transform.position); } } } ͪΐͬͱॻ͖ͯ͠ςετ࣮ߦ
✔
ςετͱ͍͏͔ ϦϑΝΫλϦϯά͡Όͳ͍ʁ
͍
MonoBehaviorͷςετ͠ΜͲ͍ • MonoBehaviorϕλॻ͖ςετ͠ʹ͍͘ • ϏδωεϩδοΫΛMonoBehaviorʹॻ͍͍ͯ͘ͱҾͬு ΒΕͯςετқ্͕͕Δ • ͭ·Γີ݁߹ • ີ݁߹Α͍ઃܭͱݴ͑ͳ͍
• ςετͷ͠ʹ͔͘͞ΒઃܭͷΛѲ͢Δ
Humble Object ύλʔϯ • ςετ͠ʹ͍͘ͷͱͦ͏Ͱͳ͍ ͷΛ໌֬ʹׂ͚ͯ͢Δύλ ʔϯ • GUIͷॲཧͷৄࡉςετ͠ʹ͍͘ ͕ɺGUIͷৼΔ͍ςετͰ͖Δ
• ӈͷίʔυɺͷੜ෦ͷς ετ͍͕͠ɺʮੜ͢Δͱ͍ ͏ৼΔ͍͕ߦΘΕ͔ͨʯ·Ͱ ςετͰ͖Δ • MonoBehaviorʹ༗ޮ͔͠Εͳ ͍ public class PlayerUnitPresenter { private IPlayerUnitView _view; public void Shot(Vector3 position) { _view.Shot(position); } } public interface IPlayerUnitView { void Shot(Vector3 position); } public class PlayerUnitView : MonoBehaviour, IPlayerUnitView { public void Shot(Vector3 position) { // ࡞ͬͨΓ͢Δ } }
ςετίʔυͷՁ • ಈ࡞֬ೝͱ͍͏ࢹ͚ͩͳΒɺҰճॻ͍ͯऴΘΓͷݸਓ ϓϩμΫτʹೖΕΔҙٛബ͍ • ࢹˍΤσΟλ࠶ੜͷ͕͍έʔεଟ͍ • લड़ͷ௨Γઃܭͷͷؾ͖ͮΛಘΒΕΔࣄଟ͍ • ؾ͖ͮະདྷͷ։ൃ࣌ؒॖ
ؾ͖ͮͷΉ͔͠ͳ͠ • UserData(Ծ໊)ͱ͍͏Ϣʔβͷ͋ΒΏΔσʔλΛอ࣋ͨ͠Γ ॲཧͰ͖Δେ͖ͳΫϥε͕͋ͬͨ • ͋·Γྑ͘ͳ͍ΑͶͱ͍͏ೝࣝͰ্ָ͕࣮͋ͬͨͳͷ Ͱͦͷ··ͩͬͨ • ςετॻ͖࢝Ίͨஈ֊ͰUserData͕བྷΉςετқ͕ߴ ͍͜ͱʹؾ͖ͮ࢝Ίͨ
• νʔϜͰʹͳΓɺUserDataͷϦϑΝΫλϦϯά͕༏ઌత ʹߦΘΕ·ͨ͠ͱ͞
·ͱΊ • MonoBehaviorϕλॻ͖Ͱςετॻ͚·͢ • ςετ͍͢͠ͷɺ͠ʹ͍͘ͷΛׂ͍ͯ͜͠͏ • ͷѲͱ͍͏ࢹͰςετॻ͍ͯΈΔͷ͍͍Α
͓ΘΓ