目录
一、背包系统的实现
视频演示地址: 【Unity3D 背包系统的实现】
1. 导入需要的游戏资源包
在Asset Store中添加并导入以下三项资源包:
2. GUI 图形界面设计
在之前实现好的场景中添加一个名为Bag的Panel,为其添加子对象:Button对象CloseButton;包含text的image对象Title;text对象itemdescription;和panel对象Grid:
‘
(1)设置关闭按钮事件
在CloseButton中,添加GameObject对象“Bag”的关闭事件。
(2)设置背包栏的网格结构
1. 为Grid导入图片素材,同时按住Alt和Shift,并点击居中结构即可使panel位于Bag的中央,调整大小:
2. 为Grid添加Grid Layout Group的component,即可实现每一小格的网格效果,可调整每格的大小和间距,使每个小格居中:
3. 添加Grid子对象slot和slot的一个text子对象,可以设置装备图片及其数量,将slot作为预制体:
(3)GUI界面
得到的GUI界面大致如下,在Player挂载的movement脚本中添加OpenMybag操作,并将Bag添加到Player中的MyBag对象,即可实现玩家按下O键打开背包的功能:
3.创建背包物品的数据结构
① 定义一个物品类(Item),包含物品的名称、图标、描述等属性。
② 使用脚本ScriptableObject来创建可在Unity编辑器中配置的物品实例。
将MonoBehaviour替换为ScriptableObject,使用它可以高效地创建物品数据库和物品模版,进行数据存储。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item")]//可以在鼠标右单击 创建 找到 可以创建一New Item类的文件
public class Item : ScriptableObject//数据本地化
{
public string itemName;//物体名称
public Sprite itemImage;//物体图片
public int itemHeld; //物体数量
[TextArea]//文字可以显示多行
public string itemInfo;//物体描述
public bool Equip;//物体种类
}
③ 在Items文件夹中可以添加并导入各个物品的信息,如下图:
4.创建背包物品的数据列表
与上面同理,创建一个背包的物品数据列表:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Inventory", menuName = "Inventory/New Invontory")]
public class Invontory : ScriptableObject
{
public List<Item> itemList = new List<Item>();
}
5. 场景中物品的拾取,添加到背包的功能实现
(1) 在场景内添加物品,并为其添加碰撞组件:
(2) 预制体单元格slot
① 存储单元格中显示的信息,并通过InventoryManager方法实现点击单元格事件触发Item信息显示的功能:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class Slot : MonoBehaviour//放在预制体上显示信息
{
public Item slotItem;
public Image slotImage;
public Text slotNum;
public void ItemOnclicked()
{
InventoryManager.UpdateItemInfo(slotItem.itemInfo);
}
}
② 将slot脚本挂载到之前创建的slot预制体上,将预制体中的image和number对应到脚本之中:
(3) 显示背包栏UI : 管理Item数据
① 将该脚本挂载到Canvas上,实现单元格的更新:
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryManager : MonoBehaviour
{
static InventoryManager instance;
public Invontory myBag;
public GameObject slotGrid;//在什么地方生成单元格
public Slot slotPrefab;//单元格
public Text itemInformatoin;
private void OnEnable()
{
RefreshItem();
instance.itemInformatoin.text="";
}
public static void UpdateItemInfo(string itemDescription)
{
instance.itemInformatoin.text = itemDescription;
}
private void Awake()
{
if (instance != null)
{
Destroy(this);
}
instance = this;
}
public static void CreateNewItem(Item item)
{
Slot newItem = Instantiate(instance.slotPrefab, instance.slotGrid.transform.position, Quaternion.identity);
newItem.gameObject.transform.SetParent(instance.slotGrid.transform);
newItem.slotItem = item;
newItem.slotImage.sprite = item.itemImage;
newItem.slotNum.text=item.itemHeld.ToString();
}
public static void RefreshItem()
{
for (int i = 0; i < instance.slotGrid.transform.childCount; i++)
{
if (instance.slotGrid.transform.childCount == 0)
{
break;
}
Destroy(instance.slotGrid.transform.GetChild(i).gameObject);//毁灭所有子集
}
for (int i = 0; i < instance.myBag.itemList.Count; i++)
{
CreateNewItem(instance.myBag.itemList[i]);
}
}
}
②将UI组件中对应的文本框和网格Panel,创建好的背包列表添加到脚本中:
(4) 物体在场景中的碰撞处理
① 将该脚本挂载到场景中散落的物品,将Player碰撞到的Item信息通过AddNewItem调用InventoryManager的方法传输并显示在背包栏UI中:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class itemOnworld : MonoBehaviour
{
public Item thisItem;//物体类型
public Invontory playerInvontory;//去到背包
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
AddNewItem();
Destroy(gameObject);
}
}
//背包增加物品
public void AddNewItem()
{
if (!playerInvontory.itemList.Contains(thisItem))//判断物品不包含在列表当中
{
playerInvontory.itemList.Add(thisItem);
thisItem.itemHeld += 1;
InventoryManager.CreateNewItem(thisItem);
}
else
{
thisItem.itemHeld += 1;
}
InventoryManager.RefreshItem();
}
}
② 如下图,为场景物品脚本添加对应的之前创建存储的Item信息和背包信息:
6. 玩家的移动控制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb;
Collider2D coll;
Animator anim;
public GameObject myBag;
bool isOpen;
public float speed;
Vector2 movement;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
coll = GetComponent<Collider2D>();
anim = GetComponent<Animator>();
}
private void Update()
{
Movement();
SwitchAnim();
OpenMybag();
}
void Movement()//移动
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
rb.MovePosition(rb.position + movement * speed * Time.deltaTime);
}
void SwitchAnim()//切换动画
{
if (movement != Vector2.zero)//保证Horizontal归0时,保留movment的值来切换idle动画的blend tree
{
anim.SetFloat("horizontal", movement.x);
anim.SetFloat("vertical", movement.y);
}
anim.SetFloat("speed", movement.magnitude);//magnitude 也可以用 sqrMagnitude 具体可以参考Api 默认返回值永远>=0
}
void OpenMybag()
{
if (Input.GetKeyDown(KeyCode.O))
{
isOpen = !isOpen;
myBag.SetActive(isOpen);
}
}
}
二、 课程总结:优秀标准
通过这门课程,我熟悉掌握了Unity3D的各项基本开发技术,包括基本运动,基本组件,物理碰撞,动画设计,粒子特效及交互ui等,还掌握了MVC架构及其改进等基本游戏架构。
通过一学期的学习实践,我获得了丰富的游戏开发知识和技能,我认为我在这门课程中的表现,符合了自己设定的优秀标准,分别在以下几个方面展现了出色的能力:
-
首先,我在游戏程序设计技术方面表现出色,能够用UML清晰地表达复杂组件设计
如在“魔鬼与牧师游戏开发”项目 http://t.csdnimg.cn/IfWGW 和“魔鬼与牧师游戏(动作分离版)开发”项目 http://t.csdnimg.cn/UzWSu 中,我都熟练地使用UML清晰表达对象设计结果,说明动作的分离和集成的原理,我的项目示例和代码片段也展现出了我在实际应用中的游戏程序设计能力。
-
其次,我对中高级UI设计技术充满热情,深刻理解UI设计原则,并能够使用工具创建出吸引人的用户界面设计。
如在本博客的“背包系统”中和之前的“第一人称射箭游戏的开发”http://t.csdnimg.cn/hMP5K 中,我都设计了简洁清晰,具有趣味性和特色的的UI界面。
-
此外,在项目实践中我的自学能力、创新能力不断提高,在向他人学习游戏开发时会根据实际情况有所创新改进。
如在本博客的“背包系统”中,在创建物品数据库和物品模版时,我替换掉了 MonoBehaviour ,使用了 ScriptableObject来实现相应功能,它的优点就是不需要挂在任何 GameObject 上就能使用,这大大提高了开发的效率。
-
我在AR和VR交互技术方面表现出浓厚的兴趣,并将这些技术应用于游戏创新玩法。我的项目展示了我对这些新兴领域的熟练掌握。
-
我还在人物模型与动画控制技术领域取得了较高的水平,创造了较为精美的游戏角色模型和流畅的动画。我熟悉粒子特效的高效实现方法,能够尝试进行性能优化并得到较好的效果。
-
最后,我通过撰写技术普及博客积极分享知识,博客简洁明了,能清晰地展示出游戏开发的实际步骤,向初学者们传播游戏设计的实用技术。
总之,我在Unity3D课程中不仅掌握了多项关键技能,还将这些技能成功应用于项目中,达到了我设定的优秀标准,这门课程也将对我以后的游戏开发实践产生积极而深远的影响