Just 4 fun!

Of course I can change the world, If you give me a source code

Post Ads (Documentation)

Author Info (Documentation)

style="display:block"
data-ad-client="ca-pub-2623284640924516"
data-ad-slot="8347113188"
data-ad-format="auto">

Friday, June 17, 2016

Lặt vặt về Sprite

          Chào các bạn, như đã nói trong các bài viết trước, trong bài này mình sẽ cung cấp cho các bạn một số vấn đề mấu chốt của SpriteRenderer. Có tham khảo trên trang Unityviet.com
1/ Lấy kích thước của spriterenderer:
Khi kéo thả một hình ảnh vào scene, trong Inspector sẽ có 2 thành phần mặc định đó là Transform và Sprite Renderer.Ở đây, để lấy được kích thước của hình chúng ta chỉ cần truy cập đến thành phần Sprite Renderer như sau:

      GetComponent<SpriteRenderer>().sprite.texture

Bằng cách này chúng ta đã tham chiếu đến mục sprite trong thành phần Sprite Renderer của đối tượng hình ảnh trong scene, và để lấy kích thước (chiều cao, chiều rộng) hình ảnh, ta chỉ cần gọi:

      GetComponent<SpriteRenderer>().sprite.texture.width

      GetComponent<SpriteRenderer>().sprite.texture.height

Ở đây, các bạn cần lưu ý là nó sẽ trả về kích thước thực của hình ảnh mà bạn đưa vào. Còn trong scene (ta gọi la không gian game) sử dụng kích thước khác. Ta có thể tham chiếu đến bằng cách gọi:

GetComponent<SpriteRenderer>().bounds

Ví dụ ở đây, mình kéo một hình ảnh vào scene, thêm script C# cho nó, sử dụng "Debug.Log(GetComponent<SpriteRenderer>().bounds); " trong hàm Update và đây là kết quả trong cửa sổ Console:


2/ Thay đổi size của sprite:
Ở đây, mình khuyên các bạn nếu muốn resize lại một hình ảnh trong scene thì nên thay đổi local scale của hình ảnh đó ở tranform như sau:
transform.localScale = new Vector3(0,0,0);
rất đơn giản đúng không?


3./Đổi Sprite:
Như ở trên, chúng ta khai báo một biến public Sprite t;
sau khi gán script vào một object, ta có thể kéo thả một sprite bất kì vào chỗ trống, sau đó nếu muốn thay đổi Sprite, ta chỉ việc gọi:
 GetComponent<SpriteRenderer>().sprite = t;

Ngoài ra, bằng việc gọi đến thành phần Sprite Renderer còn cho phép bạn thay đổi những thông số khác như:
Material (chất liệu): GetComponent<SpriteRenderer>().material
Flip (lật ảnh):
GetComponent<SpriteRenderer>().flipX = true;
GetComponent<SpriteRenderer>().flipY = true;
(việc lật ảnh trong game 2D giúp Dev không cần phải quay game object một góc 180 theo trục Y hoặc X nữa, tuy nhiên nó chỉ có từ phiên bản Unity 5.4 trở lên)
Order Layer:  GetComponent<SpriteRenderer>().sortingOrder = 1;
Như mình đã nói trong bài viết trước, việc đặt layer cho hình sẽ quyết định hình nào ở trên và hình nào ở dưới trong game khi render, rõ ràng sử dụng layer thuận tiện hơn xét vị trí theo trục Z rất nhiều, đặc biệt là trong game 2D.
 Chúc các bạn thành công!

Thursday, June 16, 2016

2D EXPERIMENTAL PREVIEW


Hôm nay, chúng ta sẽ cùng tìm hiểu về "2D experimental", mình cũng chẳng biết dịch như nào cho đúng lên để nguyên như của Unity :) Còn chúng ta có thể tạm hiểu là hình ảnh 2D hay Sprite.
Vậy Sprite trong unity có những đặc điểm gì?
Đầu tiên là 9-Slice Sprites:
Unity định nghĩa đó là công nghê cho phép bạn sử dụng một hình ảnh theo nhiều kích cỡ mà không phải chuhaarn bị nhiều tài nguyên. Đừng nhầm lẫn với việc scale hình ảnh, ở đây chúng ta đang nói đến việc bạn có thể import một hình ảnh và cắt nhỏ nó thành nhiều phần trong Editer của Unity để sử dụng từng phần đó, bạn có thể dễ dàng nhìn thấy lựa chọn này bằng cách đặt hình ảnh về Multiple ở Prite mode, sau đó chọn Sprites Editor để cắt.

Thứ 2 là Sorting Group:
Đây là chức năng cho phép bạn nhóm hình ảnh của mình theo từng layer trong Sence. Từ đó quyết định thứ tự hiển thị khi được render. Cũng tương tự như các phần mềm chuyên về đồ họa, đây là một chức năng rất hữu ích giúp developer có thể quyết định ảnh nào ở lớp trên và ảnh nào hiển thị ở lớp dưới mà không phải quan tâm đến tọa độ trục Z trong game 2D.
Cuối cùng đó là Sprite Mask:
Nó cho phép hiển thị hoặc ẩn một phần của hình ảnh theo một hình dạng tro trước và (tất nhiên) do developer quyết định. Có 2 loại đó là Global Mask dùng trong scene và Scoped Mask dùng cho GameObject. Cái này thường sử dụng rất nhiều trong UI, các bạn có thể tham khảo tại đây hoặc đợi bài  viết tiếp theo của mình sẽ nói chi tiết hơn :
UI mask tutorial
Các bài viết tiếp theo mình sẽ đề cập chi tiết từng chức năng, cảm ơn đã theo dõi!

Wednesday, June 8, 2016

Căn chỉnh sprite nền vừa khít màn hình

Script canh chỉnh sprite nền vừa khít màn hình

·
Mặc dù từ bản Unity 5.0 trở đi, chúng ta đã có UI hỗ trợ việc căn chỉnh hình ảnh, button, text phù hợp với mọi kích cỡ màn hình, tuy nhiên có trường hợp như bạn có 1 sprite nền (background) và muốn nó vừa khít với tất cả tỉ lệ màn hình (4:3, 16:9, …), lúc này bạn cần viết một script nhỏ để làm việc này.
Để demo, bạn tạo 1 scene, thêm vào 1 sprite là tấm hình background




lúc này bạn chưa cần quan tâm tới vị trí hay kích thước tấm hình

Sau đó bạn viết  script như sau (tôi có comment đầy đủ chi tiết từng câu lệnh):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using UnityEngine;
using System.Collections;
//phải using UnityEditor để có thể dùng TextureImporter
using UnityEditor;

public class resizeSpriteFullScreen : MonoBehaviour {
                //tham chiếu tới camera
                public Camera cam;
                // Use this for initialization
                void Start () {
                                //lấy component Sprite Renderer
                                SpriteRenderer sr = GetComponent<SpriteRenderer>();
                                //lấy hình cần đặt fullscreen
                                TextureImporter ti = AssetImporter.GetAtPath("Assets/image1.png") as TextureImporter;
                                //lấy giá trị Pixels To Units của tấm hình sprite đó
                                float PixelsToUnits = ti.spritePixelsToUnits;
                                //Khai báo vector3 mới
                                Vector3 sc = new Vector3(1f, 1f, 1f);
                                //tính toán chiều cao và chiều rộng của sprite cho khít với màn hình
                                sc.y = cam.orthographicSize*2f*PixelsToUnits/sr.sprite.rect.height;
                                sc.x = (cam.orthographicSize*(float)Screen.width/(float)Screen.height)*2f*PixelsToUnits/sr.sprite.rect.width;
                                //gán giá trị tính được vào local Scale của sprite
                                transform.localScale = sc;
                                //cho sprite vào vị trí chính giữa màn hình
                                transform.position = cam.transform.position;
                }
}
Bạn đưa script đó bỏ vào object background và kéo object Main camera vào biến tương ứng trong script
Bạn nhớ để ý scale lúc này là 1:1:1


Bây giờ bạn Play game, sẽ thấy ngay kết quả, sprite đã vừa khít màn hình, cho dù bạn thay đổi màn hình tỉ lệ hay kích thước nào chăng nữa. Ở những bài viết sau mình sẽ nói chi tiết hơn Sprite Renderer để các bạn hiểu rõ và có thể tự mình tìm ra cách scale Sprite theo tỉ lệ màn hình phù hợp nhất.


Like, share nếu bạn thấy bài viết của mình có ích! :)

Friday, December 25, 2015

Tạo đồng hồ bằng Unity3D





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,  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,  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.
using UnityEngine;

public class ClockAnimator : MonoBehaviour {
}
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) {
                       TimeSpan timespan = DateTime.Now.TimeOfDay;
                       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 {
                       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ồ ở 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!