Unity3D自学笔记——架构应用(二)选择英雄界面

UGUI架构的应用案例——选择英雄界面

效果展示

这里写图片描述

这里写图片描述

这里写图片描述

描述


通过右边的英雄选择列表,将对应的英雄置于镜头前面,并更新英雄介绍。

步骤

  1. 每个英雄有两个模型,一个位于尽头远点,默认显示并播放Idle动画,一个位于镜头前方,默认隐藏显示时播放hit动画
  2. 选择英雄界面为三个单选按钮,每个单选按钮与两个英雄模型关联,在点击时间中进行处理,对应模型的隐藏和显示
  3. UIInfo初始化时调用PhotoManager从后台取英雄介绍数据并缓存
  4. UIInfo注册UISenceWidget的PointerClick事件,每当按钮进行点击更新对应英雄的介绍面板

目录结构


这里写图片描述

组件情况


UI_CharacterSelection->UIInfo
UIScene_Bottom->UIScene
UIScene_SelectHero->UIScene
UIScene_HeroInfo->UIScene
togHero1->UISceneWidget
togHero2->UISceneWidget
togHero3->UISceneWidget

实现

1.创建英雄近点和远点(目前只有两个英雄),并挂上对应角色模型

这里写图片描述

这里写图片描述

2.单选按钮与角色模型对应,并实现按钮选中后对应模型的显示和隐藏

这里写图片描述

[RequireComponent(typeof(Toggle))]
public class UIToggleObject : MonoBehaviour {
    public GameObject Show;
    public GameObject Hide;
    void Awake()
    {
        GetComponent<Toggle>().onValueChanged.AddListener(OnSelectChanged);
    }

    private void OnSelectChanged(bool isChecked)
    {
            Show.SetActive(isChecked);
            Hide.SetActive(!isChecked);
    }
}

3.英雄信息的读取和缓存

表结构
两个字段一个ID一个描述
这里写图片描述

服务端修改

ALI.ARPG.Operations
构造Entity

[Serializable]
    public class HeroEntity : IEntityIntKey
    {
        public virtual int ID { get; set; }
        public virtual string Desc { get; set; }
    }

由于后面代码需要,对服务端架构做了调整,对Entity做了接口约束,这里把IntKey单独抽取出来是为了扩展以后主键不是int类型的实体,如GUID

public interface IEntity
{
}
public interface IEntityIntKey : IEntity
{
    int ID { get; set; }
}

增加一个OperationCode

public enum OperationCode : byte
    {
        Register,
        Login,
        GetHeroInfo
    }

ALI.ARPG.Data
设置Entity与数据库的映射及构造Hero对应的Repository

public class HeroMap: ClassMap<HeroEntity>
    {
        public HeroMap()
        {
            Table("heroinfo");
            Id(x => x.ID).Column("id");
            Map(x => x.Desc).Column("Desc");
        }
    }
public class HeroRepository : Repository<HeroEntity>
    {
        public HeroRepository(ISession session) : base(session)
        {
        }
    }

ALI.ARPG.Domain
构造ICommand和ICommandHandler,由于获取数据不需要验证,所以不需要ICommandValidate

 public class HeroInfoCommand : ICommand
    {
        public int ID;
    }

由于是获取所有数据,是不需要参数的,但是因为需要通过反射查找对应的Handler所以这里还是需要定义ICommand

public class GetAllHeroInfoHandler : ICommandHandler<HeroInfoCommand>
    {
        private readonly HeroRepository heroRepository;
        private UnitOfWork unitOfWork;

        public GetAllHeroInfoHandler()
        {
            unitOfWork = new UnitOfWork();
            heroRepository = new HeroRepository(unitOfWork.Session);
        }
        public ICommandResult Excute(HeroInfoCommand command)
        {
            IEnumerable<HeroEntity> heroinfos = heroRepository.All();
            unitOfWork.Commit();
            return new CommandResult<HeroEntity>(true, heroinfos);
        }
    }

ALI.ARPG.Server
设置Entity和Command的转换

public class ViewModelToDomainMappingProfile : Profile
    { 
        public ViewModelToDomainMappingProfile()
        {
            this.CreateMap<AccountEntity, UserRegisterCommand>();
            this.CreateMap<AccountEntity, UserLoginCommand>();
            this.CreateMap<HeroEntity, HeroInfoCommand>();
        }
    }
public class DomainToViewModelMappingProfile : Profile
    {
        public DomainToViewModelMappingProfile()
        {
            this.CreateMap<UserRegisterCommand, AccountEntity>();
            this.CreateMap<UserLoginCommand, AccountEntity>();
            this.CreateMap<HeroInfoCommand, HeroEntity>();
        }
    }

AliPeer中增加对OprationCode.GetHeroInfo的响应

protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (AliPeer.log.IsDebugEnabled)
            {
                AliPeer.log.DebugFormat("OnOperationRequest. Code={0}", operationRequest.OperationCode);
            }
            switch (operationRequest.OperationCode)
            {
                case (byte)OperationCode.Register:
                    HandleRegisterOperation(operationRequest, sendParameters);
                    break;
                case (byte)OperationCode.Login:
                    HandleLoginOperation(operationRequest, sendParameters);
                    break;
                case (byte)OperationCode.GetHeroInfo:
                    HandleGetHeroinfoOperation(operationRequest, sendParameters);
                    break;
                default:
                    break;
            }
        }
protected virtual void HandleGetHeroinfoOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            try
            {
                OperationResponse response = new OperationResponse((byte)OperationCode.GetHeroInfo);
                //因为没有ValidateHandler所以直接执行CommandHandler
                CommandResult<HeroEntity> result = commandBus.Submit(new HeroInfoCommand()) as CommandResult<HeroEntity>;
                if (result.Success)
                {
                    response.ReturnCode = (short)ReturnCode.Sucess;
                    Dictionary<byte, object> dict = new Dictionary<byte, object>();
                    string strJson = JsonMapper.ToJson(result.Result);
                    dict.Add((byte)ReturnCode.Sucess, strJson);
                    response.Parameters = dict;
                }
                else
                {
                    response.ReturnCode = (short)ReturnCode.Faild;
                }

                SendOperationResponse(response, sendParameters);
            }
            catch (Exception ex)
            {
                if (AliPeer.log.IsDebugEnabled)
                {
                    AliPeer.log.DebugFormat("Error: {0}", ex.Message);
                }
            }
        }

客户端

PhotonManager
增加一个连接上服务器的事件

public event Action OnConnected;

public void OnStatusChanged(StatusCode statusCode)
    {
        switch (statusCode)
        {
            case StatusCode.Connect:
                Debug.Log("服务器连接成功");
                IsConnected = true;
                if(OnConnected != null)
                {
                    OnConnected();
                }
                break;
            case StatusCode.Disconnect:
            case StatusCode.DisconnectByServer:
            case StatusCode.DisconnectByServerUserLimit:
                Debug.Log("服务器已断开连接, StarusCode:" + statusCode);
                IsConnected = false;
                break;
            default:
                break;
        }

UIHeroInfo
监听服务器连接的事件,连接上就向服务器发起获取英雄列表请求

public class UIHeroInfo : UIScene {
    private Text m_LblDesc;

    protected override void Start()
    {
        base.Start();
        InitWidget();
        //监听服务器连接事件
        PhotonManager.Instance.OnConnected += PhotonServerOnConnected;
    }

    void InitWidget()
    {
        m_LblDesc = UIHelper.FindChild<Text>(transform, "lblDesc");
    }  

    private void PhotonServerOnConnected()
    {
        //获取英雄信息列表
        GetAllHeroInfo();
    }

    public void GetAllHeroInfo()
    {
        if (PhotonManager.Instance.IsConnected)
        {
            Dictionary<byte, object> parameter = new Dictionary<byte, object>();
            parameter.Add((byte)OperationCode.GetHeroInfo, null);
//向服务端发起请求 
           PhotonManager.Instance.Peer.OpCustom((byte)OperationCode.GetHeroInfo, parameter, true);
        }
    }
}

PhotonManager
增加服务器响应时间,获取HeroList,并将其缓存

 public void OnOperationResponse(OperationResponse operationResponse)
    {
        switch ((OperationCode)operationResponse.OperationCode)
        {
            case OperationCode.Login:
                HandleLoginResponse(operationResponse);
                break;
            case OperationCode.Register:
                HandleRegisterResponse(operationResponse);
                break;
            case OperationCode.GetHeroInfo:
                HandleHeroInfoResponse(operationResponse);
                break;
        }
    }

private void HandleHeroInfoResponse(OperationResponse operationResponse)
    {
        switch ((ReturnCode)operationResponse.ReturnCode)
        {
            case ReturnCode.Sucess:
                object json;
                operationResponse.Parameters.TryGetValue((byte)ReturnCode.Sucess, out json);
                if (json != null)
                {
                    JsonData data = JsonMapper.ToObject(json.ToString());
                    AddHeroDataInCache(data);
                }
                break;
        }
    }
//反序列化Json对象,并加入缓存
private void AddHeroDataInCache(JsonData data)
    {
        for (int i = 0; i < data.Count; i++)
        {
            HeroEntity entiy = new HeroEntity();
            entiy.ID = (int)data[i]["ID"];
            entiy.Desc = data[i]["Desc"].ToString();
            PhotonDataCache.AddOrUpdateDataCache(PhotonCacheType.HeroList, entiy);
        }
    }

PhotonDataCache
增加缓存类

public enum PhotonCacheType
{
    HeroList
}
public static class PhotonDataCache
{
    private static readonly Dictionary<PhotonCacheType, Dictionary<int, IEntity>> DataCache = new Dictionary<PhotonCacheType, Dictionary<int, IEntity>>();

    public static void AddOrUpdateDataCache(PhotonCacheType cacheType, int key, IEntity value)
    {
        Dictionary<int, IEntity> dict;
        if (!DataCache.ContainsKey(cacheType))
        {
            dict = new Dictionary<int, IEntity>();
            DataCache.Add(cacheType, dict);
        }

        dict = DataCache.First(x => x.Key == cacheType).Value;

        if (!dict.ContainsKey(key))
        {
            dict.Add(key, value);
        }
        else
        {
            dict[key] = value;
        }
    }

    public static void AddOrUpdateDataCache(PhotonCacheType cacheType, IEntityIntKey entity)
    {
        AddOrUpdateDataCache(cacheType, entity.ID, entity);
    }

    public static IEntity GetValue(PhotonCacheType cacheType, int key)
    {
        if (DataCache.ContainsKey(cacheType))
        {
            Dictionary<int, IEntity> data = DataCache.First(x => x.Key == cacheType).Value;
            if(data !=null)
            {
                return data.First(x => x.Key == key).Value;
            }
        }

        return null;
    }

    public static T GetValue<T>(PhotonCacheType cacheType, int key) where T : IEntity
    {
        IEntity entity = GetValue(cacheType, key);

        if (entity != null)
            return (T)entity;
        return default(T);
    }
}

以上数据已经被放入进缓存,只需要在界面上进行绑定
UISelectHero
初始化,并监听英雄选择按钮点击事件

public class UISelectHero : UIScene {
    private UIHeroInfo m_HeroInfo;

    protected override void Start()
    {
        base.Start();
        InitWidget();
    }

    private void InitWidget()
    {
        m_HeroInfo = UIManager.Instance.GetUI<UIHeroInfo>(UIName.UIHeroInfo);

        for (int i = 0; i < this.GetWidgetCount(); i++)
        {
            UISceneWidget m_TogButton = GetWidget("togHero" + (i + 1));
            if(m_TogButton != null)
            {
                m_TogButton.PointerClick += TogButtonOnPointerClick;
            }
        }
    }

    private void TogButtonOnPointerClick(UnityEngine.EventSystems.PointerEventData obj)
    {
        string heroID = obj.selectedObject.name;
        heroID = heroID.Substring(heroID.Length - 1);
        m_HeroInfo.SetHeroInfo(heroID);
    }
}

UIHeroInfo
更新介绍信息

public void SetHeroInfo(string heroId)
    {
        int id;
        if(Int32.TryParse(heroId, out id))
        {
            HeroEntity heroInfo = PhotonDataCache.GetValue<HeroEntity>(PhotonCacheType.HeroList, id);
            m_LblDesc.text = heroInfo.Desc;
        }
    }   

搞定
这里写图片描述

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
FPGA自学笔记——设计与验证JMB FPGA(可编程逻辑门阵列)是一种可编程的硬件平台,可以实现各种数字电路的设计与验证。本文将简要介绍使用FPGA自学设计与验证JMB(低功耗、高效能、集成度高的多媒体芯片)的过程。 首先,我们需要了解JMB的功能和特性。JMB是一种面向多媒体应用的芯片,具备低功耗、高效能和高集成度的优势。我们需要详细研究JMB的硬件架构和内部模块,包括处理器核、存储器模块、图像和音频处理模块等。 接下来,我们可以使用FPGA开发板来设计和验证JMB。首先,我们需要熟悉FPGA设计工具,例如Vivado或Quartus等。这些工具提供了图形化界面和硬件描述语言(HDL)等设计方法。我们可以使用HDL编写JMB的功能模块,并将其综合为FPGA可执行的位流文件。 在设计完成后,我们需要验证JMB的功能和性能。我们可以使用仿真工具(例如ModelSim或ISE Simulator)来模拟JMB在不同情况下的行为。通过设计测试程序并运行仿真,我们可以验证JMB的各个模块是否正确地工作,是否满足设计要求。 在验证完成后,我们可以将位流文件下载到FPGA开发板中进行智能芯片的物理实现和测试。通过与外部设备的连接以及相关测试程序的运行,我们可以验证JMB在实际硬件中的功能和性能。 总结起来,学习FPGA设计与验证JMB,我们需要熟悉JMB的硬件架构和内部模块,并使用FPGA开发工具进行设计与验证。通过仿真和物理实现测试,我们可以验证JMB的功能和性能。这些过程需要理论知识和实践经验的结合,希望这些笔记能够给你提供一些参考和指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值