Home advanced Unity3D_Gameplay_method
Post
Cancel

advanced Unity3D_Gameplay_method

advanced Unity3D_Gameplay_method

Backpack UI

  • Grid Layout Group
  • Slot Holder

DragItem

EventSystem

RectTransform: record four corners

PointerEventData

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class DragItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    ItemUI currentItemUI;
    SlotHolder currentHolder;
    SlotHolder targetHolder;

    private void Awake()
    {
        currentItemUI = GetComponent<ItemUI>();
        currentHolder = GetComponentInParent<SlotHolder>();
    }
    public void OnBeginDrag(PointerEventData eventData)
    {
        // the first item data -> temp data
        InventoryManager.Instance.currentDrag = new InventoryManager.DragData();
        InventoryManager.Instance.currentDrag.originalHolder = GetComponentInParent<SlotHolder>();
        InventoryManager.Instance.currentDrag.originalParent = (RectTransform)transform.parent;


        // To avoid being overlaid by the other canvas, set the itemslot to the DragCanvas
        transform.SetParent(InventoryManager.Instance.dragCanvas.transform, true);
    }

    public void OnDrag(PointerEventData eventData)
    {
        // follow with the mouse
        transform.position = eventData.position;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        // put down the item -> exchange data

        // whether pointing at the UI item
        if (EventSystem.current.IsPointerOverGameObject())
        {
            // whether it is an slotholder
            if (InventoryManager.Instance.CheckInActionUI(eventData.position) || InventoryManager.Instance.CheckInEquipmentUI(eventData.position)
            || InventoryManager.Instance.CheckInInventoryUI(eventData.position))
            {
                // if it doesn't have a slot holder, then it is the original slot. It shouldn't move to the other slot.
                if (eventData.pointerEnter.gameObject.GetComponent<SlotHolder>())
                {
                    targetHolder = eventData.pointerEnter.gameObject.GetComponent<SlotHolder>();
                }
                else
                {
                    // In case that it doesn't get the image component
                    targetHolder = eventData.pointerEnter.gameObject.GetComponentInParent<SlotHolder>();
                }

                switch (targetHolder.slotType)
                {
                    case SlotType.BAG:
                        SwapItem();
                        break;
                    case SlotType.ACTION:
                        break;
                    case SlotType.WEAPON:
                        break;
                    case SlotType.ARMOR:
                        break;
                }

                // update SO database -> UI
                targetHolder.UpdateItem();
                currentHolder.UpdateItem();
            }
        }

        // return to the original canvas
        transform.SetParent(InventoryManager.Instance.currentDrag.originalParent);

        // return to the original position
        RectTransform t = transform as RectTransform;
        t.offsetMax = -Vector2.one * 5;
        t.offsetMin = Vector2.one * 5;


    }

    public void SwapItem()
    {
        var targetItem = targetHolder.itemUI.Bag.items[targetHolder.itemUI.Index];
        var tempItem = currentHolder.itemUI.Bag.items[currentHolder.itemUI.Index];

        bool isSameItem = tempItem.itemData == targetItem.itemData;

        if (isSameItem && targetItem.itemData.stackable)
        {
            targetItem.amount += tempItem.amount;
            tempItem.itemData = null;
            tempItem.amount = 0;
        }
        else
        {
            currentHolder.itemUI.Bag.items[currentHolder.itemUI.Index] = targetItem;
            targetHolder.itemUI.Bag.items[targetHolder.itemUI.Index] = tempItem;

        }
    }
}

实现映射渲染: RawImage / 独立 Camera / render Texture

render Texture

RawImage

独立 Camera

ToolTip

Content Size Fitter: auto-resize UI

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class ItemToolTip : MonoBehaviour
{
    public TextMeshProUGUI itemNameText;
    public TextMeshProUGUI itemInfoText;
    public RectTransform rectTransform;


    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }
    public void SetupTooltip(ItemData_SO item)
    {
        itemNameText.text = item.itemName;
        itemInfoText.text = item.description;
    }

    private void OnEnable()
    {
        UpdatePosition();
    }
    private void Update()
    {
        UpdatePosition();
    }

    public void UpdatePosition()
    {
        Vector3 mousePos = Input.mousePosition;
        Vector3[] cornors = new Vector3[4];
        rectTransform.GetWorldCorners(cornors);

        float width = cornors[3].x - cornors[0].x;
        float height = cornors[1].y - cornors[0].y;

        if (mousePos.y < height)
        {
            rectTransform.position = mousePos + Vector3.up * height * 0.6f;
        }
        else if (Screen.width - mousePos.x > width)
        {
            rectTransform.position = mousePos + Vector3.right * width * 0.6f;
        }
        else
        {
            rectTransform.position = mousePos + Vector3.left * width * 0.6f;
        }
    }
}

RectTransform.GetWorldCorners

Dialogue

OnValidate(): for Dic in the SO Scripts

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
28
29
30
31
32
33
34
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "New Dialogue", menuName = "Dialogue/Dialogue Data")]
public class DialogueData_SO : ScriptableObject
{
    public List<DialoguePiece> dialoguePieces = new List<DialoguePiece>();
    public Dictionary<string, DialoguePiece> dialogueIndex = new Dictionary<string, DialoguePiece>();

// synchornize the id and index
#if UNITY_EDITOR
// only run when making changes in the SO file from the Inspector Panel
    void OnValidate()//仅在编辑器内执行导致打包游戏后字典空了
    {
        dialogueIndex.Clear();
        foreach (var piece in dialoguePieces)
        {
            if (!dialogueIndex.ContainsKey(piece.ID))
                dialogueIndex.Add(piece.ID, piece);
        }
    }
#else
    void Awake()//保证在打包执行的游戏里第一时间获得对话的所有字典匹配 
    {
        dialogueIndex.Clear();
        foreach (var piece in dialoguePieces)
        {
            if (!dialogueIndex.ContainsKey(piece.ID))
                dialogueIndex.Add(piece.ID, piece);
        }
    }
#endif
}

Task

Find tasks in the list

Linq usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public List<QuestTask> tasks = new List<QuestTask>();

    public bool HaveQuest(QuestData_SO data)
    {
        if (data != null)
        {
            return tasks.Any(q => q.questData.questName == data.questName);
        }
        else
        {
            return false;
        }
    }

    public QuestTask GetTask(QuestData_SO data)
    {
        return tasks.Find(q => q.questData.questName == data.questName);
    }
1
2
3
4
5
6
7
8
9
10
    public void CheckQuestProgress()
    {
        var finishRequires = questRequires.Where(r => r.requireAmount <= r.currentAmount);
        isComplete = questRequires.Count == finishRequires.Count();

        if (isComplete)
        {
            Debug.Log("Complete!");
        }
    }

Editor Script

New Inspector

1
2
3
4
5
6
7
8
9
10
11
12
13
// define which file should be chousen
[CustomEditor(typeof(DialogueData_SO))]
public class DialogueCustomEditor : Editor
{
    public override void OnInspectorGUI()
    {
        if (GUILayout.Button("Open in Editor"))
        {
            DialogueEditor.InitWindow((DialogueData_SO)target);
        }
        base.OnInspectorGUI();
    }
}

ReorderableList: render enumerable object

1
2
3
4
piecesList = new ReorderableList(currentData.dialoguePieces, typeof(DialoguePiece), true, true, true, true);
piecesList.drawHeaderCallback += OnDrawPieceHeader;
piecesList.drawElementCallback += OnDrawPieceListElement;
piecesList.elementHeightCallback += OnHightChanged;

OnSelectionChange()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    // when change to another file without quit
    private void OnSelectionChange()
    {
        var newData = Selection.activeObject as DialogueData_SO;
        if (newData != null)
        {
            currentData = newData;
            SetupReorderableList();
        }
        else
        {
            currentData = null;
            piecesList = null;
        }
        Repaint();
    }

Create & Save New File

1
2
3
4
5
6
7
8
9
10
11
            if (GUILayout.Button("Create New Dialogue"))
            {
                string dataPath = "Assets/Game Data/Dialogue/";
                if (!Directory.Exists(dataPath))
                {
                    Directory.CreateDirectory(dataPath);
                }
                DialogueData_SO newData = ScriptableObject.CreateInstance<DialogueData_SO>();
                AssetDatabase.CreateAsset(newData, dataPath + "/" + "New Dialogue.asset");
                currentData = newData;
            }

Scroller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        if (currentData != null)
        {
            EditorGUILayout.LabelField(currentData.name, EditorStyles.boldLabel);
            GUILayout.Space(10);

            // scoller
            scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
            if (piecesList == null)
            {
                SetupReorderableList();
            }

            // draw the list
            piecesList.DoLayoutList();
            GUILayout.EndScrollView();
        }

Dirty Object: auto-save, Undo … in the inspector

1
2
        // SetDirty -> make data in the new panel be auto-save, Undo...
        EditorUtility.SetDirty(currentData);

Expand

1
2
            // pointer -> sync with currentPiece.canExpand
            currentPiece.canExpand = EditorGUI.Foldout(tempRect, currentPiece.canExpand, currentPiece.ID);
This post is licensed under CC BY 4.0 by the author.