Skip to content

Commit b200605

Browse files
committed
Merge branch 'master' of github.com:sachPico/top-down
2 parents 5bc1cda + 296a318 commit b200605

36 files changed

+1866
-14
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,7 @@ crashlytics-build.properties
6868

6969
# Temporary auto-generated Android Assets
7070
/[Aa]ssets/[Ss]treamingAssets/aa.meta
71-
/[Aa]ssets/[Ss]treamingAssets/aa/*
71+
/[Aa]ssets/[Ss]treamingAssets/aa/*
72+
ProjectSettings/ProjectVersion.txt
73+
ProjectSettings/ProjectVersion.txt
74+
ProjectSettings/ProjectVersion.txt

.vscode/settings.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"files.exclude":
3+
{
4+
"**/.DS_Store":true,
5+
"**/.git":true,
6+
"**/.gitignore":true,
7+
"**/.gitmodules":true,
8+
"**/*.booproj":true,
9+
"**/*.pidb":true,
10+
"**/*.suo":true,
11+
"**/*.user":true,
12+
"**/*.userprefs":true,
13+
"**/*.unityproj":true,
14+
"**/*.dll":true,
15+
"**/*.exe":true,
16+
"**/*.pdf":true,
17+
"**/*.mid":true,
18+
"**/*.midi":true,
19+
"**/*.wav":true,
20+
"**/*.gif":true,
21+
"**/*.ico":true,
22+
"**/*.jpg":true,
23+
"**/*.jpeg":true,
24+
"**/*.png":true,
25+
"**/*.psd":true,
26+
"**/*.tga":true,
27+
"**/*.tif":true,
28+
"**/*.tiff":true,
29+
"**/*.3ds":true,
30+
"**/*.3DS":true,
31+
"**/*.fbx":true,
32+
"**/*.FBX":true,
33+
"**/*.lxo":true,
34+
"**/*.LXO":true,
35+
"**/*.ma":true,
36+
"**/*.MA":true,
37+
"**/*.obj":true,
38+
"**/*.OBJ":true,
39+
"**/*.asset":true,
40+
"**/*.cubemap":true,
41+
"**/*.flare":true,
42+
"**/*.mat":true,
43+
"**/*.meta":true,
44+
"**/*.prefab":true,
45+
"**/*.unity":true,
46+
"build/":true,
47+
"Build/":true,
48+
"Library/":true,
49+
"library/":true,
50+
"obj/":true,
51+
"Obj/":true,
52+
"ProjectSettings/":true,
53+
"temp/":true,
54+
"Temp/":true
55+
}
56+
}
Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,127 @@
11
# Gerakan dan Animasi
22

3-
TBA
3+
Bab ini akan menjelaskan beberapa hal berikut:
4+
5+
1. Menggerakkan Objek
6+
2. Mengatur Animasi _Sprite_
7+
3. Mengubah _Sprite_ Objek _Player_ Berdasarkan Posisi _Mouse_
8+
9+
## Menggerakkan Objek
10+
Buat _script_ C# baru (misal kita beri nama _MovementInput.cs_), kemudian buka _script_ yang sudah dibuat pada _text editor_ atau _IDE yang telah ter-_install_ di komputer Anda. Tambahkan kedua _variabel_ berikut di dalam _class MovementInput_
11+
12+
```C#
13+
public float speed = 5f;
14+
```
15+
16+
Seluruh _public variable_ yang Anda masukkan dalam semua jenis _class_ secara otomatis akan tampil di tampilan _Inspector_ objek _Unity_ dan variabel tersebut dapat diubah nilainya dan disimpan perubahannya secara otomatis pada _Edit Mode_.
17+
18+
Supaya kita mampu menggerakkan objek sesuai dengan input yang diberikan pada _keyboard, maka kita harus tahu tombol mana saja yang ditekan. _Unity_ telah memudahkan kita untuk melakukan hal tersebut melalui sebuah _interface_ pada _class Input_ yang mengurus segala hal yang berkaitan dengan perangkat input. Tak hanya itu, _Unity_ juga menentukan fungsi masing-masing dari setiap tombol pada perangkat input, dalam kasus ini, kita mampu mendapatkan informasi input yang berkaitan dengan gerakan objek menggunakan fungsi _Input.GetAxisRaw()_. Pada fungsi _Update()_, tambahkan kode berikut:
19+
20+
```C#
21+
void Update()
22+
{
23+
float inputX = Input.GetAxisRaw("Horizontal");
24+
float inputY = Input.GetAxisRaw("Vertical");
25+
26+
Vector3 movement = new Vector3(inputX, inputY, 0);
27+
28+
transform.Translate(movement * speed * Time.deltaTime);
29+
}
30+
```
31+
32+
Fungsi _GetAxisRaw_ membutuhkan sebuah parameter input berupa _keyword_ untuk mendapatkan jenis input apa yang ingin didapatkan. Daftar _Keyword_ dapat kita lihat pada konfigurasi input _Unity_ melalui _Edit > Project Settings > Input Manager_
33+
34+
![Konfigurasi _Input Manager_](Assets/2-Gerakan-dan-Animasi/img/input-manager.PNG)
35+
36+
Fungsi _GetAxisRaw_ akan menghasilkan nilai antara -1, 0, dan 1 tergantung dari tombol yang ditekan; apabila tombol diatur sebagai _negative button_, nilai yang dihasilkan adalah -1. Sebaliknya, apabila diatur sebagai _positive button_, nilai yang dihasilkan adalah 1. Apabila tidak ada tombol yang ditekan, nilai yang dihasilkan adalah 0.
37+
38+
Variable _inputX_ dan _inputY_ digunakan untuk menampung informasi input dari fungsi _Input.GetAxisRaw()_. Informasi input dari kedua variabel akan digabung menjadi satu variabel bertipe _Vector3_, yaitu sebuah _class_ yang mendefinisikan sebuah vektor dalam dimensi tiga. Objek akan digeser melalui fungsi _Translate()_ dengan variabel _Vector3_ sebagai input dan besar perpindahan objek. Terlihat pada contoh bahwa _movement_ selain dikalikan dengan _speed_ juga dikalikan dengan _Time.deltaTime_. Hal ini dilakukan agar simulasi perpindahan objek per detik dapat berjalan dengan benar, sebaliknya perpindahan objek akan terlihat semakin cepat.
39+
40+
Mari kita uji coba program yang telah kita tulis dengan menjalankan mode _Game mode_. Anda akan mendapati pergerakan diagonal objek yang terlihat lebih cepat dibanding pergerakan vertikal maupun horizontal. Hal ini terjadi karena perbedaan panjang vektor pada variabel _movement_. Untuk mengatasi masalah tersebut, kita perlu menormalisasi variabel _movement_ agar panjang vektornya bernilai 1.
41+
42+
<!--Tambahin gambar masalah normalisasi vektor-->
43+
44+
```C#
45+
void Update()
46+
{
47+
float inputX = Input.GetAxisRaw("Horizontal");
48+
float inputY = Input.GetAxisRaw("Vertical");
49+
50+
//Mengambil nilai variabel vektor unit dari variabel Vector3 yang baru dibuat
51+
Vector3 movement = new Vector3(inputX, inputY, 0).normalized;
52+
```
53+
54+
## Mengatur Animasi _Sprite_
55+
_Unity_ menyediakan dua _interface_ untuk mengatur animasi; _Animation_ dan _Animator Controller_. _Animation_ adalah objek yang menyimpan tindakan apa saja yang harus dilakukan selama satu animasi berjalan, sedangkan _Animator Controller_ adalah objek yang mengatur alur berjalannya kumpulan _Animation_. Kali ini kita akan mencoba mengubah _sprite_ (gambar yang ditampilkan untuk sebuah objek) melalui kedua _interface_ tersebut.
56+
57+
Pertama, kita atur _spritesheet_ yang berada pada folder _2-Gerakan-dan-Animasi > Sprites > Drone >_ untuk membagi kumpulan gambar pada _spritesheet_ menjadi gambar-gambar individu. Pilih gambar _player256.png_, kemudian perhatikan panel _Inspector_. Atur _spritesheet_ sesuai dengan pengaturan pada gambar berikut. Setelah itu, pilih "_Sprite Editor_".
58+
59+
![Konfigurasi _Sprites_](Assets/2-Gerakan-dan-Animasi/img/config-sprites.PNG)
60+
61+
Pada _Sprite Editor_, pilih menu _Slice_, kemudian pada opsi _Type_, pilih _Grid By Cell Count_. Isikan kotak _C_ saja dengan nilai 8. Tekan _Slice_ dan simpan perubahan dengan menekan tombol _Apply_. _Spritesheet_ yang telah kita atur siap dipakai untuk dimasukkan ke objek _Animation_.
62+
63+
![Membagi _Spritesheet_](Assets/2-Gerakan-dan-Animasi/img/slice-spritesheet.png)
64+
![_Spritesheet_ yang sudah terbagi](/img/sliced-spritesheet.PNG)
65+
66+
Untuk menambahkan potongan _spritesheet_ ke dalam _Animation_, kita perlu menambahkan _component Animator Controller_ terlebih dahulu ke objek _player_. _Component Animator Controller_ ini perlu sebuah objek _Animator Controller_ yang bisa kita buat pada panel _Project_ dengan meng-klik kanan _window Project_, kemudian pilih _Create > Animator Controller_. Kemudian kita buat objek _Animation_ dengan meng-klik kanan pada _window Project_, pilih _Create > Animation_. Untuk bab ini kita buat empat objek _Animation_ dengan nama _Up_, _Down_, _Right_, dan _Left_. _Double-click_ objek _Animator Controller_ yang baru saja dibuat, kemudian _drag_ semua objek _Animation_ yang telah dibuat ke _window Animator Controller_ yang telah muncul.
67+
68+
![Isi _Window Animator Controller](Assets/2-Gerakan-dan-Animasi/img/animator-controller.PNG)
69+
70+
Buka _window Animation_ untuk mulai mengatur animasi _sprite_ dengan memilih menu _Window > Animation > Animation_. Dengan objek _player_ terpilih, akan muncul _drop down menu_ di bawah teks _Preview_ yang menampilkan seluruh _Animation_ yang berada di dalam _Animator Controller_ objek _player_. Kita coba atur _Animation_ bernama _Up_ terlebih dahulu. Untuk memberi gambar pada _Animation_, cukup pindahkan _sprite_ yang menunjukkan _player_ menghadap ke atas ke panel di mana tombol _Add Property_ berada. Secara otomatis potongan _sprite_ akan masuk ke _keyframe_ ke-0.
71+
72+
![Isi _Window Animation_](Assets/2-Gerakan-dan-Animasi/img/animation.PNG)
73+
74+
Berpindah ke _window Animator Controller_, kita atur bagaimana transisi tiap animasi berjalan. Setiap kotak yang Anda lihat di _window Animator Controller_ disebut sebagai _state_, baik kotak bertuliskan _Any State_, _End_, _Start_, dan _Animation_ yang telah Anda masukkan. Di _Animator Controller_ kita mengatur bagaimana alur perpindahan _state_ berjalan. Karena animasi pergerakan _player_ dapat berubah tergantung arah perpindahan _player_ dan tidak peduli pada arah mana _player_ menghadap, kita hubungkan kotak _Any State_ ke-empat _Animation_ kita dengan meng-klik kanan kotak _Any State_, pilih _Make Transition_, kemudian pilih _Animation_ yang ingin dihubungkan.
75+
76+
Transisi animasi akan berjalan apabila beberapa kondisi terpenuhi. Pada _Animator Controller_ terdapat empat macam tipe parameter yang bisa kita gunakan untuk menyusun kondisi transisi animasi; _float_, _integer_, _bool_, dan _trigger_. Parameter-parameter yang dibutuhkan terdapat pada tab _parameters_. Kita buat paramater baru bertipe _integer_. Penjelasan mengenai penggunaan parameter akan diterangkan pada sub-bab berikutnya.
77+
78+
## Mengubah _Sprite_ Objek _Player_ Berdasarkan Posisi _Mouse_
79+
Kita akan mengaplikasikan teori trigonometri untuk membantu pekerjaan kita menentukan _sprite player_ yang harus ditampilkan sesuai dengan posisi _mouse_ terhadap objek _player_.
80+
81+
Perhatikan gambar berikut:
82+
![Sudut](/img/sudut.png)
83+
84+
Kita memiliki _spritesheet_ yang terdiri dari delapan gambar berbeda yang juga menghadap ke arah yang berbeda juga. Pada gambar, garis hitam menunjukkan besar sudut yang dimiliki _spritesheet_ kita, sedangkan garis merah adalah jangkauan yang apabila posisi _mouse_ berada di antara kedua garis merah, maka _player_ akan "menghadap" ke arah dengan sudut sesuai dengan garis hitam yang terapit oleh kedua garis merah tersebut. Angka biru adalah indeks arah, dengan 0 menghadap ke kanan, 1 menghadap ke kanan atas, dan seterusnya. Indeks inilah yang akan kita cari untuk mengatur transisi animasi pada _Animator Controller_.
85+
86+
Perhitungan untuk mendapatkan indeks didefinisikan dengan rumus berikut:
87+
![Rumus Indeks](/img/index-eq.png)
88+
89+
_playerToMouse_ adalah vektor yang menghubungkan posisi _mouse_ dengan posisi _player_. Posisi _mouse_ didapat dengan menggunakan fungsi _Camera.ScreenToWorldPoint()_, di mana input yang dibutuhkan adalah posisi _mouse_ pada layar (diperoleh dari _Input.mousePosition_).
90+
91+
```C#
92+
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
93+
Vector3 mouseToPlayer = (mouseScreenToWorld - transform.position);
94+
int directionID = (int)((((Mathf.Atan2(mouseToPlayer.y, mouseToPlayer.x) * Mathf.Rad2Deg)+360f)%360 + 22.5f)/ 45)%8;
95+
```
96+
97+
Indeks yang didapat kemudian diteruskan ke parameter pada _Animator Controller_ melalui fungsi _AnimatorController.SetInteger()_ yang mengambil dua paramater; nama parameter yang akan diatur nilainya dan besar nilai yang akan diberikan.
98+
99+
Berikut adalah isi program pada file _MovementInput.cs_ per bab kedua:
100+
```C#
101+
public class MovementInput : MonoBehaviour
102+
{
103+
private int directionID;
104+
private Animator animator;
105+
private Vector3 mouseScreenToWorld, mouseToPlayer;
106+
public float speed = 5f;
107+
108+
void Start()
109+
{
110+
animator = gameObject.GetComponent<Animator>();
111+
}
112+
113+
void Update()
114+
{
115+
float inputX = Input.GetAxisRaw("Horizontal");
116+
float inputY = Input.GetAxisRaw("Vertical");
117+
118+
Vector3 movement = new Vector3(inputX, inputY, 0f).normalized;
119+
mouseScreenToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
120+
mouseToPlayer = (mouseScreenToWorld - transform.position);
121+
directionID = (int)((((Mathf.Atan2(mouseToPlayer.y, mouseToPlayer.x) * Mathf.Rad2Deg)+360f)%360 + 22.5f)/ 45)%8;
122+
123+
animator.SetInteger("directionIndex", directionID);
124+
transform.Translate(movement * speed * Time.deltaTime);
125+
}
126+
}
127+
```

Assets/2-Gerakan-dan-Animasi/Scenes/Game.unity

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,122 @@ NavMeshSettings:
121121
debug:
122122
m_Flags: 0
123123
m_NavMeshData: {fileID: 0}
124+
--- !u!1 &200492216
125+
GameObject:
126+
m_ObjectHideFlags: 0
127+
m_CorrespondingSourceObject: {fileID: 0}
128+
m_PrefabInstance: {fileID: 0}
129+
m_PrefabAsset: {fileID: 0}
130+
serializedVersion: 6
131+
m_Component:
132+
- component: {fileID: 200492219}
133+
- component: {fileID: 200492218}
134+
- component: {fileID: 200492217}
135+
- component: {fileID: 200492220}
136+
m_Layer: 0
137+
m_Name: NewPlayer
138+
m_TagString: Untagged
139+
m_Icon: {fileID: 0}
140+
m_NavMeshLayer: 0
141+
m_StaticEditorFlags: 0
142+
m_IsActive: 1
143+
--- !u!212 &200492217
144+
SpriteRenderer:
145+
m_ObjectHideFlags: 0
146+
m_CorrespondingSourceObject: {fileID: 0}
147+
m_PrefabInstance: {fileID: 0}
148+
m_PrefabAsset: {fileID: 0}
149+
m_GameObject: {fileID: 200492216}
150+
m_Enabled: 1
151+
m_CastShadows: 0
152+
m_ReceiveShadows: 0
153+
m_DynamicOccludee: 1
154+
m_MotionVectors: 1
155+
m_LightProbeUsage: 1
156+
m_ReflectionProbeUsage: 1
157+
m_RayTracingMode: 0
158+
m_RenderingLayerMask: 1
159+
m_RendererPriority: 0
160+
m_Materials:
161+
- {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
162+
m_StaticBatchInfo:
163+
firstSubMesh: 0
164+
subMeshCount: 0
165+
m_StaticBatchRoot: {fileID: 0}
166+
m_ProbeAnchor: {fileID: 0}
167+
m_LightProbeVolumeOverride: {fileID: 0}
168+
m_ScaleInLightmap: 1
169+
m_ReceiveGI: 1
170+
m_PreserveUVs: 0
171+
m_IgnoreNormalsForChartDetection: 0
172+
m_ImportantGI: 0
173+
m_StitchLightmapSeams: 1
174+
m_SelectedEditorRenderState: 0
175+
m_MinimumChartSize: 4
176+
m_AutoUVMaxDistance: 0.5
177+
m_AutoUVMaxAngle: 89
178+
m_LightmapParameters: {fileID: 0}
179+
m_SortingLayerID: 0
180+
m_SortingLayer: 0
181+
m_SortingOrder: 0
182+
m_Sprite: {fileID: 8144170407764102786, guid: f04734119fbe03c438a9dde4294b9c87,
183+
type: 3}
184+
m_Color: {r: 1, g: 1, b: 1, a: 1}
185+
m_FlipX: 0
186+
m_FlipY: 0
187+
m_DrawMode: 0
188+
m_Size: {x: 1, y: 1}
189+
m_AdaptiveModeThreshold: 0.5
190+
m_SpriteTileMode: 0
191+
m_WasSpriteAssigned: 1
192+
m_MaskInteraction: 0
193+
m_SpriteSortPoint: 0
194+
--- !u!95 &200492218
195+
Animator:
196+
serializedVersion: 3
197+
m_ObjectHideFlags: 0
198+
m_CorrespondingSourceObject: {fileID: 0}
199+
m_PrefabInstance: {fileID: 0}
200+
m_PrefabAsset: {fileID: 0}
201+
m_GameObject: {fileID: 200492216}
202+
m_Enabled: 1
203+
m_Avatar: {fileID: 0}
204+
m_Controller: {fileID: 9100000, guid: 56bf43ab919238c408a9c6fb8417245f, type: 2}
205+
m_CullingMode: 0
206+
m_UpdateMode: 0
207+
m_ApplyRootMotion: 0
208+
m_LinearVelocityBlending: 0
209+
m_WarningMessage:
210+
m_HasTransformHierarchy: 1
211+
m_AllowConstantClipSamplingOptimization: 1
212+
m_KeepAnimatorControllerStateOnDisable: 0
213+
--- !u!4 &200492219
214+
Transform:
215+
m_ObjectHideFlags: 0
216+
m_CorrespondingSourceObject: {fileID: 0}
217+
m_PrefabInstance: {fileID: 0}
218+
m_PrefabAsset: {fileID: 0}
219+
m_GameObject: {fileID: 200492216}
220+
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
221+
m_LocalPosition: {x: 0, y: 0, z: 0}
222+
m_LocalScale: {x: 1, y: 1, z: 1}
223+
m_Children: []
224+
m_Father: {fileID: 0}
225+
m_RootOrder: 2
226+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
227+
--- !u!114 &200492220
228+
MonoBehaviour:
229+
m_ObjectHideFlags: 0
230+
m_CorrespondingSourceObject: {fileID: 0}
231+
m_PrefabInstance: {fileID: 0}
232+
m_PrefabAsset: {fileID: 0}
233+
m_GameObject: {fileID: 200492216}
234+
m_Enabled: 1
235+
m_EditorHideFlags: 0
236+
m_Script: {fileID: 11500000, guid: 2038d51ac04b61e40bb507d55410550a, type: 3}
237+
m_Name:
238+
m_EditorClassIdentifier:
239+
speed: 5
124240
--- !u!1 &743459980
125241
GameObject:
126242
m_ObjectHideFlags: 0
@@ -222,7 +338,7 @@ GameObject:
222338
m_Icon: {fileID: 0}
223339
m_NavMeshLayer: 0
224340
m_StaticEditorFlags: 0
225-
m_IsActive: 1
341+
m_IsActive: 0
226342
--- !u!95 &1347093907
227343
Animator:
228344
serializedVersion: 3

Assets/2-Gerakan-dan-Animasi/Scripts/MovementInput.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
public class MovementInput : MonoBehaviour
66
{
7+
private int directionID;
78
private Animator animator;
9+
private Vector3 mouseScreenToWorld, mouseToPlayer;
810
public float speed = 5f;
911

1012
void Start()
@@ -14,16 +16,22 @@ void Start()
1416

1517
void Update()
1618
{
17-
float inputX = Input.GetAxis("Horizontal");
18-
float inputY = Input.GetAxis("Vertical");
19-
20-
Vector3 movement = new Vector3(inputX, inputY, 0f);
19+
// Dapatkan nilai input dari keyboard
20+
float inputX = Input.GetAxisRaw("Horizontal");
21+
float inputY = Input.GetAxisRaw("Vertical");
22+
23+
// Gunakan nilai yang telah didapatkan untuk menggerakkan pemain
24+
//Input axis are normalized to ensure every possible movements are in the same speed
25+
Vector3 movement = new Vector3(inputX, inputY, 0f).normalized;
26+
mouseScreenToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
27+
mouseToPlayer = (mouseScreenToWorld - transform.position);
28+
directionID = (int)((((Mathf.Atan2(mouseToPlayer.y, mouseToPlayer.x) * Mathf.Rad2Deg)+360f)%360 + 22.5f)/ 45)%8;
29+
// Debug.Log((Mathf.Atan2(mouseToPlayer.y, mouseToPlayer.x) * Mathf.Rad2Deg + 360f)%360 + ", "+directionID + "("+ mouseToPlayer.x + ", "+mouseToPlayer.y+")");
30+
// Debug.DrawLine(transform.position, mouseScreenToWorld, Color.red);
31+
2132

33+
// Atur animasi dan gerakkan pemain
34+
animator.SetInteger("directionIndex", directionID);
2235
transform.Translate(movement * speed * Time.deltaTime);
23-
24-
if (animator != null) {
25-
animator.SetBool("idle", movement.magnitude <= 0f);
26-
animator.SetFloat("move_x", movement.x);
27-
}
2836
}
2937
}

Assets/2-Gerakan-dan-Animasi/Sprites/Drone.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)