Chào các bạn, hôm nay chúng ta sẽ thử làm một chiếc đồng
hồ bằng Unity3D.
Chúng ta bắt đầu với việc tạo một dự án Unity trống. Scene mặc định của Unity bao gồm một Camera có tọa độ (0,1,-10) nhìn xuống trục Z. Để đồng nhất góc nhìn chọn Camera và chọn GameObject / Align View to Selected từ Menu.
Chúng ta cần có một đối tượng trông giống cái
đồng hồ một chút J bằng cách tạo một Empty
Game Object (chọn GameObject / Create Empty). Đặt tọa độ của nó về (0,0,0) và sửa tên
thành Clock tạo them những đối tượng con của Clock và đặt tên lần lượt
là Hours, Minutes,
và Seconds. Nhớ kiểm tra kĩ tọa độ của chúng đều là (0,0,0).
Ta sẽ sử dụng những khối hình hộp đơn giản có
sẵn trong Unity để tạo cái đồng hồ. Tạo khối hộp bằng cách chọn GameObject
/ Create Other / Cube. Gán các khối hộp đó làm các
đối tượng con của Hours, Minutes,
và Seconds ta đã tạo ở trên. Bây giờ, với khối hộp con của Hours, ta sẽ đặt
tọa độ của nó thành (0, 1, 0) và chỉnh lại scale là (0.5, 2, 0.5). Tương tự, với
khối hộp trong Minutes ta sẽ đặt tọa độ là (0,1. 5, 0) và scale là (0.25, 3, 0.25), ở Seconds,
tọa độ của khối hộp là (0, 2, 0) và scale là (0.1, 4, 0.1).
Làm chuyển động cho cái đồng
hồ.
Chúng ta cần lập trình để cái đồng hồ chạy. Tạo một file C# bằng cách chọn Create / C#
Script trong phần Project và đặt tên nó là ClockAnimator. Mở file C# đó ra và chúng ta sẽ bắt đầu viết thuật toán cho nó.
Đầu tiên, hãy nhìn vào đoạn code mặc định của
được tạo bởi Unity. Đầu tiên, chúng ta có đoạn khai báo class ClockAnimator được định nghĩa là public và kế thừa từ MonoBehavior.
Chúng ta có thể lập trình thuật
toán và tạo ra các thành phần trong class này. Lưu đoạn code này lại và gán nó
cho đối tượng Clock mà chúng ta tạo ở
trên bằng cách kéo thả nó từ cửa sổ Project
vào cửa sổ Hierarchy (hãy nhớ
chọn đối tượng Clock trước để các cài
đặt thuộc tính của nó hiện hết lên trên cửa sổ Hyperacys ), hoặc chọn nút Add Component trong cửa sổ Hierarchy
nhập tên của file C# và ấn Enter.
File C# ClockAnimator được thêm vào đối tượng Clock
Để đồng
hồ chuyển động, chúng ta cần thay đổi thành phần Tranform của Clock, bằng cách khai báo một biến public có kiểu dữ liệu là Tranform trong file C# và lưu nó lại. Việc này sẽ thêm một thông
số vào thành phần Clock Animator , cho phép chúng ta kéo thả một đối tượng vào đó
và điều khiển nó trong trình biên dịch. Trình biên dịch sẽ nhận lấy đối tượng
có kiểu Tranform mà ta gán vào thông qua biến đã khai báo ở trên. Chọn đối
tượng Clock, có thể nhận thấy biến kiểu Tranform mà ta khai báo ở đoạn code trong file C# đã hiện
ra thành một thành phần của Clock. Kéo thả đối tượng tương ứng vào từng biến.
using UnityEngine;
public class ClockAnimator : MonoBehaviour {
public Transform hours, minutes, seconds;
}
ClockAnimator trước và sau khi gán các đối tượng.
Tiếp theo, chúng ta sẽ tiếp tục với hàm Update
trong file C#. Đây là một hàm đặc biệt trong được tạo ra bởi Unity và sẽ được gọi
liên tục trong từng frame. Chúng ta sẽ dùng nó để làm cho kim đồng hồ quay.
using UnityEngine;
public class ClockAnimator : MonoBehaviour {
public Transform hours, minutes, seconds;
private void Update () {
// currently do nothing
}
}
Sau khi lưu file lại, chúng ta có thể chọn kích
hoạt file C# này khi chạy hoặc không bằng cách chọn hoặc bỏ chọn trong ô
checkbox ở ClockAnimator. Dĩ nhiên là
ở đây chúng ta chọn để code được kích hoạt.
Chọn ở ô Checkbox để code được gọi ra trong mỗi frame khi chạy.
Sau mỗi giờ, đối tượng Hours sẽ phải quay một góc 360/12 độ. Đối tượng Minutes phải
quay 360/60 độ mỗi phút và Seconds phải
quay 360/360 độ mỗi giây.
Từ đó, ta sẽ khai báo các biến private kiểu float để lưu trữ các thông số trên
cho tiện dụng.
using UnityEngine;
public class ClockAnimator : MonoBehaviour {
private const float
hoursToDegrees = 360f / 12f,
minutesToDegrees = 360f / 60f,
secondsToDegrees = 360f / 60f;
public Transform hours, minutes, seconds;
private void Update () {
// currently do nothing
}
}
Mỗi lần gọi, chúng ta cần phải biết
giờ hiện tại để chắc chắn rằng code hoạt động đúng. Chúng ta sẽ tạo ra một
struct là DateTime thuộc namespace Systems để đảm nhiệm việc này. Nó chứa một thành
phần static là Now luôn trả về thời
gian thực của hệ thống. Chúng ta cần gán nó cho một biến tạm thời như sau:
using UnityEngine;
using System;
public class ClockAnimator : MonoBehaviour {
private const float
hoursToDegrees = 360f / 12f,
minutesToDegrees = 360f / 60f,
secondsToDegrees = 360f / 60f;
public Transform hours, minutes, seconds;
private void Update () {
DateTime time = DateTime.Now;
}
}
Giờ để cho các đối tượng quay,
chúng ta cần phải thay đổi góc độ hiện tại của chúng bằng cách sử dụng một thiết
lập có sẵn của Unity là localRotation trong
mỗi đối tượng. Lệnh Quaternion cho
phép chúng ta xác định một vòng xoay tùy ý.
Vì chúng ta nhìn xuống trục Z và
Unity sử dụng hệ thống theo tay trai nên trục quay phải được thiết lập xoay
theo trục Z.
using UnityEngine;
using System;
public class ClockAnimator : MonoBehaviour {
private const float
hoursToDegrees = 360f / 12f,
minutesToDegrees = 360f / 60f,
secondsToDegrees = 360f / 60f;
public Transform hours, minutes, seconds;
private void Update () {
DateTime time = DateTime.Now;
hours.localRotation =
Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
minutes.localRotation =
Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
seconds.localRotation =
Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
}
}
Đồng hồ hiển thị 12:44
Nâng cao
Khi play thử, chúng ta có thể thấy nó đã hoạt động
và hiển thị ra thời gian thực trên máy tính của mình. Tuy nhiên, nhìn nó vẫn chả
khác gì một cái đồng hồ điện tử vì các kim vẫn chưa trôi mượt mà theo từng
frame mà vẫn còn giật cục. Giờ hãy thêm một bước nữa để cái đồng hồ có thể hoạt
động theo kiểu analog. Khai báo một biến public tên là analog, kiểu dữ liệu boolean, chúng ta sẽ dung nó để xác định mỗi đối
tượng cần phải làm gì trong mỗi frame.
using UnityEngine;
using System;
public class ClockAnimator : MonoBehaviour {
private const float
hoursToDegrees = 360f / 12f,
minutesToDegrees = 360f / 60f,
secondsToDegrees = 360f / 60f;
public Transform hours, minutes, seconds;
public bool analog;
private void Update () {
if (analog) {
// currently do nothing
}
else {
DateTime time = DateTime.Now;
hours.localRotation =
Quaternion.Euler(0f, 0f, time.Hour * -hoursToDegrees);
minutes.localRotation =
Quaternion.Euler(0f, 0f, time.Minute * -minutesToDegrees);
seconds.localRotation =
Quaternion.Euler(0f, 0f, time.Second * -secondsToDegrees);
}
}
}
ClockAnimator cho phép chế độ Analog
Giờ để có thể cho phép chế độ analog, chúng ta
cần phải thực hiện một số thay đổi nhỏ. Thay vì dung DateTime.Now, chúng ta sẽ
dùng Timespan là DateTime.Now.TimeofDay.
Hàm này cho phép chúng ta chia nhỏ mỗi giây, phút, giờ trôi qua. Vì giá trị này
cũng cấp độ chính xác gấp đôi – kiểu thập phân cực cực kì nhỏ - chúng ta cần
khai báo chúng về kiểu floats.
using
UnityEngine;
using
System;
public class ClockAnimator
: MonoBehaviour
{
private const float
hoursToDegrees = 360f / 12f,
minutesToDegrees = 360f / 60f,
secondsToDegrees = 360f / 60f;
public Transform
hours, minutes, seconds;
public bool
analog;
private void Update
() {
if
(analog) {
hours.localRotation = Quaternion.Euler(
0f, 0f, (float)timespan.TotalHours
* -hoursToDegrees);
minutes.localRotation = Quaternion.Euler(
0f, 0f, (float)timespan.TotalMinutes
* -minutesToDegrees);
seconds.localRotation = Quaternion.Euler(
0f, 0f, (float)timespan.TotalSeconds
* -secondsToDegrees);
}
else {
hours.localRotation =
Quaternion.Euler(0f, 0f,
time.Hour * -hoursToDegrees);
minutes.localRotation =
Quaternion.Euler(0f, 0f,
time.Minute * -minutesToDegrees);
seconds.localRotation =
Quaternion.Euler(0f, 0f,
time.Second * -secondsToDegrees);
}
}
}
Đồng hồ ở chế độ analog đang hiển thị 12:56
Giờ đồng hồ của chúng ta đã có thể chạy theo kiểu
analog rồi J
yeahhhhhhhhhhhhhhhh!
No comments:
Post a Comment