2018-03-23 20:07:47 MadBam_boo 阅读数 633
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

Unity3d实战之Unity3d网络游戏实战篇(13):登录&注册面板

学习书籍《Unity3d网络游戏实战》 罗培羽著 机械工业出版社
本文是作者在学习过程中遇到的认为值得记录的点,因此引用的代码等资源基本出资罗培羽老师的书籍,如有侵权请联系,必删。

 建立好网络模块后,我们可以开始对UI进行编程,实现可视化的登录注册面板。在第二节-代码资源分离的界面系统中,实现了Panel基类,之后的所有面板都会基于该基类并根据需求进行实现。本节给出登录、注册的实例。

 1、登录面板
 根据自己的喜好构建一个登录界面,这里给出一个测试样例:
 这里写图片描述
 注意,其中的Panel和Tips是Canvas下的空物体,用于对各种Panel进行分组,他们拥有的是Rect Transform组件而不是Transform组件。
 LoginPanel本身是Panel类型,以Text为后缀的是Text类型,以Input为后缀的是IntputField类型,以Btn为后缀的是Button类型。记得将LoginPanel拖拽到Resources文件夹中,因为PanelMgr的OpenPanel方法将从Resources文件夹中寻到对应的Panel并实例化。

 根据LoginPanel所示,我们在登录时需要输入用户名、密码、点击登录或者注册。这四个物体使我们所关注的。
 创建C# Script,命名为LoginPanel,声明四个变量:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;   // don't forget it.

public class LoginPanel : PanelBase {
    /*
     * Add a logout listener.
     */
    private InputField idInput;  // InputField of user name 
    private InputField pwInput;  // InputField of password
    private Button loginBtn;     // Button of login
    private Button regBtn;       // Button of register
}

 然后,按照需求重载父类PanelBase的Init()方法和OnShowing()方法:

#region Operation-Cycle
public override void Init (params object[] args)
{
    base.Init (args);
    skinPath = "LoginPanel";
    layer = PanelMgr.PanelLayer.Panel;
}

public override void OnShowing ()
{
    base.OnShowing ();
    Transform skinTrans = skin.transform;
    idInput = skinTrans.Find ("idInput").GetComponent<InputField> ();
    pwInput = skinTrans.Find ("pwInput").GetComponent<InputField> ();
    loginBtn = skinTrans.Find ("loginBtn").GetComponent<Button> ();
    regBtn = skinTrans.Find ("regBtn").GetComponent<Button> ();

    loginBtn.onClick.AddListener (OnLoginButtonClick);
    regBtn.onClick.AddListener (OnRegisterButtonClick);
}
#endregion

 在Init()方法中,将skinPath设置为LoginPanel,这样调用PanelMgr.OpenPanel方法才能在Resource文件夹中找到对应的Panel。
 在OnShowing()方法中,首先,获取到LoginPanel的实例的Transform组件,然后使用Transform.Find(string name).GetComponent<>()来获取需要用到的组件。并给Button添加点击事件。

 当用户点击Login按钮时,Client需要检测用户输入的用户名和密码是否为空,如果为空则输出对应的提示信息(Tips组的Panel,实现方法与LoginPanel的方法相似,读者可尝试自行实现);否则,将用户名和密码打包成消息发送给服务端,并等待服务端的处理结果,根据处理结果决定用户是进入游戏大厅还是输出提示信息。
 当用户点击Register按钮时,跳转到RegisterPanel,关闭LoginPanel。

#region OnButtonClickEvent
void OnLoginButtonClick()
{
    if (idInput.text == "" || pwInput.text == "") {
        //Debug.Log ("[LoginPanel.OnLoginButtonClick] Id and pw can't stay empty.");
        PanelMgr.instance.OpenPanel<TipPanel>("","Id and pw can't stay empty.");
        return;
    }

    if (NetMgr.servConn.status != Connection.Status.Connected) {
        NetMgr.servConn.proto = new ProtocolBytes ();
        if (!NetMgr.servConn.Connect ("127.0.0.1", 1234)) {
            PanelMgr.instance.OpenPanel<TipPanel> ("", "Connect server fail.");
        }
    }

    ProtocolBytes protocol = new ProtocolBytes ();
    protocol.AddString ("Login");
    protocol.AddString (idInput.text);
    protocol.AddString (pwInput.text);
    Debug.Log ("[LoginPanel.OnLoginButtonClick] Send protocol: Login " + idInput.text + "[id] " + pwInput.text + "[pw]");
    NetMgr.servConn.Send (protocol, OnLoginBack);
}

void OnRegisterButtonClick()
{
    PanelMgr.instance.OpenPanel<RegisterPanel> ("");
    Close ();
}
#endregion

 在Register的点击事件中,我们先对用户输入进行判空处理,然后对用户的网络连接进行检测,之后再打包用户输入的用户名和密码,发送给服务端并等待处理结果。在事件结尾我们使用了NetMgr.servConn.Send (protocol, OnLoginBack);,(详情传送门走起)当接收到服务端返回的处理结果后,Client将调用OnLoginBack方法,根据结果执行不同的逻辑。

#region OnBackEvent
void OnLoginBack(ProtocolBase protoBase)
{
    ProtocolBytes protocolRec = (ProtocolBytes)protoBase;
    int start = 0;
    string protoName = protocolRec.GetString (start, ref start);
    int result = protocolRec.GetInt (start, ref start);
    if (result == 0) {
        //Debug.Log ("[LoginPanel.OnLoginBack] Login success. ");
        PanelMgr.instance.OpenPanel<TipPanel>("","Login success. ");
        PanelMgr.instance.OpenPanel<LobbyPanel> ("");
        Close ();
    }else{
        //Debug.Log ("[LoginPanel.OnLoginBack] Login fail. ");
        PanelMgr.instance.OpenPanel<TipPanel>("","Login fail. Please check your username and password.");
    }
}
#endregion

 如果用户密码正确,进入大厅,否则弹出错误提示。

 2、注册面板
 测试样例:
 这里写图片描述
 需要用到的UI跟LoginPanel相差不大,只是多了一个确认密码的UI而已。其他部分改改Text、改改位置即可。
 在RegisterPanel中,增加了一个Repaet UI,用于用户密码的二次确认。其他部分跟LoginPanel类似,因此,RegisterPanel脚本跟LoginPanel脚本不同的地方就在于对用户的输入的密码增加一个二次确认的判断,其余部分相差不大,读者可自行体会:
 

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

public class RegisterPanel : PanelBase {

    private InputField idInput;
    private InputField pwInput;
    private InputField rpInput;
    private Button regBtn;
    private Button closeBtn;

    #region Operation-Cycle
    public override void Init (params object[] args)
    {
        base.Init (args);
        skinPath = "RegisterPanel";
        layer = PanelMgr.PanelLayer.Panel;
    }

    public override void OnShowing ()
    {
        base.OnShowing ();
        Transform skinTrans = skin.transform;
        idInput = skinTrans.Find ("idInput").GetComponent<InputField> ();
        pwInput = skinTrans.Find ("pwInput").GetComponent<InputField> ();
        rpwInput = skinTrans.Find ("rpInput").GetComponent<InputField> ();
        regBtn = skinTrans.Find ("regBtn").GetComponent<Button> ();
        closeBtn = skinTrans.Find ("closeBtn").GetComponent<Button> ();

        regBtn.onClick.AddListener (OnRegisterButtonClick);
        closeBtn.onClick.AddListener (OnCloseButtonClick);
    }
    #endregion

    #region OnButtonClickEvent
    void OnRegisterButtonClick()
    {
        // check empty input.
        if (idInput.text == "" || pwInput.text == "" || rpInput.text == "") {
            //Debug.Log ("[RegisterPanel.OnRegisterButtonClick] Id and pw and check pw can't stay empty.");
            PanelMgr.instance.OpenPanel<TipPanel>("","Id and pw and check pw can't stay empty.");
            return;
        }

        // check if the password correct.
        if (pwInput.text != rpInput.text) {
            //Debug.Log ("[RegisterPanel.OnRegisterButtonClick] Two password are different.");
            PanelMgr.instance.OpenPanel<TipPanel>("","Two password are different.");
            return;
        }

        // check the connection status
        if (NetMgr.servConn.status != Connection.Status.Connected) {
            NetMgr.servConn.clientProtocol= new ProtocolBytes ();
            if (!NetMgr.servConn.Connect ("127.0.0.1", 1234)) {
                PanelMgr.instance.OpenPanel<TipPanel> ("", "Connect server fail.");
            }
        }

        // send message
        ProtocolBytes protocol = new ProtocolBytes ();
        protocol.AddString ("Register");
        protocol.AddString (idInput.text);
        protocol.AddString (pwInput.text);
        Debug.Log ("[LoginPanel.OnRegisterButtonClick] Send protocol: Register " + idInput.text + "[id] " + pwInput.text + "[pw]");
        NetMgr.servConn.Send (protocol, OnRegisterBack);     // wait for result.
    }

    void OnCloseButtonClick()
    {
        PanelMgr.instance.OpenPanel<LoginPanel> ("");
        Close ();
    }
    #endregion

    #region OnBackEvent
    void OnRegisterBack(ProtocolBase protoBase)
    {
        ProtocolBytes protocol = (ProtocolBytes)protoBase;
        int start = 0;
        string protoName = protocol.GetString (start, ref start);
        int result = protocol.GetInt (start, ref start);
        //  if ok, open login panel, else print out tips panel.
        if (result == 0) {
            //Debug.Log ("[RegisterPanel.OnRegisterBack] Register success.");
            PanelMgr.instance.OpenPanel<TipPanel>("","Register success.");
            PanelMgr.instance.OpenPanel<LoginPanel> ("");
            Close ();
        } else {
            //Debug.Log ("[RegisterPanel.OnRegisterBack] Register fail.");
            PanelMgr.instance.OpenPanel<TipPanel>("","Register fail. Please use another id.");
        }
    }
    #endregion
}

 本节只举了LoginPanel和RegisterPanel两个例子,其他的面板实现方式都是类似的,如果有认真读懂这两个脚本的话,自己设计其他面板是没有太大的问题的。如果想要UI好看点,可以研究一下Unity3d的Aniimation。
 官方教程传送门-Unity3d Animation Tutorial

如果想要在打开面板前后加入动画或者其他逻辑,可以重载OnShowing和OnShowed方法;
如果想要在关闭面板前后加入动画或者其他逻辑,可以重载OnClosing和OnClosed方法。

 以上。

2017-02-26 20:49:29 kong1287988804 阅读数 4495
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

工具准备:Unity,NGUI插件,字体制作工具bitmap font,TexturePackerGUI


1、首先对字体进行处理

界面所用到的字保存成一个txt文本,注意要把编码改成Unicode(可以把文本另存为,选择Unicode编码)。

之后打开bitmap font工具,并在font setting中设置微软雅黑


在Edit中先选择Clear all....之后再select chars from file 把之前的txt文件导入

导出选项设置(注意32位 ,下面选择png),完事选择Save bitmap font as.....导出结果。

成品是这两个文件,把fnt后缀的改成txt,编码改成Unicode2。

2、对图片进行图集处理



注意以下配置:1024*1024,Basic



完事形成两个文件,同样要把.txt文件改成Unicode2编码。


未完待续。。。




2015-01-23 10:20:32 book_longssl 阅读数 2226
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

1,创建一个数据库表,我们就以 test数据库为例,数据库里建一个tb_User表, tb_User里有User_Name , User_Pass 字段.

2,创建一个验证用户基本信息的asp.net页面,页面名字是:Default.aspx

后台代码如下:
  1. using System;
  2. using System.Configuration;
  3. using System.Data;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.HtmlControls;
  8. using System.Web.UI.WebControls;
  9. using System.Web.UI.WebControls.WebParts;
  10. using System.Data.SqlClient;

  11. public partial class _Default : System.Web.UI.Page
  12. {

  13. SqlConnection conn = new SqlConnection("Data Source=.sqlexpress2008;Initial Catalog=test;Integrated Security=True");

  14. protected void Page_Load(object sender, EventArgs e)
  15. {
  16. string name = Request.Form["name2";
  17. string pwd=Request.Form["pwd";

  18. conn.Open();

  19. string sql = "select User_Name from tb_User where User_Name='" + name + "' and User_Pass='"+pwd+"'";
  20. SqlCommand cmd = new SqlCommand(sql, conn);
  21. if (cmd.ExecuteScalar() != null)
  22. Response.Write("success");
  23. else
  24. Response.Write("faield");
  25. conn.Close();
  26. }
  27. }
复制代码



前台代码不用管.

3,新建一个Unity 3D项目,新建一个Javascript文件, 在Javascript文件上编写如下代码:

  1. var URL = "http://devmac.net/domino/rui/Default.aspx"; //提交的URL地址
  2. static var return_data:String;
  3. var strname:String;
  4. var strpwd:String;
  5. var cls:boolean=false;
  6. var xx:Rect = Rect (20, 10, 150, 100);
  7. function OnGUI() {
  8. if(cls)
  9. xx = GUI.Window(1, xx, windowjj, "Window");
  10. GUI.Label(Rect(10,10,80,20),"UserName:");
  11. GUI.Label(Rect(10,30,80,20),"Userpass:");
  12. strname=GUI.TextField(Rect(90,10,100,20),strname);
  13. strpwd=GUI.PasswordField(Rect(90,30,100,20),strpwd,"*"[0],25);
  14. //same as above, but for password
  15. if ( GUI.Button ( Rect (60, 60, 100, 20) , "Login" ) ){ //just a button
  16. Login();
  17. }
  18. }
  19. function windowjj(windowID : int){
  20. GUI.Label(Rect(55,25,50,20),return_data);
  21. if(GUI.Button(Rect(50,55,50,20),"Close")) cls=false;//
  22. }
  23. function Login() {
  24. var form = new WWWForm(); //创建一个WWWForm对象。
  25. form.AddField( "name2", strname );
  26. form.AddField("pwd",strpwd);
  27. var w:WWW=new WWW(URL,form);
  28. yield w; //we wait for the form to check the PHP file, so our game dont just hang
  29. cls=true;
  30. if (w.error != null) {
  31. //if there is an error, tell us
  32. return_data=w.error;
  33. } else {
  34. return_data=w.text;
  35. w.Dispose(); //clear our form in game
  36. }
  37. }
复制代码


4. 此代码放在主相机上。

5.最后在网上搜一个crossdomain.xml文件,自己写也行,把它放在挂有Asp.net网站的根目录下,这样就大功告成了.



6,导入到IPhone手机里也成功访问到数据库.

2016-09-12 13:57:27 c5138891 阅读数 8225
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

第一次写文章!

unity3d 开发项目适配问题处理,实现的结果是宽高比超出的部分相机直接裁掉留黑,如果要加背景可以再挂一个相机填补黑色,代码以横屏为例

using UnityEngine;

/// <summary>
/// 屏幕适配
/// </summary>
[RequireComponent(typeof(Camera))]
public class ScreenAdapt : MonoBehaviour
{
	public float screenHeight;
	public float screenWidth;

	void Start()
	{
		UpdateCamera ();
	}
	
	void UpdateCamera ()
	{
		screenHeight = Screen.height;
		screenWidth = Screen.width;

		Rect r = new Rect();
		if(screenHeight / screenWidth > 0.61f)//更方的屏幕 480*800
		{
			r.width = 1;
			r.height = (screenWidth * 0.61f) / screenHeight;
			r.x = 0;
			r.y = (1 - r.height) / 2f;
		}	
		else if(screenHeight / screenWidth < 0.56f)//更长的屏幕480*854
		{
			
			r.width = (screenHeight / 0.56f) / screenWidth;
			r.height = 1f;
			r.x = (1 - r.width) / 2f;
			r.y = 0;
		}
		else //在可适配区域不做处理480*800 - 480*854之间的
		{
			r.width = 1;
			r.height = 1;
			r.x = 0;
			r.y = 0f;
		}
		GetComponent<Camera>().rect = r;
	}
}

直接将脚本挂在需要适配的相机上即可,

原理就是修改的相机的视口


这样处理后,即可完美适配,建议pause/resume 后做一次刷新



http://blog.csdn.net/c5138891/article/details/52512881

2016-02-23 14:56:48 wsc122181582 阅读数 1735
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4646 人正在学习 去看看 张刚

开发项目:RPG黑暗之光单机


开发软件:Unity5.3+VS2015


开发时间:30天


开发过程:

1.场景搭建

2.开始界面,角色选择界面

3.角色控制(移动,视角,视野,状态机)

4.功能模块

(1)任务

(2)背包,物品

(3)状态

(4)装备

(5)技能

(6)商店(武器,药品)

5.游戏界面(头像,血量,经验,地图,功能栏,快捷栏)

6.敌人控制(状态机)

7.战斗系统、技能系统


开发技术:UGUI、DOTween、读取txt文档、

Unity3D 事件优化

阅读数 9

没有更多推荐了,返回首页