UGUI架构的应用案例——用户登录
输入用户名及密码,点击登录按钮后提交登录请求至PhotonServer,再通过PhotonServer返回的消息进行展示。若有错误即弹出提示框,若成功则切换场景。
效果展示
目录结构
UI组件情况
UI_Title -> UIInfo
UIScene_Login->UILogin->UIScene
UIScene_Popup->UIPopup->UIScene
btnLogin->UISceneWidget
分析
根据描述可以看出,进入场景后,UIScene_Login是默认显示的, UIScene_Popup 是当提示错误时才显示。因为界面显示是通过UIInfo调用UIManager进行初始化显示的,所以需要添加UIManager代码
只显示UILogin,默认所有UIScene将被隐藏,所以只需要设置需要显示的UIScene
//显示一级界面
public UIScene SetTitleVisible(bool visible)
{
return SetVisible(UIName.UILogin, visible);
}
UIName是一个常量类,因为是通过名字去进行缓存,所以命名需要规范
public class UIName
{
public const string UILogin = "UIScene_Login";
public const string UIPopup = "UIScene_Popup";
}
然后在UIInfo初始化方法里面进行调用
void InitUIManager()
{
Object obj = FindObjectOfType(typeof(UIManager));
if (obj != null)
uiManager = obj as UIManager;
if (uiManager == null)
{
GameObject manger = new GameObject("UIManager");
uiManager = manger.AddComponent<UIManager>();
}
uiManager.InitializeUIs(); //初始化UIManager
uiManager.SetTitleVisible(true);//显示开始游戏一级界面
}
界面显示初始化做完了,然后就是登录按钮的点击事件了,因为登录按钮已经被添加了UISceneWidget组件,所以它已经被缓存进了UIScene里面,我们只需要在UIScene里面注册登录按钮的点击响应事件就行。
public class UILogin : UIScene {
private UISceneWidget m_BtnLogin;
private Text m_IptName;
private Text m_IptPassword;
protected override void Start()
{
base.Start();
InitWidget();
}
void InitWidget()
{
//从缓存中得到UISceneWidget
m_BtnLogin = GetWidget("btnLogin");
//注册点击事件
if(m_BtnLogin != null)
m_BtnLogin.PointerClick += BtnLoginOnClick;
m_IptName = UIHelper.FindChild<Text>(transform, "iptName/Text");
m_IptPassword = UIHelper.FindChild<Text>(transform, "iptPassword/Text");
}
private void BtnLoginOnClick(PointerEventData obj)
{
//发送服务端请求,传入输入框中的账号和密码,然后提交至Server
if (PhotonManager.Instance.IsConnected)
{
string json = JsonMapper.ToJson(new AccountEntity() { Name = m_IptName.text, Password = m_IptPassword.text });
Dictionary<byte, object> parameter = new Dictionary<byte, object>();
parameter.Add((byte)OperationCode.Login, json);
PhotonManager.Instance.Peer.OpCustom((byte)OperationCode.Login, parameter, true);
}
}
}
服务端代码
UserLoginValidateHandler
所有提示信息被放入了后台资源文件易于管理
public class UserLoginValideHandler : IValidateHandler<UserLoginCommand>
{
private readonly AccountRepository accountRepository;
private UnitOfWork unitOfWork;
public UserLoginValideHandler()
{
unitOfWork = new UnitOfWork();
accountRepository = new AccountRepository(unitOfWork.Session);
}
public ValidationResult Validate(UserLoginCommand command)
{
ValidationResult result = null;
if (string.IsNullOrEmpty(command.Name.Trim()))
{//传入用户名为空,则提示“用户名不能为空”
result = new ValidationResult(Resource.NameRequire);
}
else if (string.IsNullOrEmpty(command.Password.Trim()))
{//若密码为空,则提示“密码不能为空”
result = new ValidationResult(Resource.PasswordRequire);
}
else
{
AccountEntity account = accountRepository.FindBy(
x => x.Name == command.Name && x.Password == command.Password);
unitOfWork.Commit();
if (account == null)
{//若用户为能找到,则提示“用户名或密码错误”
result = new ValidationResult(Resource.AccountNotFound);
}
else if (account.IsLogin)
{//若用户已经登录,则提示“用户已经登录”
result = new ValidationResult(Resource.AccountIsLogin);
}
}
return result;
}
}
UserLoginHandler
验证通过后执行,更改用户IsLogin状态
public class UserLoginHandler : ICommandHandler<UserLoginCommand>
{
private readonly AccountRepository accountRepository;
private UnitOfWork unitOfWork;
public UserLoginHandler()
{
unitOfWork = new UnitOfWork();
accountRepository = new AccountRepository(unitOfWork.Session);
}
public ICommandResult Excute(UserLoginCommand command)
{
AccountEntity account = accountRepository.FindBy(x => x.Name == command.Name && x.Password == command.Password);
account.IsLogin = true;
account.LoginTime = DateTime.Now;
accountRepository.Update(account);
unitOfWork.Commit();
return new CommandResult(true);
}
}
OK 搞定。