unity卡牌游戏开发记录(4)

咕咕咕,鸽了好久,今天来继续我们的游戏开发

今天实现的内容是把卡牌加入卡组,从文件读取卡组,从卡组删除卡牌,把卡组保存到文件中。

---------------------------------------------------分割线---------------------------------------------------------------------

首先是卡牌加入卡组。上一期我们实现了加载所有卡牌列表,现在我想要点击某张卡牌时它能够加入到卡组中。那么我们先新建一个卡组ui,用来显示卡组中的卡牌。

大概这样。我们需要卡牌按一定的规则排列好,方便检查卡组,所以在卡组对象下挂一个空对象,给它加一个Grid Layout Group组件,这样可以让它的子对象以表格的显示显示。

约束计数就是一行放多少个子对象。上面的数据自己看着填就行。

接下来要做的事情很简单:点击卡牌列表的卡牌时,新建一个子对象挂在deck_parent上。首先我们把card_inlist预制体复制一下,后面还得做个卡组中的卡牌。因为需要增加点击事件,所以在预制体中增加一个空对象,在上面挂一个脚本,脚本里写一个public的函数,然后给预制体增加点击事件,把这个空对象放到点击事件中,右侧选择刚刚写的函数即可。我写的函数名字是PushCard

可以在PushCard函数中写个debug测试一下能不能正常触发事件。

思考一下,我们要往卡组里增加卡牌,如何表示卡组中的卡牌数量呢,有两种方法,一是有多少张就显示多少张,二是在卡牌上显示一个数字,表示卡组里面的这张卡牌已经有多少张了。为了方便,我选择了第二种。因此,我们要用到刚刚复制出来的预制体。

把复制出来的预制体改名为Card_indeck,表示这个卡牌预制体是用来在卡组中显示的。给它添加一个新的空对象名为nums,方便管理卡牌数量。其实在随便一个预制体的脚本增加一个public的变量也行,只要会调用就行。在nums下面挂一个text组件,用来存储和显示数量。

接下来回到PushCard函数,首先获取所有卡牌列表,方便添加卡牌到卡组中。然后获取卡组当前卡牌列表,如果点击的卡牌的id不存在于卡组中,那么新建一个卡牌对象放入卡组;如果存在,就传入id,调用Card_indeck的脚本把对应id的卡牌的nums加一。(这个函数等下讲)

 public void PushCard()
 {
     Cardlist = GameObject.Find("parent").GetComponent<showcard>().card_informations_list;
     //把卡牌加入卡组,按下按钮后再保存

     //Debug.Log(transform);
     //Debug.Log("PushCard");
     //首先读取DeckScript的卡牌列表
     int id = transform.parent.GetComponent<saveCardInformation>().id;//踩坑,这个脚本放在了子物体上,导致一开始找不到指定的脚本
     
     if (GameObject.Find("deck_parent").GetComponent<DeckScript>().deck[id] != null)
     {
         //获取卡牌数量,转为int类型然后加一
         string nums_string = GameObject.Find("deck_parent").GetComponent<DeckScript>().deck[id].transform.Find("nums").GetComponent<TextMeshProUGUI>().text;
         int.TryParse(nums_string, out int nums);
         nums++;
         GameObject.Find("deck_parent").GetComponent<DeckScript>().deck[id].transform.Find("nums").GetComponent<TextMeshProUGUI>().text=nums.ToString();
     }
     else
     {
         //如果当前卡组没有这张卡牌,调用函数新建卡牌
         GameObject.Find("deck_parent").GetComponent<DeckScript>().AddToParent(id,Cardlist,true);
     }

 }

好了,让我们回到卡组。为了读取卡组文件,在deck对象下挂一个脚本,读取卡组文件并生成卡牌显示在卡组框中。

private int[] Cards=new int[100];//下标就是卡牌编号,数组数字就是下标id的卡牌的数量
public TextAsset DeckText;//卡组文件
public GameObject card_indeck;//卡组卡牌预制件
public GameObject[] deck;//卡组卡牌数组

首先是读取文件。这里我用的是public的textassest变量,可以在unity中把文本文件放到上面。根据逗号来分割每一行的内容。卡组文件只需要存储id和数量num就行。csv文件最后有一个回车,如果读取到最后一行,说明item的长度是0,直接跳过。id和num已经存入数组Cards,可以在其他函数直接调用。

void GetDeckFile()
{
    //string path_root = Directory.GetCurrentDirectory()+ "/Assets/deck/deck.csv";
    string[] datarow = DeckText.text.Split("n");
    foreach (var item in datarow)
    {
        if (item.Length == 0)
        {
            continue;
        }
        string[] carddata = item.Split(',');
        if (carddata[0] == "id")
        {
            continue;
        }

        int.TryParse(carddata[0], out int id);
        int.TryParse(carddata[1], out int num);

        Cards[id] = num;
    }
}

然后是把刚刚拿到的数组变成ui显示出来,函数根据id来读取之前初始化好的卡牌列表,把每一张卡牌的信息存入实例化的卡牌中,这样子就可以让卡牌信息显示出来。其中的bool isadd用来判断是添加卡牌还是卡牌数量加一。添加卡牌就是上面写的,点击卡牌往卡组添加。

void LoadDeck()
{
    //先读取所有卡牌的文件
    List<Card_information> Cardlist = new();
    Cardlist = GameObject.Find("parent").GetComponent<showcard>().card_informations_list;
    //遍历卡组列表
    for (int id = 1; id < Cards.Length; id++)
    {
        //如果卡牌数量为0则不显示
        if (Cards[id] == 0)
        {
            continue;
        }
        //生成卡牌并作为子对象放在deck下
        AddToParent(id, Cardlist,false);
    }
}
 //把卡牌显示在卡组中额外写一个函数,方便其他脚本调用
 public void AddToParent(int id, List<Card_information> Cardlist,bool IsAdd)
 {
     
     GameObject a = Instantiate(card_indeck, transform.position, Quaternion.identity);//实例化物体
     a.transform.Find("name").GetComponent<TextMeshProUGUI>().text = Cardlist[id - 1].name;
     a.transform.Find("attack").GetComponent<TextMeshProUGUI>().text = Cardlist[id - 1].attack.ToString();
     a.transform.Find("defense").GetComponent<TextMeshProUGUI>().text = Cardlist[id - 1].defense.ToString();
     a.transform.Find("fakang").GetComponent<TextMeshProUGUI>().text = Cardlist[id - 1].fakang.ToString();
     a.transform.Find("health").GetComponent<TextMeshProUGUI>().text = Cardlist[id - 1].health.ToString();
     a.transform.Find("Character_image").GetComponent<Image>().sprite = Cardlist[id - 1].Character.sprite;//因为cardlist是从零开始,所以减一
     if(IsAdd)
     {
         Cards[id]++;
     }
     a.transform.Find("nums").GetComponent<TextMeshProUGUI>().text = Cards[id].ToString();
     a.transform.parent = this.transform;
     //把实例化的物体加入数组,方便修改
     //UnityEngine.Debug.Log(deck.Length);
     deck[id] = a;
     
     Saveinformation(a, Cardlist[id - 1].id, Cardlist[id - 1].cost, Cardlist[id - 1].name, Cardlist[id - 1].attack, Cardlist[id - 1].defense, Cardlist[id - 1].health, Cardlist[id - 1].fakang, Cardlist[id - 1].birth, Cardlist[id - 1].career, Cardlist[id - 1].force, Cardlist[id - 1].race, Cardlist[id - 1].description, Cardlist[id - 1].Character);
 }
//用来保存卡牌信息,方便显示
void Saveinformation(GameObject a, int _id, int _cost, string _name, double _attack, double _defense, float _health, double _fakang, string _birth, string _career, string _force, string _race, string _des, UnityEngine.UI.Image _ch)
{
    a.GetComponent<saveCardInformation>().id = _id;
    a.GetComponent<saveCardInformation>().cost = _cost;
    a.GetComponent<saveCardInformation>().cardname = _name;
    a.GetComponent<saveCardInformation>().attack = _attack;
    a.GetComponent<saveCardInformation>().defense = _defense;
    a.GetComponent<saveCardInformation>().health = _health;
    a.GetComponent<saveCardInformation>().fakang = _fakang;
    a.GetComponent<saveCardInformation>().birth = _birth;
    a.GetComponent<saveCardInformation>().career = _career;
    a.GetComponent<saveCardInformation>().force = _force;
    a.GetComponent<saveCardInformation>().race = _race;
    a.GetComponent<saveCardInformation>().description = _des;
    a.GetComponent<saveCardInformation>().Character = _ch;
}
   

然后是删除卡牌,这个很简单,点击卡组中的卡牌触发删除函数,num-1,如果num=0,就销毁卡牌实例。随便在卡牌的脚本中写一个简单的销毁函数。

public void deleteself()
{
    Destroy(gameObject);
}

如法炮制,给卡组的卡牌弄一个删除按钮函数

public void DeleteButton()
{
    Debug.Log(transform.parent);
    string num=transform.parent.Find("nums").GetComponent<TextMeshProUGUI>().text;
    int.TryParse(num, out int num_int);
    num_int--;
    if(num_int == 0)
    {
        transform.parent.GetComponent<show_in_deckedit>().deleteself();
    }
    else
    {
        transform.parent.Find("nums").GetComponent<TextMeshProUGUI>().text=num_int.ToString();
    }
}

最后就是保存卡组。

public void SaveDeckFuntion()
{
    //根据tag获取卡组中的卡牌对象
    GameObject[] CardDeckList = GameObject.FindGameObjectsWithTag("CardInDeck");
    using (StreamWriter sw = new(@"Assetsdeckdeck.csv"))
    {
        foreach (GameObject card in CardDeckList)
        {
            //获取每一张卡牌的id和nums
            string num_str = card.transform.Find("nums").GetComponent<TextMeshProUGUI>().text;
            int id = card.transform.GetComponent<saveCardInformation>().id;


            //把id和nums写入csv文件
            string csv_str = id.ToString() + "," + num_str;
            sw.WriteLine(csv_str);
        }

    }
    
}

至此,卡组编辑界面已经差不多完成。检索卡牌还没做,以后有机会再实现吧。接下来就是实现战斗了。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇

)">
下一篇>>