这次制作了一个切换装备的UI界面,首先上效果图
有点恐怖,嘿嘿,下面说一下制作思路
游戏背景
新建一个空对象命名为SF Scene Elements,里面包含一个main camera,一个空对象BackGround,一个粒子系统。
在BackGround中添加Sprite Renderer组件,将选好的背景添加。
值得注意,我一开始下载的是图片资源,怎么都不能挂到Sprite上,后来知道要将图片的Texture Type改为Sprite才行
调整粒子系统,做出比较炫酷的样子,点击播放可以查看效果
引入骷髅兵
自然,首先想到的就是将我们的骷髅兵放在相对于main camera合适的位置。但是通过老师的指引,我发现了一种更好的办法:用摄像机的叠加渲染效果。
原理很简单,当一个游戏场景中包含多个摄像机时,会根据摄像机组件Depth的大小决定渲染顺序。那么我们就可以先用一个摄像机把背景渲染出来,然后再用另外一个摄像机把骷髅兵(不包括天空盒)渲染出来,就可以达到效果。
新建一个摄像机为Hero Camera,把它放到十分遥远的地方(反正和其余游戏对象都没有关联就行),将Clear Flags设为Depth only,这样它就不会渲染天空盒。
由于这个摄像机是很遥远的,只会渲染骷髅兵,其他的游戏对象不会进入它的视角范围内,所以Culing Mask可以设为Everything。
然后把骷髅兵作为这个摄像机的子对象加入,调整位置,再为骷髅兵添加动画
如图,骷髅兵是在画布后面被渲染的,作为我们的幕后英雄,它的渲染效果是这样的(它会动的,我不会录视频….)
这里说一下我对用不同相机渲染游戏的理解:这样可以将游戏中相应的模块独立出来,以后可以拿来继续使用,有良好的延续性。其次,功能独立,这样便于游戏的设计
关于UI
可以看出游戏中包含两个UI界面,一个是装备栏,一个是背包栏,首先新建一个画布Canvas,里面添加一个子对象Panel,Panel中包含这两个UI界面,Bag,Equipment应该也同样为Panel
Bag,Equipment
Bag里有九个格子,Equipment有三个,可以通过Grid Layout Group组件来实现,由于点击需要触发事件,所以我把这些格子都设为了Button,设置相关参数,比如Equipment的Hand(Grid Layout Group其实已经把位置规定好了,只需要调整文本位置和图片就行)
UI Camera
同样用到了多摄像头渲染的原理,与Scene画布同级创建一个摄像机,设定作用层为UI
可以在右下角窗口看到,UI Camera拍到的内容
设置完这一切我们就可以达到一开始图片的效果了
拓展
你以为这样就完了吗,不不不。既然作为切换装备的UI界面,装备要是不能切换岂不是欺骗人民群众。结合相关案例分析,我的思路是:
有一个单例模式下形成的类Mouse记录当前选取的装备
一个Equip类挂载到每一个装备按钮上定义装备栏点击触发事件
一个MyBag类挂载到每一个背包按钮上定义背包栏点击触发事件
一个Equipment类记录当前鼠标选取的装备。
Mouse
获取当前鼠标选取的装备
using UnityEngine;
using System.Collections;
using Game_Manager;
namespace Game_Manager
{
public class EquipmentManager : System.Object
{
private static EquipmentManager _instance;
private static Equipment _Equipment;
public static EquipmentManager GetInstance()
{
if (_instance == null)
{
_instance = new EquipmentManager();
}
return _instance;
}
public void SetEquipment(Equipment _equipment)
{
if (_Equipment == null)
{
_Equipment = _equipment;
}
}
public Equipment GetEquipment()
{
return _Equipment;
}
}
}
public class Mouse : MonoBehaviour
{
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
创建一个空对象Manager挂载
Equipment
我将它挂载到一个Image对象上(简陋版…),让它时时跟随鼠标移动,但是如果没有选取装备,则将这个对象颜色设为透明,如果选取了装备,则设为不透明。关于装备种类有三种,用int类型来区分:
- 1:盾牌
- 2:武器
- 3:战靴
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using Game_Manager;
public class Equipment : MonoBehaviour {
private EquipmentManager gsm;
private Image Equipment_image;
private int Equipment_type = 0;
public Color None;
public Color NotNone;
void Awake()
{
gsm = EquipmentManager.GetInstance();
gsm.SetEquipment(this);
Equipment_image = GetComponent<Image>();
}
public int GetEquipmentType()
{
return Equipment_type;
}
public void SetEquipmentType(int equipment_type)
{
Equipment_type = equipment_type;
}
public Image GetImage()
{
return Equipment_image;
}
void Update()
{
if (Equipment_type == 0) // 什么都不是
{
Equipment_image.color = None; // 透明颜色
}
else
{
Equipment_image.color = NotNone; // 不透明,可见
}
transform.position = new Vector3(Input.mousePosition.x - 425, Input.mousePosition.y - 165, 0);
}
}
Equip
有一个int类型的种类信息记录装备的类型,这样在给人物添加对应种类装备错误时就不会放上去,这样可以避免人物把剑当鞋子之类的乌龙。拿走装备前提是鼠标当前没有选取装备,佩戴装备前提是鼠标选取了与对应装备栏种类相同的装备。关于拿走装备骷髅兵会脱掉相应装备,佩戴装备骷髅兵会穿上装备的实现也很简单,就是将相关组件disable掉或者重新激活,因此需要一个GameObject对象,挂上对应的对象组件就行
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using Game_Manager;
public class Equip : MonoBehaviour
{
private EquipmentManager gsm;
private Image equip_image;
public int Equipment_type;
public Sprite IdelSprite;
public GameObject equipment;
void Awake()
{
gsm = EquipmentManager.GetInstance();
equip_image = GetComponent<Image>();
}
public void On_equip_Button() // 按钮被按触发事件
{
int EquipmentType = gsm.GetEquipment().GetEquipmentType();
if (equip_image.sprite != IdelSprite && EquipmentType == 0) // 装备栏有武器时,抓取,此时要求没有选中任何武器所以MouseType要为0
{
gsm.GetEquipment().GetImage().sprite = equip_image.sprite;
equip_image.sprite = IdelSprite;
gsm.GetEquipment().SetEquipmentType(Equipment_type);
if (equipment != null)
equipment.SetActive(false);
}
else
{
if (EquipmentType == Equipment_type && equip_image.sprite == IdelSprite) // 放置到装备栏,此时要求装备栏中该位置为空闲,否则原来的武器会消失
{
equip_image.sprite = gsm.GetEquipment().GetImage().sprite;
gsm.GetEquipment().SetEquipmentType(0);
if (equipment != null)
equipment.SetActive(true);
}
}
}
}
比如盾牌装备栏
这里的Bip01 L就是骷髅兵的盾牌对象。同时记得给On Click登记相应事件
MyBag
由于MyBag会随时放置不同种类的装备,所以也会包含一个int类型的Element_Type记录当前所放的装备类型,当物品放置到背包时,Equipment类就会把对应装备的种类传给背包,同理,取出装备时背包会将装备类型传给Equipment类。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using Game_Manager;
public class MyBag : MonoBehaviour
{
private EquipmentManager gsm;
private Image bag_image;
public int Equipment_type = 0;
public Sprite IdelSprite;
void Awake()
{
gsm = EquipmentManager.GetInstance();
bag_image = GetComponent<Image>();
}
public void On_equip_Button()
{
int EquipmentType = gsm.GetEquipment().GetEquipmentType();
if (bag_image.sprite != IdelSprite && EquipmentType == 0) // 该处有装备,拿走
{
gsm.GetEquipment().GetImage().sprite = bag_image.sprite;
bag_image.sprite = IdelSprite;
gsm.GetEquipment().SetEquipmentType(Equipment_type);
Equipment_type = 0;
}
else
{
if (bag_image.sprite == IdelSprite)
{
bag_image.sprite = gsm.GetEquipment().GetImage().sprite;
Equipment_type = EquipmentType;
gsm.GetEquipment().SetEquipmentType(0);
}
}
}
}
所以,背包中的装备、装备种类值只能通过预处理阶段或者后期和Equipment类合作修改
TiltWindow
这个类可以使UI界面跟随鼠标的移动而改变朝向,使界面具有动态感,上课时的案例抄来的……
using UnityEngine;
public class TiltWindow : MonoBehaviour
{
public Vector2 range = new Vector2(5f, 3f);
Transform mTrans;
Quaternion mStart;
Vector2 mRot = Vector2.zero;
void Start ()
{
mTrans = transform;
mStart = mTrans.localRotation;
}
void Update ()
{
Vector3 pos = Input.mousePosition;
float halfWidth = Screen.width * 0.5f;
float halfHeight = Screen.height * 0.5f;
float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f);
float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);
mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f);
mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, mRot.x * range.x, 0f);
}
}
效果展示
取走盾牌放入背包(只能放入空闲背包,不然不会让你放入),骷髅兵:“咦,我的盾牌呢”
给骷髅兵换上一面新盾牌,骷髅兵:“哦,在这啊”
把盾牌和剑都取下来,骷髅兵:“天啊,我撞鬼啦”
装上新的盾牌(放到剑栏就不会有反应,拒绝放入) 骷髅兵:“我像不像美国队长”
鞋嘛,这货没穿鞋,我就不演示了,同时UI框也朝向了鼠标移动的位置,反正截图看不出来(信我啊)
Summary
本次实验加深了我对摄像机使用的理解(多层渲染)。对于UI的设计其实很简单,无论美术功底好不好都能创造出不错的UI界面,很多UI对象的功能我都不是很熟悉,都是后期不断尝试最后弄清楚的,对于计算机类实验,不要害怕尝试,要大胆探索,unity中有很多有趣的东西,是官方手册说不完的,还需要我们更深入的探索。本次实验我参考了较多的案例,有很多自己的理解,欢迎大家提出意见,我好予以改正!