Hiển thị các bài đăng có nhãn Project RPG. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Project RPG. Hiển thị tất cả bài đăng

Thứ Năm, 8 tháng 5, 2014

Project RPG BÀI 16. HIỂN THỊ TÊN KHI XÁC ĐỊNH MỤC TIÊU



Ở bài viết Project RPG BÀI 4. Xác định mục tiêu, chúng ta đã tạo ra script Targetting để chọn đối tượng trong phạm vi của nhân vật bằng phím Tab và thay đổi mục tiêu qua lại giữa các đối tượng. Ở bài viết này, chúng ta sẽ tạo ra một script mới dựa theo script Targetting nhưng có thêm phần hiển thị tên mục tiêu cùng thanh máu thay vì chỉ thay đổi màu sắc như ở bài trước.


B1. Double click vào scene Level1 ở thẻ Project để tiếp tục làm việc với scene này.

B2. Vào Edit | Project Settings | Tags and Layers và qua thẻ Inspector, mục Tags nhập vào Element 0 là Enemy.


B3. Tại thẻ Project, nhấp chọn mob_Slug ở thư mục Prefabs và qua thẻ Inspector, điều chỉnh tag là Enemy.

B4. Tại thẻ Hierarchy, đổi tên 3 đối tượng mob_Slug thành mob_Slug 1, mob_Slug 2, mob_Slug 3 và chỉnh tag cho cả 3 là Enemy. (Lưu ý: không nên chọn tất cả rồi đặt tag trong một lần vì có thể dính tag cho đối tượng con là Armateur)

 

B5. Tại thẻ Hierarchy, nhấp chọn Create | 3D Text và đặt tên là Name.


B6. Nhấp chọn Name ở thẻ Hierarchy vừa tạo ở bước trên và qua thẻ Inspector, điều chỉnh như sau:


B7. Kéo thả Name vào mob_Slug 1 rồi qua thẻ Inspector, điều chỉnh tọa độ và Mesh Render của Name như sau:


B8. Tại thẻ Hierarchy, nhấp chọn mob_Slug 1 và qua thẻ Inspector, bấm chọn nút Apply để các mob_slug còn lại đều có thêm Name giống như mob_Slug 1 vừa điều chỉnh.

 


B9. Nhấp phải vào thư mục Script và chọn Create | C# Script và đặt tên là TargetMob. Double click vào file này và xóa tất cả đi, chèn lại đoạn code sau vào:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class TargetMob : MonoBehaviour {
    public List<Transform> targets;
    public Transform selectedTarget;
   
    private Transform myTransform;
    // Use this for initialization
    void Start () {
        targets = new List<Transform>();
        selectedTarget = null;
        myTransform = transform;
        AddAllEnemies();
    }
   
    public void AddAllEnemies(){
        GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");
       
        foreach(GameObject enemy in go)
            AddTarget(enemy.transform);
    }
   
    public void AddTarget(Transform enemy){
        targets.Add (enemy);
    }
   
    private void SortTargetsByDistance(){
        targets.Sort(delegate(Transform t1, Transform t2){
            return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
        });
       
    }
   
    private void TargetEnemy(){
        if(selectedTarget == null){
            SortTargetsByDistance();
            selectedTarget = targets[0];
        }
        else{
            int index = targets.IndexOf (selectedTarget);
           
            if(index < targets.Count - 1){
                index++;
            }
            else{
                index = 0;
            }
            DeselectTarget();
            selectedTarget = targets[index];
        }
        SelectTarget();
    }
   
    private void SelectTarget(){
        Transform name = selectedTarget.FindChild ("Name");

        if (name == null) {
            Debug.LogError("Could not find the Name on " + selectedTarget.name);
            return;
        }

        name.GetComponent<TextMesh>().text = selectedTarget.GetComponent<Mob>().Name;
        name.GetComponent<MeshRenderer>().enabled = true;
        selectedTarget.GetComponent<Mob>().DisplayHealth();

        Messenger<bool>.Broadcast("show mob vitalbars", true);
    }

    private void DeselectTarget(){
        selectedTarget.FindChild ("Name").GetComponent<MeshRenderer> ().enabled = false;
       
        selectedTarget = null;
        Messenger<bool>.Broadcast("show mob vitalbars", false);
    }

    // Update is called once per frame
    void Update () {
        if(Input.GetKeyDown(KeyCode.Tab)){
            TargetEnemy();
        }
    }
}

B10. Kéo thả file C# TargetMob vào Game Master ở thẻ Hierarchy.


B11. Double click vào file C# Mob và xóa tất cả đi chèn lại đoạn code bên dưới vào:

 using UnityEngine;
using System.Collections;

public class Mob : BaseCharacter {
    public int curHealth;
    public int maxHealth;
  
    // Use this for initialization
    void Start () {
    //    GetPrimaryAttribute ((int)AttributeName.Constituion).BaseValue = 100;
    //    GetVital((int)VitalName.Health).Update ();

        Name = "Slug Mob";
    }
  
    // Update is called once per frame
    void Update () {

    }

    public void DisplayHealth(){
        Messenger<int, int>.Broadcast("mob health update", curHealth, maxHealth);

    }
}


B12. Tại thẻ Project, nhấp chọn mob_Slug 1 rồi qua thẻ Inspector, điều chỉnh Cur Health và Max Health như sau:


B13. Thực hiện tương tự với các mob_Slug còn lại nhưng nhập vào các giá trị Cur Health khác nhau còn Max Health giống bước trên.


B14. Double click vào file C# VitarBar nằm trong thư mục HUDClasses, xóa tất cả đi và chèn lại đoạn code sau vào:

/// <summary>
/// VitalBar.cs
///
/// This class is responsble for displaying a vita for the player character or a mob...
/// </summary>
using UnityEngine;
using System.Collections;

public class VitalBar : MonoBehaviour {
    public bool _isPlayerHealthBar;
   
    private int _maxBarLength;
    private int _curBarLength;
    private GUITexture _display;

    void Awake(){
        _display = gameObject.GetComponent<GUITexture>();
    }

    // Use this for initialization
    void Start () {

        _maxBarLength = (int)_display.pixelInset.width;

        _curBarLength = _maxBarLength;
        _display.pixelInset = CalculatePosition ();
        OnEnable();
    }
   

    //This method is called when the gameobject is enabled
    public void OnEnable(){
        if(_isPlayerHealthBar)
            Messenger<int, int>.AddListener("player health update", OnChangeHealthBarSize);
        else{
            ToggleDisplay(false);
            Messenger<int, int>.AddListener("mob health update", OnChangeHealthBarSize);
            Messenger<bool>.AddListener("show mob vitalbars", ToggleDisplay);
        }
    }
   
    //this method is called when the gameobject is disabled
    public void OnDisable(){
        if(_isPlayerHealthBar)
            Messenger<int, int>.RemoveListener("player health update", OnChangeHealthBarSize);
        else{
            Messenger<int, int>.RemoveListener("mob health update", OnChangeHealthBarSize);
            Messenger<bool>.RemoveListener("show mob vitalbars", ToggleDisplay);
        }
    }
   
    //This method will calculate the total size of the healthbar in relation to the % of health the target has left
    public void OnChangeHealthBarSize(int curHealth, int maxHealth){
        //Debug.Log("We heard an event: curHealth = " + curHealth + " - maxHealth = " + maxHealth);
        _curBarLength = (int)((curHealth / (float)maxHealth) * _maxBarLength);    //this calculate the current bar length based on the player health %

        //_display.pixelInset = new Rect(_display.pixelInset.x, _display.pixelInset.y, _curBarLength, _display.pixelInset.height);
        _display.pixelInset = CalculatePosition();
    }
   
    //setting the health bar to the player or mob
    public void SetPlayerHealth(bool b){
        _isPlayerHealthBar = b;
    }

    private Rect CalculatePosition(){
        float yPos = _display.pixelInset.y / 2 - 10;

        if(!_isPlayerHealthBar){
            float xPos = (_maxBarLength - _curBarLength) - (_maxBarLength / 4 + 10);
            return new Rect(xPos, yPos, _curBarLength, _display.pixelInset.height);
        }

        return new Rect(_display.pixelInset.x, yPos, _curBarLength, _display.pixelInset.height);

    }

    private void ToggleDisplay (bool show){
        _display.enabled = show;

    }
}


B15. Save scene và ấn nút Play để kiểm tra thành quả. Ấn Tab để thay đổi qua lại giữa các mục tiêu.

Chủ Nhật, 27 tháng 4, 2014

Project RPG BÀI 15. MOB CLASS



Bài viết này mình sẽ sử dụng model mob đã download về từ bài 13 để import kẻ địch cho nhân vật vào scene.



B1. Tại thẻ Project, double click vào scene Level1 nằm trong thư mục Scenes để mở scene này lên.Ở thẻ Hierarchy sẽ bao gồm các đối tượng sau:


B2. Tại thẻ Project, vào thư mục Assets | monsterMob đã tải ở Bài 13 và nhấp chọn monsterMob, qua thẻ Inspector điều chỉnh như sau:

 

B3. Vẫn ở thẻ Project, kéo thả prefab monsterMob vào thẻ Hierarchy. Qua thẻ Inspector, nhấp phải vào Animator và chọn Remove Component. Vào Component | Miscellanious | Animation và điều chỉnh như sau:


B4. Nhấp phải vào thư mục Script ở thẻ Project và chọn Create | C# Script và đặt tên là Mob. Double click vào file C# vừa tạo và xóa tất cả đi chèn đoạn code sau vào:

using UnityEngine;
using System.Collections;

public class Mob : BaseCharacter {

    // Use this for initialization
    void Start () {
        GetPrimaryAttribute ((int)AttributeName.Constituion).BaseValue = 100;
        GetVital((int)VitalName.Health).Update ();
   
    }
   
    // Update is called once per frame
    void Update () {
        Messenger<int, int>.Broadcast("mob health update", 80, 100);
    }
}


B5. Kéo thả file C# Mob vào monsterMob ở thẻ Hierarchy.


B6. Tại thẻ Project, nhấp phải vào thư mục Prefabs và chọn Create | Prefab và đặt tên là mob_Slug.


B7. Kéo thả monsterMob ở thẻ Hierarchy vào mob_Slug ở thẻ Project | Prefabs.


B8. Nhấp chọn monsterMob ở thẻ Hierarchy và nhấn Delete.


B9. Kéo thả mob_Slug ở thẻ Project vào thẻ Hierarchy.


B10. Nhấp chọn mob_Slug ở thẻ Hierarchy, qua thẻ Inspector, nhập tọa độ vào như sau:

 

B11. Tại thẻ Hierarchy, nhấp chọn mob_Slug và ấn Ctrl + D 2 lần và kéo 2 đối tượng vừa tạo sang 2 phía như hình sau:


B12. Ấn Ctrl + S để save scene Level1 lại.

Thứ Tư, 9 tháng 4, 2014

Project RPG BÀI 14B. DỌN DẸP FILE SKILL


Thêm chú thích và các công dụng để dễ hiểu rõ hơn phần nào về các tính năng của script Skill...


Double click vào file Skill và xóa tất cả đi, chèn lại đoạn code sau vào:

/// <summary>
/// Skill.cs
///
/// This class contain all the extra function that are needed for a skill
/// </summary>
public class Skill : ModifiedStat {
    private bool _known;            //a boolean variable to toggle if a character knowns a skill

    /// <summary>
    /// Initializes a new instance of the <see cref="Skill"/> class.
    /// </summary>
    public Skill(){
        UnityEngine.Debug.Log ("Skill created");
        _known = false;
        ExpToLevel = 25;
        LevelModifier = 1.1f;
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="Skill"/> is known.
    /// </summary>
    /// <value><c>true</c> if known; otherwise, <c>false</c>.</value>
    public bool Known{
        get{ return _known; }
        set{ _known = value; }
    }
}

/// <summary>
/// This enumeration is just a list of skills the player can learn
/// </summary>
public enum SkillName{
    Melee_Offence,
    Melee_Defence,
    Ranged_Offence,
    Ranged_Defence,
    Magic_Offence,
    Magic_Defence
}

Project RPG BÀI 14A. DỌN DẸP FILE VITAL


Thêm chú thích và các công dụng để dễ hiểu rõ hơn phần nào về các tính năng của script Vital...


Double click vào file Vital và xóa tất cả đi, chèn lại đoạn script sau vào:

/// <summary>
/// Vital.cs
/// This class contain all the extra function for a character vitals
/// </summary>

public class Vital : ModifiedStat {
    private int _curValue;                //this is the current value of this vital

    /// <summary>
    /// Initializes a new instance of the <see cref="Vital"/> class.
    /// </summary>
    public Vital(){
        UnityEngine.Debug.Log ("Vital Created");
        _curValue = 0;
        ExpToLevel = 40;
        LevelModifier = 1.1f;
    }

    /// <summary>
    /// When getting the _curValue, make sure that it is not greater than our AdjustedBaseValue
    /// If it is, make it the same as our AdjustedBaseValue
    /// </summary>
    /// <value>The current value.</value>
    public int CurValue{
        get{
            if(_curValue > AdjustedBaseValue)
                _curValue = AdjustedBaseValue;
           
            return _curValue;
        }
        set{ _curValue = value; }
    }
}

/// <summary>
/// This enumerations is just a list of the vitals our character will have
/// </summary>
public enum VitalName{
    Health,
    Energy,
    Mana
}

Thứ Năm, 6 tháng 3, 2014

Project RPG BÀI 13. SỬ DỤNG GUI TEXTURE CHO THANH MÁU

 


Ở bài viết đầu tiên, chúng ta đã tạo thanh máu cho nhân vật bằng GUI Box, bây giờ, chúng ta sẽ sử dụng GUI Texture để hiển thị thanh máu với sự hỗ trợ của C# Messenger Extended đã tạo ở bài 12.



B1. Double click vào scene Level1 để làm việc với màn này. Tại thẻ Project, nhấp phải vào thư mục Prefab và chọn Create | Prefabs và đặt tên là Player Health bar Prefab.



B2. Tải file guiTexture.rar này về (Tệp / Lưu Ctrl + S) giải nén và kéo thả ảnh redBar.png vào thư mục Skin, kéo thả thư mục monsterMob vào thư mục Assets.

B3. Vào GameObject | Create Other | GUI Texture. Tại thẻ Project, kéo thả file ảnh redBar vào Texture của UnityWatermark-small ở thẻ Inspector vừa tạo ở bước trên và điều chỉnh như sau:


B4. Kéo thả file C# VitalBar ở thẻ Project vào UnityWatermark-small ở thẻ Hierarchy.


B5. Kéo thả UnityWatermark-small vào Player Health bar Prefab ở thẻ Project.


B6. Nhấp chọn UnityWatermark-small ở thẻ Hierarchy và ấn Delete.


B7. Kéo thả Player Health bar Prefab ở thẻ Project vào thẻ Hierarchy.


B8. Tại thẻ Project, nhấp chọn Player Health bar Prefab, ấn Ctrl + D để nhân đôi đối tượng này lên và đổi tên đối tượng mới thành Mob Health bar Prefab.


B9. Kéo thả  Mob Health bar Prefab ở thẻ Project vào thẻ Hierarchy.


B10. Nhấp chọn Mob Health bar Prefab ở thẻ Hierarchy, qua thẻ Inspector, điều chỉnh các thông số như hình sau:


B11. Double click vào file C# VitalBar, xóa tất cả đi và chèn lại đoạn code sau vào:

 /// <summary>
/// VitalBar.cs
///
/// This class is responsble for displaying a vita fpr the player character or a mob...
/// </summary>
using UnityEngine;
using System.Collections;

public class VitalBar : MonoBehaviour {
    public bool _isPlayerHealthBar;

    private int _maxBarLength;
    private int _curBarLength;
    private GUITexture _display;

    // Use this for initialization
    void Start () {
        //_isPlayerHealthBar = true;

        _display = gameObject.GetComponent<GUITexture>();

        _maxBarLength = (int)_display.pixelInset.width;
        OnEnable();
    }
  
    // Update is called once per frame
    void Update () {
  
    }

    //This method is called when the gameobject is enabled
    public void OnEnable(){
        if(_isPlayerHealthBar)
            Messenger<int, int>.AddListener("player health update", OnChangeHealthBarSize);
        else
            Messenger<int, int>.AddListener("mob health update", OnChangeHealthBarSize);
    }

    //this method is called when the gameobject is disabled
    public void OnDisable(){
        if(_isPlayerHealthBar)
            Messenger<int, int>.RemoveListener("player health update", OnChangeHealthBarSize);
        else
            Messenger<int, int>.RemoveListener("mob health update", OnChangeHealthBarSize);

    }

    //This method will calculate the total size of the healthbar in relation to the % of health the target has left
    public void OnChangeHealthBarSize(int curHealth, int maxHealth){
        //Debug.Log("We heard an event: curHealth = " + curHealth + " - maxHealth = " + maxHealth);
        _curBarLength = (int)((curHealth / (float)maxHealth) * _maxBarLength);    //this calculate the current bar length based on the player health %
        _display.pixelInset = new Rect(_display.pixelInset.x, _display.pixelInset.y, _curBarLength, _display.pixelInset.height);
  
    }

    //setting the health bar to the player or mob
    public void SetPlayerHealth(bool b){
        _isPlayerHealthBar = b;
    }
}


B12. Double click vào file C# PlayerCharacter, xóa tất cả đi và chèn lại đoạn code sau vào:

 public class PlayerCharacter : BaseCharacter {
    void Update(){
        Messenger<int, int>.Broadcast("player health update", 80, 100);
    }
}


B13. Tại thẻ Hierarchy, nhấp chọn Mob Health bar Prefab, qua thẻ Inspector, bỏ dấu stick ở mục Is Player Health Bar đi.


B14. Tại thẻ Hierarchy, nhấp chọn Player Health bar Prefab, qua thẻ Inspector, đánh dấu stick vào mục Is Player Health Bar.


B15. Nhấn Ctrl + S để save scene Level1 này lại. Nhấp nút Play để kiểm tra thành quả.


Thứ Ba, 25 tháng 2, 2014

Project RPG BÀI 12. CSharpMessenger Extended

 

Đây là file C# thông báo (hay còn gọi là trung tâm thông báo), nó cung cấp đoạn hội thoại để kiểm tra giữa người tạp sự kiện (event) và người dùng của sự kiện đó mà không cần phải đợi đến người dùng hợp tác với người tạo. Điều này hiệu quả hơn cho việc kiểm tra, phát hiện lỗi trong quá trình xử lý.

B1. Nhấp phải vào thư mục Script và chọn Create | Folder và đặt tên là CSMessenger Extended.





B2. Nhấp phải vào thư mục CSMessenger Extended và chọn Create | C# Script và đặt tên là Callback. Double click vào file C# vừa tạo và xóa tất cả đi, chèn đoạn code sau vào:

// MessengerUnitTest.cs v1.0 by Magnus Wolffelt, magnus.wolffelt@gmail.com
//
// Delegates used in Messenger.cs.

public delegate void Callback();
public delegate void Callback<T>(T arg1);
public delegate void Callback<T, U>(T arg1, U arg2);
public delegate void Callback<T, U, V>(T arg1, U arg2, V arg3);


B3. Nhấp phải vào thư mục CSMessenger Extended và chọn Create | C# Script và đặt tên là Messenger. Double click vào file C# vừa tạo và xóa tất cả đi, chèn đoạn code sau vào:

// Messenger.cs v1.0 by Magnus Wolffelt, magnus.wolffelt@gmail.com
//
// Inspired by and based on Rod Hyde's Messenger:
// http://www.unifycommunity.com/wiki/index.php?title=CSharpMessenger
//
// This is a C# messenger (notification center). It uses delegates
// and generics to provide type-checked messaging between event producers and
// event consumers, without the need for producers or consumers to be aware of
// each other. The major improvement from Hyde's implementation is that
// there is more extensive error detection, preventing silent bugs.
//
// Usage example:
// Messenger<float>.AddListener("myEvent", MyEventHandler);
// ...
// Messenger<float>.Broadcast("myEvent", 1.0f);


using System;
using System.Collections.Generic;

public enum MessengerMode {
    DONT_REQUIRE_LISTENER,
    REQUIRE_LISTENER,
}


static internal class MessengerInternal {
    static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
    static public readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;
  
    static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded) {
        if (!eventTable.ContainsKey(eventType)) {
            eventTable.Add(eventType, null);
        }
      
        Delegate d = eventTable[eventType];
        if (d != null && d.GetType() != listenerBeingAdded.GetType()) {
            throw new ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name));
        }
    }
  
    static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved) {
        if (eventTable.ContainsKey(eventType)) {
            Delegate d = eventTable[eventType];
          
            if (d == null) {
                throw new ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
            } else if (d.GetType() != listenerBeingRemoved.GetType()) {
                throw new ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
        } else {
            throw new ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
        }
    }
  
    static public void OnListenerRemoved(string eventType) {
        if (eventTable[eventType] == null) {
            eventTable.Remove(eventType);
        }
    }
  
    static public void OnBroadcasting(string eventType, MessengerMode mode) {
        if (mode == MessengerMode.REQUIRE_LISTENER && !eventTable.ContainsKey(eventType)) {
            throw new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
        }
    }
  
    static public BroadcastException CreateBroadcastSignatureException(string eventType) {
        return new BroadcastException(string.Format("Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventType));
    }
  
    public class BroadcastException : Exception {
        public BroadcastException(string msg)
        : base(msg) {
        }
    }
  
    public class ListenerException : Exception {
        public ListenerException(string msg)
        : base(msg) {
        }
    }
}


// No parameters
static public class Messenger {
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
  
    static public void AddListener(string eventType, Callback handler) {
        MessengerInternal.OnListenerAdding(eventType, handler);
        eventTable[eventType] = (Callback)eventTable[eventType] + handler;
    }
  
    static public void RemoveListener(string eventType, Callback handler) {
        MessengerInternal.OnListenerRemoving(eventType, handler);  
        eventTable[eventType] = (Callback)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }
  
    static public void Broadcast(string eventType) {
        Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
    }
  
    static public void Broadcast(string eventType, MessengerMode mode) {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d)) {
            Callback callback = d as Callback;
            if (callback != null) {
                callback();
            } else {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}

// One parameter
static public class Messenger<T> {
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
  
    static public void AddListener(string eventType, Callback<T> handler) {
        MessengerInternal.OnListenerAdding(eventType, handler);
        eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
    }
  
    static public void RemoveListener(string eventType, Callback<T> handler) {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }
  
    static public void Broadcast(string eventType, T arg1) {
        Broadcast(eventType, arg1, MessengerInternal.DEFAULT_MODE);
    }
  
    static public void Broadcast(string eventType, T arg1, MessengerMode mode) {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d)) {
            Callback<T> callback = d as Callback<T>;
            if (callback != null) {
                callback(arg1);
            } else {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}


// Two parameters
static public class Messenger<T, U> {
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
  
    static public void AddListener(string eventType, Callback<T, U> handler) {
        MessengerInternal.OnListenerAdding(eventType, handler);
        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;
    }
  
    static public void RemoveListener(string eventType, Callback<T, U> handler) {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }
  
    static public void Broadcast(string eventType, T arg1, U arg2) {
        Broadcast(eventType, arg1, arg2, MessengerInternal.DEFAULT_MODE);
    }
  
    static public void Broadcast(string eventType, T arg1, U arg2, MessengerMode mode) {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d)) {
            Callback<T, U> callback = d as Callback<T, U>;
            if (callback != null) {
                callback(arg1, arg2);
            } else {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}


// Three parameters
static public class Messenger<T, U, V> {
    private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
  
    static public void AddListener(string eventType, Callback<T, U, V> handler) {
        MessengerInternal.OnListenerAdding(eventType, handler);
        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] + handler;
    }
  
    static public void RemoveListener(string eventType, Callback<T, U, V> handler) {
        MessengerInternal.OnListenerRemoving(eventType, handler);
        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] - handler;
        MessengerInternal.OnListenerRemoved(eventType);
    }
  
    static public void Broadcast(string eventType, T arg1, U arg2, V arg3) {
        Broadcast(eventType, arg1, arg2, arg3, MessengerInternal.DEFAULT_MODE);
    }
  
    static public void Broadcast(string eventType, T arg1, U arg2, V arg3, MessengerMode mode) {
        MessengerInternal.OnBroadcasting(eventType, mode);
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d)) {
            Callback<T, U, V> callback = d as Callback<T, U, V>;
            if (callback != null) {
                callback(arg1, arg2, arg3);
            } else {
                throw MessengerInternal.CreateBroadcastSignatureException(eventType);
            }
        }
    }
}


B4. Nhấp phải vào thư mục Script và chọn Create | Folder và đặt tên là HUD Classes.


B5. Nhấp phải vào thư mục HUD Classes và chọn Create | C# Script và đặt tên là VitalBar. Double click vào file C# vừa tạo và xóa tất cả đi, chèn đoạn code sau vào:

/// <summary>
/// VitalBar.cs
///
/// This class is responsble for displaying a vita fpr the player character or a mob...
/// </summary>
using UnityEngine;
using System.Collections;

public class VitalBar : MonoBehaviour {

    // Use this for initialization
    void Start () {
  
    }
  
    // Update is called once per frame
    void Update () {
  
    }

    //This method is called when the gameobject is enabled
    public void OnEnable(){
    }

    //this method is called when the gameobject is disabled
    public void OnDisable(){
    }
}


Bài viết sau sẽ làm rõ hơn về file VitalBar cho các bạn!

Thứ Ba, 18 tháng 2, 2014

Project RPG BÀI 11. TẠO ĐIỂM HỒI SINH


Khi nhân vật được khởi tạo hoặc chết trong game, sau một khoảng thời gian nhân vật đó sẽ được hồi sinh và được đưa đến điểm nhất định hay còn gọi là "về làng", điểm đó được gọi là điểm hồi sinh (spawn point).



B1. Double click vào scene Level1 để tiến hành làm việc trên scene này. Sau đó vào Game Object | Create other | Terrain để tiến hành tạo địa hình cho game.


B2. Nhấp phải vào thẻ Project và chọn Import Package | Terrain Assets để sử dụng các file ảnh làm vật liệu cho địa hình.


B3. Tại thẻ Hierarchy, nhấp chọn Terrain, qua thẻ Inspector, sử dụng các công cụ trong Terrain (Script) để tạo độ ghồ ghề, mấp mô cho terrain theo ý bạn.

 

 

B4. Vẫn ở thẻ Inspector, nhấp chọn Paint Texture, nhấp chuột vào nút Edit Textures và chọn Add Texture. Tại khung Texture, nhấp chọn nút Select và double click vào Grass (Hill). Ấn nút Add để gán vật liệu này cho địa hình.

   

B5. Vào Game Object | Create Empty và đặt tên là Player Spawn Point, dùng công cụ dịch chuyển và kéo game object này ra vị trí rộng rãi để làm điểm hồi sinh. Nhớ kéo lên phía trên địa hình một khoảng bởi vì khi khởi tạo mô hình, nhân vật của bạn có thể bị rơi xuống bên dưới địa hình bởi lực hút.


B6. Double click vào file C# GameSettings và chèn thêm dòng code tô đỏ như sau:

public class GameSettings : MonoBehaviour {
    public const string PLAYER_SPAWN_POINT = "Player Spawn Point";        

    //This is the name of the gameobject that the player will spawn on at the start of level
    void Awake(){
        DontDestroyOnLoad(this);
    }


B7. Double click vào file C# GameMaster và xóa tất cả đi, chèn lại đoạn code sau vào:

using UnityEngine;
using System.Collections;

public class GameMaster : MonoBehaviour {
    public GameObject playerCharacter;
    public GameObject gameSettings;
    public Camera mainCamera;

    public float zOffset;
    public float yOffset;
    public float xRotOffset;

    private GameObject _pc;
    private PlayerCharacter _pcScript;

    private Vector3 _playerSpawnPointPos;            //this is the place where player will spawn

    // Use this for initialization
    void Start () {
        _playerSpawnPointPos = new Vector3(107, 1, 116);        //the default position for our player spawn point

        GameObject go = GameObject.Find(GameSettings.PLAYER_SPAWN_POINT);

        if(go == null){
            Debug.LogWarning("Can not find Player Spawn Point");

            go = new GameObject(GameSettings.PLAYER_SPAWN_POINT);
            Debug.Log("Created Player Spawn Point");

            go.transform.position = _playerSpawnPointPos;
            Debug.Log("Moved Player Spawn Point");
        }

        _pc = Instantiate(playerCharacter, go.transform.position, Quaternion.identity) as GameObject;
        _pc.name = "pc";

        _pcScript = _pc.GetComponent<PlayerCharacter>();

        zOffset = -2.5f;
        yOffset = 2.5f;
        xRotOffset = 22.5f;
        mainCamera.transform.position = new Vector3 (_pc.transform.position.x, _pc.transform.position.y + yOffset, _pc.transform.position.z + zOffset);
        mainCamera.transform.Rotate(xRotOffset, 0, 0);

        LoadCharacter();
    }

    public void LoadCharacter(){
        GameObject gs = GameObject.Find("__GameSettings");

        if(gs == null){
            GameObject gs1 = Instantiate(gameSettings, Vector3.zero, Quaternion.identity) as GameObject;
            gs1.name = "__GameSettings";
        }
            GameSettings gsScript = GameObject.Find ("__GameSettings").GetComponent<GameSettings>();

            //loading the character data
            gsScript.LoadCharacterData();


    }
}


Nếu bạn tự tạo ra điểm hồi sinh và dùng công cụ di chuyển bằng chuột để kéo thả điểm hồi sinh đến nơi bạn muốn như đã làm ở B5 rồi bạn có thể qua B9. Bạn cũng có thể để file script tự tạo điểm hồi sinh cho bạn bằng cách thiết lập tọa độ mặc định cho game object này thông qua B8.

B8 (Xóa Player Spawn Point ở thẻ Hierarchy đi). Hãy thay đổi tọa độ điểm hồi sinh bằng cách đổi tọa độ của 3 tọa độ được tô đỏ (107, 1, 116) ở file C# GameMaster phù hợp với địa hình mà bạn đã tạo, nên đặt tọa độ điểm hồi sinh ở nơi rộng và bằng phẳng để tránh việc nhân vật bị kẹt vào địa hình.

B9. Ấn Ctrl + S để lưu scene Level1 lại. Nhấp nút Play để kiểm tra thành quả.

Thứ Sáu, 14 tháng 2, 2014

Project RPG BÀI 10C. DỌN DẸP FILE ModifiedStat


Chuỗi bài viết dọn dẹp nhà cửa vì lo ăn tết nên post muộn :D



Double click vào file C# ModifiedStat và xóa tất cả đi, chèn lại đoạn code sau vào:

/// <summary>
/// ModifiedStat.cs
/// This is the base class for all stats that will be modifiable by attributes
/// </summary>
using System.Collections.Generic;                //Generic was added so we can use the List<>

public class ModifiedStat : BaseStat {
    private List<ModifyingAttribute> _mods;        //A listof Attribute that modify this stat
    private int _modValue;                        //The amount added to the baseValue from the modifiers

    /// <summary>
    /// Initializes a new instance of the <see cref="ModifiedStat"/> class.
    /// </summary>
    public ModifiedStat(){
        UnityEngine.Debug.Log("Modified Created");
        _mods = new List<ModifyingAttribute>();
        _modValue = 0;
    }

    /// <summary>
    /// Add a ModifyingAttribute to list of mods for this ModifiedStat
    /// </summary>
    /// <param name="mod">Mod.</param>
    public void AddModifier( ModifyingAttribute mod ){
        _mods.Add(mod);
    }

    /// <summary>
    /// Reset _modValue to 0.
    /// Check to see if we have at least one ModifyingAttribute in our list of mods.
    /// If we d, then interate through the list and add the AdjustedBaseValue * ratio to our modValue
    /// </summary>
    private void CalculateModValue(){
        _modValue = 0;

        if(_mods.Count > 0)
            foreach(ModifyingAttribute att in _mods)
                _modValue += (int)(att.attribute.AdjustedBaseValue * att.ratio);
    }

    /// <summary>
    /// This function is overriding the AdjustBaseValue in the BaseStat class
    /// Calculate the AdjustBaseValue from the BaseValue + Buffvale+ _modValue
    /// </summary>
    /// <value>The adjusted base value.</value>
    public new int AdjustedBaseValue{
        get{ return BaseValue + BuffValue + _modValue; }
    }

    /// <summary>
    /// Update this instance.
    /// </summary>
    public void Update(){
        CalculateModValue();
    }

    public string GetModifyingAttributesString(){
        string temp = "";

        //UnityEngine.Debug.Log("Number of mods: " + _mods.Count);

        for(int cnt = 0; cnt < _mods.Count; cnt++){
            temp += _mods[cnt].attribute.Name;
            temp += "_";
            temp += _mods[cnt].ratio;

            if(cnt < _mods.Count - 1)
                temp += "|";

        }
       
        //UnityEngine.Debug.Log(temp);
        return temp;
    }
}

/// <summary>
/// A structue that will hold an Attribute and a ratio that will be added as a modifying attribute to our ModifiedStats
/// </summary>
public struct ModifyingAttribute{
    public Attribute attribute;        //the attribute to be used as a modifier
    public float ratio;                //the percent of the attributes AdjustedBaseValue that will be to our ModifiedStats

    /// <summary>
    /// Initializes a new instance of the <see cref="ModifyingAttribute"/> struct.
    /// </summary>
    /// <param name="att">
    /// Att. the attribute to be used
    /// </param>
    /// <param name="rat">
    /// Rat. the ratio to be used
    /// </param>
    public ModifyingAttribute(Attribute att, float rat){
        UnityEngine.Debug.Log ("Modifying Attribute Created");
        attribute = att;
        ratio = rat;
    }
}

Chủ Nhật, 2 tháng 2, 2014

Project RPG BÀI 10B. DỌN DẸP FILE ATTRIBUTE





Chuỗi bài viết dọn dẹp nhà cửa vì lo ăn tết nên post muộn :D


Double click vào file C# Attribute và xóa tất cả đi, chèn lại đoạn code sau vào:

 /// <summary>
/// This is the class for all of the chacracter attributes in-game
/// </summary>
public class Attribute : BaseStat {
    new public const int STARTING_EXP_COST = 50;    //this is the starting cost for all of the attributes
                  
    private string _name;                            //this is the name of the attribute

    /// <summary>
    /// Initializes a new instance of the <see cref="Attribute"/> class.
    /// </summary>
    public Attribute(){
        _name = "";                                  
        ExpToLevel = STARTING_EXP_COST;      
        LevelModifier = 1.05f;
    }

    /// <summary>
    /// Gets or sets the _name.
    /// </summary>
    /// <value>The name.</value>
    public string Name{
        get{return _name;}
        set{_name = value;}
    }
}

/// <summary>
/// A list of all attributes that we will have in-game for chacracters
/// </summary>
public enum AttributeName{
    Might,
    Constituion,
    Nimbleness,
    Speed,
    Concentration,
    Willpower,
    Charisma
}