إنشاء نظام جرد وصياغة العناصر في الوحدة

في هذا البرنامج التعليمي، سأوضح كيفية إنشاء نظام Minecraft-style للمخزون وصياغة العناصر في Unity.

إن صناعة العناصر في ألعاب الفيديو هي عملية دمج عناصر محددة (عادةً ما تكون أبسط) في عناصر أكثر تعقيدًا، مع خصائص جديدة ومحسنة. على سبيل المثال، الجمع بين الخشب والحجر في معول، أو الجمع بين الصفائح المعدنية والخشب في السيف.

نظام الصياغة أدناه متوافق مع الهاتف المحمول ومؤتمت بالكامل، مما يعني أنه سيعمل مع أي تخطيط واجهة المستخدم ومع القدرة على إنشاء وصفات صياغة مخصصة.

Sharp Coder مشغل فديوهات

الخطوة 1: إعداد واجهة المستخدم الخاصة بالصياغة

نبدأ بإعداد واجهة المستخدم الخاصة بالصياغة:

  • قم بإنشاء لوحة قماشية جديدة (Unity شريط المهام العلوي: GameObject -> UI -> Canvas)
  • قم بإنشاء صورة جديدة عن طريق النقر بزر الماوس الأيمن على كائن قماش -> واجهة المستخدم -> الصورة
  • أعد تسمية كائن الصورة إلى "CraftingPanel" وقم بتغيير الصورة المصدر الخاصة به إلى الوضع الافتراضي "UISprite"
  • قم بتغيير قيم "CraftingPanel" RectTransform إلى (Pos X: 0 Pos Y: 0 Width: 410 Height: 365)

  • قم بإنشاء كائنين داخل "CraftingPanel" (انقر بزر الماوس الأيمن على CraftingPanel -> إنشاء فارغ، مرتين)
  • أعد تسمية الكائن الأول إلى "CraftingSlots" وقم بتغيير قيم RectTransform الخاصة به إلى ("محاذاة أعلى اليسار" Pivot X: 0 Pivot Y: 1 Pos X: 50 Pos Y: -35 Width: 140 Height: 140). سيحتوي هذا الكائن على فتحات تصنيع.
  • أعد تسمية الكائن الثاني إلى "PlayerSlots" وقم بتغيير قيم RectTransform الخاصة به إلى ("Top Stretch Horizontally" Pivot X: 0.5 Pivot Y: 1 Left: 0 Pos Y: -222 Right: 0 Height: 100). سيحتوي هذا الكائن على فتحات اللاعب.

عنوان القسم:

  • أنشئ نصًا جديدًا بالنقر بزر الماوس الأيمن على "PlayerSlots" Object -> UI -> Text وأعد تسميته إلى "SectionTitle"
  • قم بتغيير قيم "SectionTitle" RectTransform إلى ("محاذاة أعلى اليسار" المحور X: 0 المحور Y: 0 Pos X: 5 Pos Y: 0 Width: 160 الارتفاع: 30)
  • قم بتغيير النص "SectionTitle" إلى "Inventory" وقم بتعيين حجم الخط إلى 18، والمحاذاة إلى اليسار الأوسط، واللون إلى (0.2، 0.2، 0.2، 1)
  • قم بتكرار الكائن "SectionTitle"، وقم بتغيير النص الخاص به إلى "Crafting" وانقله أسفل الكائن "CraftingSlots"، ثم قم بتعيين نفس قيم RectTransform مثل "SectionTitle" السابقة.

فتحة الصياغة:

ستتكون فتحة الصياغة من صورة خلفية وصورة عنصر ونص عدد:

  • قم بإنشاء صورة جديدة عن طريق النقر بزر الماوس الأيمن على كائن قماش -> واجهة المستخدم -> الصورة
  • أعد تسمية الصورة الجديدة إلى "slot_template"، واضبط قيم RectTransform الخاصة بها على (Post X: 0 Pos Y: 0 Width: 40 Height: 40)، وقم بتغيير لونها إلى (0.32، 0.32، 0.32، 0.8)
  • انسخ "slot_template" وأعد تسميته إلى "Item"، وانقله داخل الكائن "slot_template"، وقم بتغيير أبعاد RectTransform إلى (Width: 30 Height: 30) واللون إلى (1، 1، 1، 1)
  • أنشئ نصًا جديدًا بالنقر بزر الماوس الأيمن على "slot_template" Object -> UI -> Text وأعد تسميته إلى "Count"
  • قم بتغيير قيم "Count" RectTransform إلى ("محاذاة أسفل اليمين" المحور X: 1 المحور Y: 0 Pos X: 0 Pos Y: 0 Width: 30 الارتفاع: 30)
  • اضبط "Count" النص على رقم عشوائي (مثال 12)، ونمط الخط على غامق، وحجم الخط على 14، والمحاذاة إلى أسفل اليمين، واللون على (1، 1، 1، 1)
  • أضف مكون الظل إلى النص "Count" واضبط لون التأثير على (0، 0، 0، 0.5)

يجب أن تبدو النتيجة النهائية كما يلي:

فتحة النتيجة (التي سيتم استخدامها لصياغة النتائج):

  • قم بتكرار الكائن "slot_template" وأعد تسميته إلى "result_slot_template"
  • قم بتغيير العرض والارتفاع "result_slot_template" إلى 50

زر صياغة ورسومات إضافية:

  • أنشئ زرًا جديدًا بالنقر بزر الماوس الأيمن على "CraftingSlots" Object -> UI -> Button وأعد تسميته إلى "CraftButton"
  • اضبط قيم "CraftButton" RectTransform على ("محاذاة اليسار الأوسط" Pivot X: 1 Pivot Y: 0.5 Pos X: 0 Pos Y: 0 Width: 40 الارتفاع: 40)
  • قم بتغيير نص "CraftButton" إلى "Craft"

  • أنشئ صورة جديدة بالنقر بزر الماوس الأيمن على "CraftingSlots" Object -> UI -> Image وأعد تسميتها إلى "Arrow"
  • اضبط قيم "Arrow" RectTransform على ("محاذاة اليمين الأوسط" Pivot X: 0 Pivot Y: 0.5 Pos X: 10 Pos Y: 0 Width: 30 Height: 30)

بالنسبة للصورة المصدر، يمكنك استخدام الصورة أدناه (انقر بزر الماوس الأيمن -> حفظ باسم.. لتنزيلها). بعد الاستيراد، اضبط نوع المادة على "Sprite (2D and UI)" ووضع التصفية على "Point (no filter)"

سهم لليمين أيقونة بكسل

  • انقر بزر الماوس الأيمن على "CraftingSlots" -> إنشاء فارغ وأعد تسميته إلى "ResultSlot"، سيحتوي هذا الكائن على فتحة النتيجة
  • اضبط قيم "ResultSlot" RectTransform على ("محاذاة اليمين الأوسط" Pivot X: 0 Pivot Y: 0.5 Pos X: 50 Pos Y: 0 Width: 50 Height: 50)

إعداد واجهة المستخدم جاهز.

الخطوة 2: نظام صياغة البرنامج

سيتكون نظام التصنيع هذا من نصين، SC_ItemCrafting.cs وSC_SlotTemplate.cs

  • قم بإنشاء سكريبت جديد، وقم بتسميته "SC_ItemCrafting" ثم الصق الكود أدناه داخله:

SC_ItemCrafting.cs

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

public class SC_ItemCrafting : MonoBehaviour
{
    public RectTransform playerSlotsContainer;
    public RectTransform craftingSlotsContainer;
    public RectTransform resultSlotContainer;
    public Button craftButton;
    public SC_SlotTemplate slotTemplate;
    public SC_SlotTemplate resultSlotTemplate;

    [System.Serializable]
    public class SlotContainer
    {
        public Sprite itemSprite; //Sprite of the assigned item (Must be the same sprite as in items array), or leave null for no item
        public int itemCount; //How many items in this slot, everything equal or under 1 will be interpreted as 1 item
        [HideInInspector]
        public int tableID;
        [HideInInspector]
        public SC_SlotTemplate slot;
    }

    [System.Serializable]
    public class Item
    {
        public Sprite itemSprite;
        public bool stackable = false; //Can this item be combined (stacked) together?
        public string craftRecipe; //Item Keys that are required to craft this item, separated by comma (Tip: Use Craft Button in Play mode and see console for printed recipe)
    }

    public SlotContainer[] playerSlots;
    SlotContainer[] craftSlots = new SlotContainer[9];
    SlotContainer resultSlot = new SlotContainer();
    //List of all available items
    public Item[] items;

    SlotContainer selectedItemSlot = null;

    int craftTableID = -1; //ID of table where items will be placed one at a time (ex. Craft table)
    int resultTableID = -1; //ID of table from where we can take items, but cannot place to

    ColorBlock defaultButtonColors;

    // Start is called before the first frame update
    void Start()
    {
        //Setup slot element template
        slotTemplate.container.rectTransform.pivot = new Vector2(0, 1);
        slotTemplate.container.rectTransform.anchorMax = slotTemplate.container.rectTransform.anchorMin = new Vector2(0, 1);
        slotTemplate.craftingController = this;
        slotTemplate.gameObject.SetActive(false);
        //Setup result slot element template
        resultSlotTemplate.container.rectTransform.pivot = new Vector2(0, 1);
        resultSlotTemplate.container.rectTransform.anchorMax = resultSlotTemplate.container.rectTransform.anchorMin = new Vector2(0, 1);
        resultSlotTemplate.craftingController = this;
        resultSlotTemplate.gameObject.SetActive(false);

        //Attach click event to craft button
        craftButton.onClick.AddListener(PerformCrafting);
        //Save craft button default colors
        defaultButtonColors = craftButton.colors;

        //InitializeItem Crafting Slots
        InitializeSlotTable(craftingSlotsContainer, slotTemplate, craftSlots, 5, 0);
        UpdateItems(craftSlots);
        craftTableID = 0;

        //InitializeItem Player Slots
        InitializeSlotTable(playerSlotsContainer, slotTemplate, playerSlots, 5, 1);
        UpdateItems(playerSlots);

        //InitializeItemResult Slot
        InitializeSlotTable(resultSlotContainer, resultSlotTemplate, new SlotContainer[] { resultSlot }, 0, 2);
        UpdateItems(new SlotContainer[] { resultSlot });
        resultTableID = 2;

        //Reset Slot element template (To be used later for hovering element)
        slotTemplate.container.rectTransform.pivot = new Vector2(0.5f, 0.5f);
        slotTemplate.container.raycastTarget = slotTemplate.item.raycastTarget = slotTemplate.count.raycastTarget = false;
    }

    void InitializeSlotTable(RectTransform container, SC_SlotTemplate slotTemplateTmp, SlotContainer[] slots, int margin, int tableIDTmp)
    {
        int resetIndex = 0;
        int rowTmp = 0;
        for (int i = 0; i < slots.Length; i++)
        {
            if (slots[i] == null)
            {
                slots[i] = new SlotContainer();
            }
            GameObject newSlot = Instantiate(slotTemplateTmp.gameObject, container.transform);
            slots[i].slot = newSlot.GetComponent<SC_SlotTemplate>();
            slots[i].slot.gameObject.SetActive(true);
            slots[i].tableID = tableIDTmp;

            float xTmp = (int)((margin + slots[i].slot.container.rectTransform.sizeDelta.x) * (i - resetIndex));
            if (xTmp + slots[i].slot.container.rectTransform.sizeDelta.x + margin > container.rect.width)
            {
                resetIndex = i;
                rowTmp++;
                xTmp = 0;
            }
            slots[i].slot.container.rectTransform.anchoredPosition = new Vector2(margin + xTmp, -margin - ((margin + slots[i].slot.container.rectTransform.sizeDelta.y) * rowTmp));
        }
    }

    //Update Table UI
    void UpdateItems(SlotContainer[] slots)
    {
        for (int i = 0; i < slots.Length; i++)
        {
            Item slotItem = FindItem(slots[i].itemSprite);
            if (slotItem != null)
            {
                if (!slotItem.stackable)
                {
                    slots[i].itemCount = 1;
                }
                //Apply total item count
                if (slots[i].itemCount > 1)
                {
                    slots[i].slot.count.enabled = true;
                    slots[i].slot.count.text = slots[i].itemCount.ToString();
                }
                else
                {
                    slots[i].slot.count.enabled = false;
                }
                //Apply item icon
                slots[i].slot.item.enabled = true;
                slots[i].slot.item.sprite = slotItem.itemSprite;
            }
            else
            {
                slots[i].slot.count.enabled = false;
                slots[i].slot.item.enabled = false;
            }
        }
    }

    //Find Item from the items list using sprite as reference
    Item FindItem(Sprite sprite)
    {
        if (!sprite)
            return null;

        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].itemSprite == sprite)
            {
                return items[i];
            }
        }

        return null;
    }

    //Find Item from the items list using recipe as reference
    Item FindItem(string recipe)
    {
        if (recipe == "")
            return null;

        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].craftRecipe == recipe)
            {
                return items[i];
            }
        }

        return null;
    }

    //Called from SC_SlotTemplate.cs
    public void ClickEventRecheck()
    {
        if (selectedItemSlot == null)
        {
            //Get clicked slot
            selectedItemSlot = GetClickedSlot();
            if (selectedItemSlot != null)
            {
                if (selectedItemSlot.itemSprite != null)
                {
                    selectedItemSlot.slot.count.color = selectedItemSlot.slot.item.color = new Color(1, 1, 1, 0.5f);
                }
                else
                {
                    selectedItemSlot = null;
                }
            }
        }
        else
        {
            SlotContainer newClickedSlot = GetClickedSlot();
            if (newClickedSlot != null)
            {
                bool swapPositions = false;
                bool releaseClick = true;

                if (newClickedSlot != selectedItemSlot)
                {
                    //We clicked on the same table but different slots
                    if (newClickedSlot.tableID == selectedItemSlot.tableID)
                    {
                        //Check if new clicked item is the same, then stack, if not, swap (Unless it's a crafting table, then do nothing)
                        if (newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                        {
                            Item slotItem = FindItem(selectedItemSlot.itemSprite);
                            if (slotItem.stackable)
                            {
                                //Item is the same and is stackable, remove item from previous position and add its count to a new position
                                selectedItemSlot.itemSprite = null;
                                newClickedSlot.itemCount += selectedItemSlot.itemCount;
                                selectedItemSlot.itemCount = 0;
                            }
                            else
                            {
                                swapPositions = true;
                            }
                        }
                        else
                        {
                            swapPositions = true;
                        }
                    }
                    else
                    {
                        //Moving to different table
                        if (resultTableID != newClickedSlot.tableID)
                        {
                            if (craftTableID != newClickedSlot.tableID)
                            {
                                if (newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                                {
                                    Item slotItem = FindItem(selectedItemSlot.itemSprite);
                                    if (slotItem.stackable)
                                    {
                                        //Item is the same and is stackable, remove item from previous position and add its count to a new position
                                        selectedItemSlot.itemSprite = null;
                                        newClickedSlot.itemCount += selectedItemSlot.itemCount;
                                        selectedItemSlot.itemCount = 0;
                                    }
                                    else
                                    {
                                        swapPositions = true;
                                    }
                                }
                                else
                                {
                                    swapPositions = true;
                                }
                            }
                            else
                            {
                                if (newClickedSlot.itemSprite == null || newClickedSlot.itemSprite == selectedItemSlot.itemSprite)
                                {
                                    //Add 1 item from selectedItemSlot
                                    newClickedSlot.itemSprite = selectedItemSlot.itemSprite;
                                    newClickedSlot.itemCount++;
                                    selectedItemSlot.itemCount--;
                                    if (selectedItemSlot.itemCount <= 0)
                                    {
                                        //We placed the last item
                                        selectedItemSlot.itemSprite = null;
                                    }
                                    else
                                    {
                                        releaseClick = false;
                                    }
                                }
                                else
                                {
                                    swapPositions = true;
                                }
                            }
                        }
                    }
                }

                if (swapPositions)
                {
                    //Swap items
                    Sprite previousItemSprite = selectedItemSlot.itemSprite;
                    int previousItemConunt = selectedItemSlot.itemCount;

                    selectedItemSlot.itemSprite = newClickedSlot.itemSprite;
                    selectedItemSlot.itemCount = newClickedSlot.itemCount;

                    newClickedSlot.itemSprite = previousItemSprite;
                    newClickedSlot.itemCount = previousItemConunt;
                }

                if (releaseClick)
                {
                    //Release click
                    selectedItemSlot.slot.count.color = selectedItemSlot.slot.item.color = Color.white;
                    selectedItemSlot = null;
                }

                //Update UI
                UpdateItems(playerSlots);
                UpdateItems(craftSlots);
                UpdateItems(new SlotContainer[] { resultSlot });
            }
        }
    }

    SlotContainer GetClickedSlot()
    {
        for (int i = 0; i < playerSlots.Length; i++)
        {
            if (playerSlots[i].slot.hasClicked)
            {
                playerSlots[i].slot.hasClicked = false;
                return playerSlots[i];
            }
        }

        for (int i = 0; i < craftSlots.Length; i++)
        {
            if (craftSlots[i].slot.hasClicked)
            {
                craftSlots[i].slot.hasClicked = false;
                return craftSlots[i];
            }
        }

        if (resultSlot.slot.hasClicked)
        {
            resultSlot.slot.hasClicked = false;
            return resultSlot;
        }

        return null;
    }

    void PerformCrafting()
    {
        string[] combinedItemRecipe = new string[craftSlots.Length];

        craftButton.colors = defaultButtonColors;

        for (int i = 0; i < craftSlots.Length; i++)
        {
            Item slotItem = FindItem(craftSlots[i].itemSprite);
            if (slotItem != null)
            {
                combinedItemRecipe[i] = slotItem.itemSprite.name + (craftSlots[i].itemCount > 1 ? "(" + craftSlots[i].itemCount + ")" : "");
            }
            else
            {
                combinedItemRecipe[i] = "";
            }
        }

        string combinedRecipe = string.Join(",", combinedItemRecipe);
        print(combinedRecipe);

        //Search if recipe match any of the item recipe
        Item craftedItem = FindItem(combinedRecipe);
        if (craftedItem != null)
        {
            //Clear Craft slots
            for (int i = 0; i < craftSlots.Length; i++)
            {
                craftSlots[i].itemSprite = null;
                craftSlots[i].itemCount = 0;
            }

            resultSlot.itemSprite = craftedItem.itemSprite;
            resultSlot.itemCount = 1;

            UpdateItems(craftSlots);
            UpdateItems(new SlotContainer[] { resultSlot });
        }
        else
        {
            ColorBlock colors = craftButton.colors;
            colors.selectedColor = colors.pressedColor = new Color(0.8f, 0.55f, 0.55f, 1);
            craftButton.colors = colors;
        }
    }

    // Update is called once per frame
    void Update()
    {
        //Slot UI follow mouse position
        if (selectedItemSlot != null)
        {
            if (!slotTemplate.gameObject.activeSelf)
            {
                slotTemplate.gameObject.SetActive(true);
                slotTemplate.container.enabled = false;

                //Copy selected item values to slot template
                slotTemplate.count.color = selectedItemSlot.slot.count.color;
                slotTemplate.item.sprite = selectedItemSlot.slot.item.sprite;
                slotTemplate.item.color = selectedItemSlot.slot.item.color;
            }

            //Make template slot follow mouse position
            slotTemplate.container.rectTransform.position = Input.mousePosition;
            //Update item count
            slotTemplate.count.text = selectedItemSlot.slot.count.text;
            slotTemplate.count.enabled = selectedItemSlot.slot.count.enabled;
        }
        else
        {
            if (slotTemplate.gameObject.activeSelf)
            {
                slotTemplate.gameObject.SetActive(false);
            }
        }
    }
}
  • أنشئ سكريبت جديد وسميه "SC_SlotTemplate" ثم الصق الكود أدناه بداخله:

SC_SlotTemplate.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class SC_SlotTemplate : MonoBehaviour, IPointerClickHandler
{
    public Image container;
    public Image item;
    public Text count;

    [HideInInspector]
    public bool hasClicked = false;
    [HideInInspector]
    public SC_ItemCrafting craftingController;

    //Do this when the mouse is clicked over the selectable object this script is attached to.
    public void OnPointerClick(PointerEventData eventData)
    {
        hasClicked = true;
        craftingController.ClickEventRecheck();
    }
}

إعداد قوالب الفتحات:

  • قم بإرفاق البرنامج النصي SC_SlotTemplate بالكائن "slot_template"، وتعيين متغيراته (ينتقل مكون الصورة في نفس الكائن إلى المتغير "Container"، والطفل "Item" ينتقل الصورة إلى المتغير "Item"، والطفل "Count" ينتقل النص إلى المتغير "Count")
  • كرر نفس العملية للكائن "result_slot_template" (أرفق البرنامج النصي SC_SlotTemplate به وقم بتعيين المتغيرات بنفس الطريقة).

تجهيز النظام الحرفي:

  • قم بإرفاق البرنامج النصي SC_ItemCrafting بكائن Canvas، وتعيين متغيراته (ينتقل كائن "PlayerSlots" إلى المتغير "Player Slots Container"، وينتقل الكائن "CraftingSlots" إلى المتغير "Crafting Slots Container"، وينتقل الكائن "ResultSlot" إلى المتغير *h51) * متغير، "CraftButton" يذهب الكائن إلى "Craft Button" متغير، "slot_template" كائن مع البرنامج النصي SC_SlotTemplate المرفق يذهب إلى "Slot Template" متغير و "result_slot_template" كائن مع البرنامج النصي SC_SlotTemplate المرفق يذهب إلى "Result Slot Template" متغير):

كما لاحظت بالفعل، هناك مصفوفتان فارغتان باسم "Player Slots" و "Items". ستحتوي "Player Slots" على عدد الفتحات المتاحة (مع العنصر أو الفارغة) وستحتوي "Items" على جميع العناصر المتاحة بالإضافة إلى الوصفات الخاصة بها (اختياري).

إعداد العناصر:

تحقق من النقوش المتحركة أدناه (في حالتي سيكون لدي 5 عناصر):

البند روك (صخر)

البند الماسي (الماس)

البند الخشب (خشب)

عنصر السيف (سيف)

السيف الألماسي (السيف الألماسي)

  • قم بتنزيل كل كائن (انقر بزر الماوس الأيمن -> حفظ باسم...) وقم باستيرادها إلى مشروعك (في إعدادات الاستيراد، قم بتعيين نوع النسيج الخاص بها على "Sprite (2D and UI)" ووضع التصفية على "Point (no filter)"

  • في SC_ItemCrafting، قم بتغيير حجم العناصر إلى 5 وقم بتعيين كل كائن لمتغير Item Sprite.

"Stackable" يتحكم المتغير في إمكانية تجميع العناصر معًا في فتحة واحدة (على سبيل المثال، قد ترغب في السماح فقط بتكديس المواد البسيطة مثل الصخور والماس والخشب).

"Craft Recipe" عناصر تحكم متغيرة إذا كان من الممكن تصنيع هذا العنصر (فارغ يعني أنه لا يمكن تصنيعه)

  • بالنسبة إلى "Player Slots"، اضبط حجم المصفوفة على 27 (أفضل ملاءمة للوحة التصنيع الحالية، ولكن يمكنك تعيين أي رقم).

عند الضغط على تشغيل، ستلاحظ أنه تمت تهيئة الفتحات بشكل صحيح، ولكن لا توجد عناصر:

لإضافة عنصر إلى كل فتحة، سنحتاج إلى تعيين عنصر Sprite للمتغير "Item Sprite" وتعيين "Item Count" على أي رقم موجب (كل شيء أقل من 1 و/أو سيتم تفسير العناصر غير القابلة للتكديس على أنها 1):

  • قم بتعيين الكائن "rock" للعنصر 0 / "Item Count" 14، والكائن "wood" للعنصر 1 / "Item Count" 8، والكائن "diamond" للعنصر 2 / "Item Count" 8 (تأكد من أن الكائنات متطابقة مع في "Items" Array، وإلا فلن يعمل).

يجب أن تظهر العناصر الآن في فتحات اللاعب، ويمكنك تغيير موضعها بالنقر فوق العنصر، ثم النقر فوق الفتحة التي تريد نقلها إليها.

صياغة وصفات:

تتيح لك صياغة الوصفات إنشاء عنصر من خلال دمج العناصر الأخرى بترتيب معين:

تنسيق صياغة الوصفة هو كما يلي: [item_sprite_name]([عدد العناصر])*اختياري... يتكرر 9 مرات، مفصولة بفاصلة (،)

إحدى الطرق السهلة لاكتشاف الوصفة هي الضغط على تشغيل، ثم وضع العناصر بالترتيب الذي تريد صياغته، ثم الضغط على "Craft"، وبعد ذلك اضغط على (Ctrl + Shift + C) لفتح وحدة التحكم Unity ورؤية السطر المطبوع حديثًا (يمكنك النقر فوق "Craft" عدة مرات لإعادة طباعة السطر)، والخط المطبوع هو وصفة الصياغة.

على سبيل المثال، المجموعة أدناه تتوافق مع هذه الوصفة: صخرة،،صخرة،،صخرة،،صخرة،،خشبية (ملاحظة: قد يختلف الأمر بالنسبة لك إذا كانت النقوش المتحركة الخاصة بك لها أسماء مختلفة).

وصفة صياغة عنصر السيف

سوف نستخدم الوصفة أعلاه لصنع سيف.

  • انسخ السطر المطبوع، وفي المصفوفة "Items" والصقه في المتغير "Craft Recipe" تحت "sword" العنصر:

الآن، عند تكرار نفس المجموعة، يجب أن تكون قادرًا على صنع سيف.

وصفة السيف الماسي هي نفسها، ولكن بدلاً من الحجر، أصبح الماس:

مفتش الوحدة وصفة السيف الماسي

نظام جرد الوحدة وصياغة العناصر

نظام الصياغة جاهز الآن.

مصدر
📁ItemCrafting.unitypackage36.13 KB
المقالات المقترحة
ترميز نظام جرد بسيط مع سحب واجهة المستخدم وإسقاطها في الوحدة
مقدمة لآلة الدولة في الوحدة
كيفية تشغيل Cutscene في الوحدة
نظام الاختيار والإسقاط بدون جرد في الوحدة
إنشاء نظام نقطي بسيط ثنائي الأبعاد في Unity
إنشاء كائنات تفاعلية في الوحدة
إنشاء محاكي حركة المرور في الوحدة