之前傻傻地认为Unity3D的UI只是在OnGUI的时候画画Button,Image用的,根本没想过UI的效果竟然可以这么棒。废话不多说先上个效果图。
是不是看起来特别帅,感觉一个好的UI界面是一个游戏成功的一半啊。
首先建立一个Canvas,并且在Canvas里面建立五个Panel分别命名为Window(主界面),HeadBag(次级界面1),HandBag(次级界面2),FootBag(次级界面3),Equip(装备界面)。并且将层次设置为UI界面,用UIcamera来渲染。
然后在Window界面建立一个Panel命名为Title,和三个Button分别命名为Head,Hand,Foot指向三个次级界面。为了让button,panel更好看我们可以加个图片控制UI显示的形状,比如Title用了SFtitle这张贴图。
为了让panel有动画,我录制了进来(window)和退出(Exit)的动画。设置Bool参数Open控制状态变换
接着制作HeadBag,HandBag,FootBag次级菜单,添加Grid Layout Group组件,用于布局。然后在菜单里面添加10个按钮,1个退出菜单,9个装备菜单。利用Button的text写下背包名称,在image组件添加图片,即为所储存的装备。
同理复制粘贴搞定另外两个,同时录制好进出的动画。然后考虑菜单随鼠标摆动。编写TiltWindow.cs
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);//求相对x比例,并且限制上下界
float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);//求相对y比例,并且限制上下界
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);//进行旋转
}
}
这时第一个Bug出现了,动画机的问题,当物体处在动画状态时,会阻塞在动画那里,使得脚本失去效果,所以我们需要让动画播放完毕之后使animator失效。顺便写一写菜单切换,可以在场景建立空对象命名为MenuManger,拥有脚本MeneManger.cs控制菜单的切换。切换菜单有两个动作,一个是关闭旧的菜单,一个是开启新的菜单,关闭首先要激活旧菜单的animator,播放退出动画,然后灭活菜单,这里我使用协程,一秒钟之后灭活,开启也要激活animator,播放进入动画,然后使动画机失效,TiltWindow脚本才能有效。
然后为了让图片跟随鼠标移动,设置UIImage,有图片时改为不透明色,没有图片时改为透明色,编写UIimage.cs,UIimage属性具体设置如下:
public class UIimage : MonoBehaviour {
private Image mouse_Image;//鼠标点击的图片
public Color visable;//可见色
public Color unvisable;//不可见色
// Use this for initialization
void Start () {
mouse_Image = GetComponent<Image>();
}
// Update is called once per frame
void Update () {
if(MenuManger.texture != null)//判断如果鼠标点击图片非空,则将UIimage设置为可见,并且将鼠标图片赋值给UIimage,同时随时更新UIimage位置
{
mouse_Image.color = visable;
mouse_Image.sprite = MenuManger.texture;
this.transform.position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
}
else //否则不可见
{
mouse_Image.color = unvisable;
}
}
}
public class Bag : MonoBehaviour {
public int type;
}
public class MenuManger : MonoBehaviour {
private GameObject Current;//当前菜单
private GameObject Previous;//旧菜单
public GameObject Window;//在属性面板拖入相应菜单
public GameObject HeadBag;//
public GameObject HandBag;//
public GameObject FootBag;//
public static Sprite texture;//鼠标获取的图片
public static int type = -1;//鼠标获得图片类型,-1表示无图片
// Use this for initialization
void Start () {
texture = null;
Current = Window;
Previous = Window;
StartCoroutine(OpenDelay());//关闭动画
}
public void getTexture(GameObject obj)
{
if(type == -1 || type == obj.GetComponent<Bag>().type)
{
Sprite previous = texture;//保存鼠标先前的图片
texture = obj.GetComponent<Image>().sprite;//
obj.GetComponent<Image>().sprite = previous;//交换图片
type = obj.GetComponent<Bag>().type;//保存类型
}
if(texture == null)
{
type = -1;//如果为空置-1
}
}
public void putTexture(GameObject obj)
{
if ((type == -1 && obj.GetComponent<Image>().sprite != null) ||type == obj.GetComponent<Bag>().type)
{
Sprite previous = texture;//保存鼠标先前图片
texture = obj.GetComponent<Image>().sprite;//
obj.GetComponent<Image>().sprite = previous;//交换图片
type = obj.GetComponent<Bag>().type;//保存类型
}
if (texture == null)
{
type = -1;
}
}
public IEnumerator OpenDelay()
{
int CoolTimes = 1;//延迟1秒
while (CoolTimes > 0)
{
print("还剩" + CoolTimes);
yield return new WaitForSeconds(1);//等待1秒
CoolTimes--;
}
Current.GetComponent<Animator>().enabled = false;//灭活动画
}
public IEnumerator CloseDelay()
{
int CoolTimes = 1;//延迟1秒
Previous.GetComponent<Animator>().enabled = true;//激活动画
Previous.GetComponent<Animator>().SetBool("Open", false);//播放关闭动画
while (CoolTimes > 0)
{
print("还剩" + CoolTimes);
yield return new WaitForSeconds(1);//等待1秒
CoolTimes--;
}
Previous.SetActive(false);//灭活旧菜单
OpenPanel();//打开新菜单
}
void OpenPanel()
{
Current.SetActive(true);//激活菜单
Previous.GetComponent<Animator>().enabled = true;//激活动画
Current.GetComponent<Animator>().SetBool("Open", true);//播放开启动画
StartCoroutine(OpenDelay());//开启延迟
}
public void OpenPanel(GameObject panel)//打开菜单
{
Previous = Current;//保存旧菜单对象
Current = panel;//保存新菜单对象
StartCoroutine(CloseDelay());//协程关闭菜单
}
}
在BUutton的Onclick函数调用相应函数,具体设置如下
然后用UIcamera负责渲染UI层,main camera渲染背景,用canvas加panel贴背景图,再放个粒子系统。设置如下
这就大功告成了,其实真正做应该是花了一天时间但是看博客,学课堂案例的代码学了挺久,一直以为很难,但其实只有真正动手才能知道难在哪里。再次吐槽我的电脑,明明下了Unity Web Player但是就是看不了demo,什么方法都试过了,我也无话可说,同样的操作同学的电脑却可以成功,而我只能凭着想象力把游戏做出来。
有兴趣看我的工程可以去我的Gihub上看Demo.