Thứ Tư, 15 tháng 1, 2014

Project RPG BÀI 8. LƯU TRỮ NHÂN VẬT KHỞI TẠO


 Chúng ta sẽ tiếp tục công việc sau khi đã khởi tạo và thiết lập các thông số phù hợp nhân vật cho người chơi. Bước tiếp theo sẽ là lưu trữ thông tin của nhân vật mà người dùng đã thiết lập lại. Công việc lưu trữ này sẽ được thực hiện thông qua bằng Prefab (Kho chứa Game Object hoặc component có thể dùng lại nhiều lần) của Unity.



B1. Chắc rằng bạn đang mở Scene Character Generator (Tại thẻ Hierarchy chỉ bao gồm 1 Main Camera đã gắn script CharacterGenerator).





B2. Nhấp phải vào folder Script ở thẻ Project và chọn Create | C# Script và đặt tên là GameSettings.

B3. Double click vào file C# vừa tạo và chèn đoạn code sau vào:

using UnityEngine;
using System.Collections;
using System;

public class GameSettings : MonoBehaviour {

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

    public void SaveCharacterData(){
        GameObject pc =GameObject.Find("pc");

        PlayerCharacter pcClass = pc.GetComponent<PlayerCharacter>();

        PlayerPrefs.SetString("Player Name", pcClass.Name);
        PlayerPrefs.DeleteAll();

        for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++){
            PlayerPrefs.SetInt (((AttributeName)cnt).ToString() + " - Base Value", pcClass.GetPrimaryAttribute(cnt).BaseValue);
            PlayerPrefs.SetInt (((AttributeName)cnt).ToString() + " - EXP To Level", pcClass.GetPrimaryAttribute(cnt).ExpToLevel);
        }

        for(int cnt = 0; cnt < Enum.GetValues(typeof(VitalName)).Length; cnt++){
            PlayerPrefs.SetInt (((VitalName)cnt).ToString() + " - Base Value", pcClass.GetVital(cnt).BaseValue);
            PlayerPrefs.SetInt (((VitalName)cnt).ToString() + " - EXP To Level", pcClass.GetVital(cnt).ExpToLevel);
            PlayerPrefs.SetInt (((VitalName)cnt).ToString() + " - Cur Value", pcClass.GetVital(cnt).CurValue);

            PlayerPrefs.SetString(((VitalName)cnt).ToString() + " - Mobs", pcClass.GetVital(cnt).GetModifyingAttributesString());

        }
      
        for(int cnt = 0; cnt < Enum.GetValues(typeof(SkillName)).Length; cnt++){
            PlayerPrefs.SetInt(((SkillName)cnt).ToString() + " - Base Value", pcClass.GetSkill(cnt).BaseValue);
            PlayerPrefs.SetInt(((SkillName)cnt).ToString() + " - EXP To Level", pcClass.GetSkill(cnt).ExpToLevel);

            PlayerPrefs.SetString(((SkillName)cnt).ToString() + " - Mobs", pcClass.GetSkill(cnt).GetModifyingAttributesString());

        }
    }

    public void LoadCharacterDate(){

    }
}



B4. Vào GameObject | Create Empty và đặt tên lại thành __GameSettings. Kéo thả file C# vừa tạo vào __GameSettings ở thẻ Hierarchy.



B5. Tại thẻ Project, nhấp chọn nút Create | Folder và đặt tên là Prefabs.

B6. Vào GameObject | Create Empty. Tại thẻ Hierarchy, đổi tên GameObject vừa tạo thành Player Character.

B7. Vẫn đang chọn Player Character, qua thẻ Inspector, bấm vào hình bánh răng sau mục Transform và chọn Reset.

 

B8. Kéo thả file C# Player Character ở thẻ Project vào Player Character ở thẻ Hierarchy.

 

B9. Nhấp phải vào thư mục Prefabs ở thẻ Project và chọn Create | Prefab, đổi tên lại thành Player Character Prefab.

 

B10. Kéo thả Player Character ở thẻ Hierarchy vào prefab bạn vừa tạo ở thẻ Project.

 

B11. Xóa Player Character ở thẻ Hierarchy đi.

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

 using UnityEngine;
using System.Collections;
using System;                 //used for Enum class

public class CharacterGenerator : MonoBehaviour {
    private PlayerCharacter _toon;
    private const int STARTING_POINTS = 350;
    private const int MIN_STARTING_ATTRIBUTE_VALUE = 10;
    private const int STARTING_VALUE = 50;
    private int pointsLeft;

    private const int OFFSET = 5;
    private const int LINE_HEIGHT = 20;

    private const int STAT_LABEL_WIDTH = 100;
    private const int BASEVALUE_LABEL_WIDTH = 30;
    private const int BUTTON_WIDTH = 20;
    private const int BUTTON_HEIGHT = 20;

    private int statStartingPos = 40;

    public GUISkin mySkin;

    public GameObject playerPrefab;


    // Use this for initialization
    void Start () {
        GameObject pc = Instantiate(playerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
        pc.name = "pc";        //Player Character

        _toon = pc.GetComponent<PlayerCharacter>();

        pointsLeft = STARTING_POINTS;
        for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++){
            _toon.GetPrimaryAttribute(cnt).BaseValue = STARTING_VALUE;
            pointsLeft -= (STARTING_VALUE - MIN_STARTING_ATTRIBUTE_VALUE);
        }
        _toon.StatUpate();
    }
  
    // Update is called once per frame
    void Update () {
      //rotate camera to make the sky rotate.
      transform.Rotate(Vector3.up * Time.deltaTime * 3, Space.World);
    }

    void OnGUI(){
        GUI.skin = mySkin;
        DisplayName();
        DisplayPointsLeft();
        DisplayAttributes();
        DisplayVitals();
        DisplaySkills();
      
        if(_toon.Name == "" || pointsLeft > 0)
            DisplayCreateLabel();
        else
            DisplayCreateButton();
    }

    private void DisplayName(){
        GUI.Label(new Rect(10, 10, 50, 25),"Name:", GUI.skin.GetStyle("styleMiddle"));
        _toon.Name = GUI.TextField(new Rect(65, 10, 100, 25), _toon.Name );

    }

    private void DisplayAttributes(){
        for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++){
            GUI.Label(new Rect( OFFSET,                                    //x
                                statStartingPos + (cnt * LINE_HEIGHT),     //y
                                STAT_LABEL_WIDTH,                         //width
                                LINE_HEIGHT                                //height
                               ), ((AttributeName)cnt).ToString());
            GUI.Label(new Rect( STAT_LABEL_WIDTH + OFFSET,                 //x
                                statStartingPos + (cnt * LINE_HEIGHT),     //y
                                BASEVALUE_LABEL_WIDTH,                     //width
                                LINE_HEIGHT                                //height
                               ), _toon.GetPrimaryAttribute(cnt).AdjustedBaseValue.ToString(), GUI.skin.GetStyle("styleMiddle"));
            if(GUI.Button(new Rect( OFFSET + STAT_LABEL_WIDTH + BASEVALUE_LABEL_WIDTH,     //x
                                    statStartingPos + (cnt*BUTTON_HEIGHT),                 //y
                                   BUTTON_WIDTH,                                         //width
                                   BUTTON_HEIGHT                                        //height
                                   ),"-")){
                if(_toon.GetPrimaryAttribute(cnt).BaseValue > MIN_STARTING_ATTRIBUTE_VALUE){
                    _toon.GetPrimaryAttribute(cnt).BaseValue--;
                    pointsLeft++;
                    _toon.StatUpate();
                }
            }

            if(GUI.Button(new Rect( OFFSET + STAT_LABEL_WIDTH + BASEVALUE_LABEL_WIDTH + BUTTON_WIDTH,     //x
                                    statStartingPos + (cnt*BUTTON_HEIGHT),                                 //y
                                    BUTTON_WIDTH,                                                         //width
                                    BUTTON_HEIGHT                                                        //height
                                   ),"+")){
                if(pointsLeft > 0){
                    _toon.GetPrimaryAttribute(cnt).BaseValue++;
                    pointsLeft--;
                    _toon.StatUpate();
                }
            }
        }
    }

    private void DisplayVitals(){
        for(int cnt = 0; cnt < Enum.GetValues(typeof(VitalName)).Length; cnt++){
            GUI.Label(new Rect( OFFSET,                                             //x
                                statStartingPos + ((cnt + 7)* LINE_HEIGHT),         //y
                                STAT_LABEL_WIDTH,                                     //width
                                LINE_HEIGHT                                            //height
                               ), ((VitalName)cnt).ToString());
            GUI.Label(new Rect( OFFSET + STAT_LABEL_WIDTH,
                                statStartingPos + ((cnt + 7) * LINE_HEIGHT),
                                BASEVALUE_LABEL_WIDTH,
                                LINE_HEIGHT
                               ), _toon.GetVital(cnt).AdjustedBaseValue.ToString(),GUI.skin.GetStyle("styleMiddle"));
          
        }

    }

    private void DisplaySkills(){
        for(int cnt = 0; cnt < Enum.GetValues(typeof(SkillName)).Length; cnt++){
            GUI.Label(new Rect( OFFSET + STAT_LABEL_WIDTH + BASEVALUE_LABEL_WIDTH + BUTTON_WIDTH * 2 + OFFSET * 2,             //x
                                statStartingPos + (cnt * LINE_HEIGHT),                                                         //y
                                STAT_LABEL_WIDTH,                                                                             //width
                                LINE_HEIGHT                                                                                    //height
                               ), ((SkillName)cnt).ToString());
            GUI.Label(new Rect( OFFSET + STAT_LABEL_WIDTH + BASEVALUE_LABEL_WIDTH + BUTTON_WIDTH * 2 + OFFSET * 2 + STAT_LABEL_WIDTH,     //x
                                statStartingPos + (cnt * LINE_HEIGHT),                                                                     //y
                                BASEVALUE_LABEL_WIDTH,                                                                                     //width
                                LINE_HEIGHT                                                                                                //height
                               ), _toon.GetSkill(cnt).AdjustedBaseValue.ToString(),GUI.skin.GetStyle("styleMiddle"));
          
        }
      
    }

    private void DisplayPointsLeft(){
        GUI.Label(new Rect(250, 10, 100, 25), "Points Left: " + pointsLeft.ToString(),GUI.skin.GetStyle("styleMiddle"));

    }
    private void DisplayCreateLabel(){  
        GUI.Label(new Rect( Screen.width / 2 - 50, statStartingPos + (10 * LINE_HEIGHT), 100, LINE_HEIGHT), "Creating...", "Button");

    }
    private void DisplayCreateButton(){  
        if(    GUI.Button(new Rect( Screen.width / 2 - 50, statStartingPos + (10 * LINE_HEIGHT), 100, LINE_HEIGHT), "Create")){

            GameSettings gsScript = GameObject.Find ("__GameSettings").GetComponent<GameSettings>();

            //Change the cur value of the vitals to the max modified value of that vital
            UpdateCurVitalValues();

            //save the character data
            gsScript.SaveCharacterData();

            Application.LoadLevel("Targetting Example");
        }
    }

    private void UpdateCurVitalValues(){
        for(int cnt = 0; cnt < Enum.GetValues(typeof(VitalName)).Length; cnt++){
            _toon.GetVital(cnt).CurValue = _toon.GetVital(cnt).AdjustedBaseValue;
        }
    }

}


 B13. Tại thẻ Project, vào thư mục Scenes, đổi tên Targetting thành Targetting Example (Nếu không bạn có thể tại về tại đây).
Vào File | Build Settings. Kéo thả 2 Scene đang có trong thư mục Scene ở thẻ Project vào Scenes to build. Sau đó tắt hộp thoại này đi.

 

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

 public class Attribute : BaseStat {
    private string _name;

    public Attribute(){
        _name = "";
        ExpToLevel = 50;
        LevelModifier = 1.05f;
    }

    public string Name{
        get{return _name;}
        set{_name = value;}
    }
}

public enum AttributeName{
    Might,
    Constituion,
    Nimbleness,
    Speed,
    Concentration,
    Willpower,
    Charisma
}


B15. Double click vào file C# Vital và sửa ExptoLevel = 50 thành 40.

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

using System.Collections.Generic;

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

    public ModifiedStat(){
        _mods = new List<ModifyingAttribute>();
        _modValue = 0;
    }

    public void AddModifier( ModifyingAttribute mod ){
        _mods.Add(mod);
    }

    private void CalculateModValue(){
        _modValue = 0;

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

    public new int AdjustedBaseValue{
        get{ return BaseValue + BuffValue + _modValue; }
    }

    public void Update(){
        CalculateModValue();
    }

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

        //UnityEngine.Debug.Log(_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;
    }
}

public struct ModifyingAttribute{
    public Attribute attribute;
    public float ratio;

    public ModifyingAttribute(Attribute att, float rat){
        attribute = att;
        ratio = rat;
    }
}


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



using UnityEngine;
using System.Collections;
using System;                    //added to access the enum class

public class BaseCharacter : MonoBehaviour {
    private string _name;
    private int _level;
    private uint _freeExp;

    private Attribute[] _primaryAttribute;
    private Vital[] _vital;
    private Skill[] _skill;

    public void Awake(){
        _name = string.Empty;
        _level = 0;
        _freeExp = 0;

        _primaryAttribute = new Attribute[Enum.GetValues(typeof(AttributeName)).Length];
        _vital = new Vital[Enum.GetValues(typeof(VitalName)).Length];
        _skill = new Skill[Enum.GetValues(typeof(SkillName)).Length];

        SetupPrimaryAttributes();
        SetupVitals();
        SetupSkills();
    }

    public string Name{
        get{ return _name;}
        set{ _name = value;}
    }
    public int Level{
        get{ return _level;}
        set{ _level = value;}
    }
    public uint FreeExp{
        get{ return _freeExp;}
        set{ _freeExp = value;}
    }
      
    public void AddExp(uint exp){
        _freeExp += exp;

        CalculateLevel();
    }

    //take avg of all of the players skills and assign that as the player lv
    public void CalculateLevel(){

    }

    private void SetupPrimaryAttributes(){
        for(int cnt = 0; cnt < _primaryAttribute.Length; cnt++){
            _primaryAttribute[cnt] = new Attribute();
            _primaryAttribute[cnt].Name = ((AttributeName)cnt).ToString();
        }
    }
    private void SetupVitals(){
        for(int cnt = 0; cnt < _vital.Length; cnt++)
            _vital[cnt] = new Vital();

        SetupVitalModifiers();
      
    }
    private void SetupSkills(){
        for(int cnt = 0; cnt < _skill.Length; cnt++)
            _skill[cnt] = new Skill();

        SetupSkillModifiers();
      
    }

    public Attribute GetPrimaryAttribute(int index){
        return _primaryAttribute[index];
    }

    public Vital GetVital(int index){
        return _vital[index];
    }

    public Skill GetSkill(int index){
        return _skill[index];
  
    }
    private void SetupVitalModifiers(){
        //health
        GetVital((int)VitalName.Health).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Constituion), .5f));
        //energy
        GetVital((int)VitalName.Energy).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Constituion), 1));
        //mana
        GetVital((int)VitalName.Mana).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Willpower), 1));

    }
    private void SetupSkillModifiers(){
        //melee offence
        GetSkill((int)SkillName.Melee_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Might), .33f));
        GetSkill((int)SkillName.Melee_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Nimbleness), .33f));
        //melee defence
        GetSkill((int)SkillName.Melee_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Speed), .33f));
        GetSkill((int)SkillName.Melee_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Constituion), .33f));
        //magic offence
        GetSkill((int)SkillName.Magic_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Concentration), .33f));
        GetSkill((int)SkillName.Magic_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Willpower), .33f));
        //magic defence
        GetSkill((int)SkillName.Magic_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Concentration), .33f));
        GetSkill((int)SkillName.Magic_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Willpower), .33f));
        //ranged offence
        GetSkill((int)SkillName.Ranged_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Concentration), .33f));
        GetSkill((int)SkillName.Ranged_Offence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Speed), .33f));
        //ranged defence
        GetSkill((int)SkillName.Ranged_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Speed), .33f));
        GetSkill((int)SkillName.Ranged_Defence).AddModifier(new ModifyingAttribute(GetPrimaryAttribute((int)AttributeName.Nimbleness), .33f));
    }

    public void StatUpate(){
        for(int cnt = 0; cnt < _vital.Length; cnt++)
            _vital[cnt].Update();
        for(int cnt = 0; cnt < _skill.Length; cnt++)
            _skill[cnt].Update();
    }
}


B18. Nhấp chọn Main Camera, kéo thả Player Character Prefab ở thư mục Prefabs vào Player Prefab ở thẻ Inspector như hình sau:


B19. Để biết dữ liệu được lưu trữ ở đâu mời bạn tham khảo tại trang tài liệu của Unity bên dưới:
http://docs.unity3d.com/Documentation/ScriptReference/PlayerPrefs.html

B20. Save Scene Character Generator lại và ấn nút Play để kiểm tra thành quả!!

Không có nhận xét nào:

Đăng nhận xét