Unity中的MVC框架

基本概念

MVC全名是Model View Controller
是模型(model)-视图(view)-控制器(controller)的缩写
是一种软件设计规范,用一种业务逻辑、数据、界面显示 分离的方法组织代码
将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

MVC在游戏开发中不是必备的,它主要用于开发游戏UI系统逻辑

前期准备

接下来要实现一个小的UI面板,分别实现不使用MVC框架和使用MVC框架的代码,以此作为对比。

Canvas设置

非MVC框架实现

主面板逻辑

MainPanel.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainPanel : MonoBehaviour
{//1.获得控件public Text txtName;public Text txtLev;public Text txtMoney;public Text txtGem;public Text txtPower;public Button btnRole;private static MainPanel panel;//2.添加事件//3.更新信息//4.动态显隐//使用静态方法,让NormalMain能够调用public static void ShowMe(){if(panel == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/MainPanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);panel = obj.GetComponent<MainPanel>();}//如果隐藏形式是setacive,则显示也要setpanel.gameObject.SetActive(true);//显示完面板 更新panel.UpdateInfo();}public static void HideMe(){if(panel != null){//一. 直接删// Destroy(panel.gameObject);// panel = null;//二. 隐藏panel.gameObject.SetActive(false);}}// Start is called before the first frame update void Start(){//2.添加事件btnRole.onClick.AddListener(ClickBtnRole);}private void ClickBtnRole(){//打开角色面板的逻辑Debug.Log("按钮点击");}//3.更新信息public void UpdateInfo(){//获取玩家数据 更新玩家信息//获取玩家数据的方式 1.网络请求  2.Json  3.xml  4.2进制  5.PlayerPrefs公共类//通过PlayerPrefs来获取本地存储的玩家信息 更新到界面上txtName.text = PlayerPrefs.GetString("PlayerName","阿喆不想学习");txtLev.text = "LV." + PlayerPrefs.GetInt("PlayerLev",1).ToString();txtMoney.text = PlayerPrefs.GetInt("PlayerMoney",999).ToString();txtGem.text = PlayerPrefs.GetInt("PlayerGem",888).ToString();txtPower.text = PlayerPrefs.GetInt("PlayerPower",10).ToString();}
}

NormalMain.cs

    void Update(){if(Input.GetKeyDown(KeyCode.M)){//显示主面板MainPanel.ShowMe();}else if(Input.GetKeyDown(KeyCode.N)){//隐藏主面板MainPanel.HideMe();}}

角色面板逻辑

RolePanel.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class RolePanel : MonoBehaviour
{//1.获得控件public Text txtLev;public Text txtHp;public Text txtAtk;public Text txtDef;public Text txtCrit;public Text txtMiss;public Text txtLuck;public Button btnClose;public Button btnLevUp;private static RolePanel panel;//2.添加事件//3.更新信息//4.动态显隐// Start is called before the first frame update public static void ShowMe(){if(panel == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/RolePanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);panel = obj.GetComponent<RolePanel>();}//如果隐藏形式是setacive,则显示也要setpanel.gameObject.SetActive(true);//显示完面板 更新panel.UpdateInfo();}public static void HideMe(){if(panel != null){//一. 直接删// Destroy(panel.gameObject);// panel = null;//二. 隐藏panel.gameObject.SetActive(false);}}void Start(){btnClose.onClick.AddListener(()=>{HideMe();});btnLevUp.onClick.AddListener(()=>{//升级就是数据更新//这里就是获取本地数据int lev = PlayerPrefs.GetInt("PlayerLev",1);int hp= PlayerPrefs.GetInt("PlayerHp",100);; int def= PlayerPrefs.GetInt("PlayerDef",10);int atk= PlayerPrefs.GetInt("PlayerAtk",20);int crit= PlayerPrefs.GetInt("PlayerCrit",20);int miss= PlayerPrefs.GetInt("PlayerMiss",10);int luck= PlayerPrefs.GetInt("PlayerLuck",40);//然后根据升级规则去改变他lev += 1;hp += lev;atk += lev;def += lev;crit += lev;miss += lev;luck += lev;//存起来PlayerPrefs.SetInt("PlayerLev",lev);PlayerPrefs.SetInt("PlayerHp",hp);PlayerPrefs.SetInt("PlayerAtk",atk);PlayerPrefs.SetInt("PlayerDef",def);PlayerPrefs.SetInt("PlayerCrit",crit);PlayerPrefs.SetInt("PlayerMiss",miss);PlayerPrefs.SetInt("PlayerLuck",luck);//同步更新面板上的数据UpdateInfo();//更新主面板的数据MainPanel.Panel.UpdateInfo();});}//更新信息public void UpdateInfo(){txtLev.text = "LV." + PlayerPrefs.GetInt("PlayerLev",1).ToString();txtHp.text = PlayerPrefs.GetInt("PlayerHp",100).ToString();txtAtk.text = PlayerPrefs.GetInt("PlayerAtk",20).ToString();txtDef.text = PlayerPrefs.GetInt("PlayerDef",10).ToString();txtCrit.text = PlayerPrefs.GetInt("PlayerCrit",20).ToString();txtMiss.text = PlayerPrefs.GetInt("PlayerMiss",10).ToString();txtLuck.text = PlayerPrefs.GetInt("PlayerLuck",40).ToString();}
}

MainPanel更新

    public static MainPanel Panel{get{return panel;}} private void ClickBtnRole(){//打开角色面板的逻辑RolePanel.ShowMe();}

MVC框架实现

Model数据脚本

using System.Collections;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
using UnityEngine;
using UnityEngine.Events;/// <summary>
/// 作为一个唯一的数据模型
/// 一般情况下 要不自己是个单例模式对象 
/// 要么自己存在在一个单例模式中
/// </summary>
public class PlayerModel
{//数据内容private string playerName;//用属性是为了能让外部得到它但不能改变他public string PlayerName{get{return playerName;}}private int lev;public int Lev{get{return lev;}}private int money;public int Money{get{return money;}}private int gem;public int Gem{get{return gem;}}private int power;public int Power{get{return power;}}private int hp;public int Hp{get{return hp;}}private int atk;public int Atk{get{return atk;}}private int def;public int Def{get{return def;}}private int crit;public int Crit{get{return crit;}}private int miss;public int Miss{get{return miss;}}private int luck;public int Luck{get{return luck;}}//通知外部更新的事件//通过它来与外部建立联系 而不是直接获取外部的面板private event UnityAction<PlayerModel> updateEvent;//在外部第一次获取这个数据 如何获取//通过单例模式 来达到数据的唯一性 和数据获取private static PlayerModel data = null;public static PlayerModel Data{get{if(data == null){data = new PlayerModel();data.Init();}return data;}}//数据相关的操作//   初始化public void Init(){playerName = PlayerPrefs.GetString("PlayerName","阿喆不想学习");lev = PlayerPrefs.GetInt("PlayerLev",1);money = PlayerPrefs.GetInt("PlayerMoney",9999);gem = PlayerPrefs.GetInt("PlayerGem",8888);power = PlayerPrefs.GetInt("PlayerPower",99);hp= PlayerPrefs.GetInt("PlayerHp",100);; def= PlayerPrefs.GetInt("PlayerDef",10);atk= PlayerPrefs.GetInt("PlayerAtk",20);crit= PlayerPrefs.GetInt("PlayerCrit",20);miss= PlayerPrefs.GetInt("PlayerMiss",10);luck= PlayerPrefs.GetInt("PlayerLuck",40);}//   更新  在这里是升级public void LevUp(){//升级 改变内容lev += 1;hp += lev;atk += lev;def += lev;crit += lev;miss += lev;luck += lev;//改变后保存SaveData();}//   保存public void SaveData(){//把这些数据内容 存储到本地PlayerPrefs.SetString("PlayerName",playerName);PlayerPrefs.SetInt("PlayerLev",lev);PlayerPrefs.SetInt("PlayerMoney",money);PlayerPrefs.SetInt("PlayerGem",gem);PlayerPrefs.SetInt("PlayerPower",power);PlayerPrefs.SetInt("PlayerHp",hp);PlayerPrefs.SetInt("PlayerAtk",atk);PlayerPrefs.SetInt("PlayerDef",def);PlayerPrefs.SetInt("PlayerCrit",crit);PlayerPrefs.SetInt("PlayerMiss",miss);PlayerPrefs.SetInt("PlayerLuck",luck);UpdateInfo();}public void AddEventListener(UnityAction<PlayerModel> function){updateEvent += function;}public void RemoveEventListener(UnityAction<PlayerModel> function){updateEvent -= function;}//通知外面更新数据的方法private void UpdateInfo(){//找到对应的 使用数据的脚本 去更新数据if(updateEvent != null){updateEvent(this);}}
}

View界面脚本

MainView.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainView : MonoBehaviour
{//1.找控件public Text txtName;public Text txtLev;public Text txtMoney;public Text txtGem;public Text txtPower;public Button btnRole;public Button btnSkill;//2.提供面板更新的方法给外部public void UpdateInfo(PlayerModel data){txtName.text = data.PlayerName;txtLev.text = "LV." + data.Lev;txtMoney.text = data.Money.ToString();txtGem.text = data.Gem.ToString();txtPower.text = data.Power.ToString();}
}

RoleView.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class RoleView : MonoBehaviour
{//1.找控件public Text txtLev;public Text txtHp;public Text txtAtk;public Text txtDef;public Text txtCrit;public Text txtMiss;public Text txtLuck;public Button btnClose;public Button btnLevUp;//2.提供面板更新的相关方法给外部public void UpdateInfo(PlayerModel data){txtLev.text = "LV." + data.Lev;txtHp.text = data.Hp.ToString();txtAtk.text = data.Atk.ToString();txtDef.text = data.Def.ToString();txtCrit.text = data.Crit.ToString();txtMiss.text = data.Miss.ToString();txtLuck.text = data.Luck.ToString();}
}

Controller业务逻辑

MainController

using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine;/// <summary>
/// Controller要处理的东西 就是业务逻辑
/// </summary>
public class MainController : MonoBehaviour
{//能够在Controller中得到界面才行private MainView mainView;//面板之间的交互都是通过Controller来实现,我们不想让mainView也变成静态被其它访问,//因此可以设置个静态的 Controller,因为Controller也要被外部访问private static MainController controller = null;public static MainController Controller{get{return controller;}}//1.界面的显隐public static void ShowMe(){if(controller == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/MainPanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);controller = obj.GetComponent<MainController>();}//如果隐藏形式是setacive,则显示也要setcontroller.gameObject.SetActive(true);}public static void HideMe(){if(controller != null){controller.gameObject.SetActive(false);}}private void Start(){//获取同样挂载在一个对象上的 view脚本mainView = this.GetComponent<MainView>();//第一次更新mainView.UpdateInfo(PlayerModel.Data);//2.界面 事件的监听 来处理对应的业务逻辑mainView.btnRole.onClick.AddListener(ClickRoleBtn);//PlayerModel.Data.AddEventListener(mainView.UpdateInfo);PlayerModel.Data.AddEventListener(UpdateInfo);}private void ClickRoleBtn(){RoleController.ShowMe();}//3. 界面的更新private void UpdateInfo(PlayerModel data){if(mainView != null){mainView.UpdateInfo(data);}    }private void OnDestroy() {PlayerModel.Data.RemoveEventListener(UpdateInfo);}
}

RoleController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline;public class RoleController : MonoBehaviour
{private RoleView roleView;private  static RoleController controller = null;public static RoleController Controller{get{return controller;}}public static void ShowMe(){if(controller == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/RolePanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);controller = obj.GetComponent<RoleController>();}//如果隐藏形式是setacive,则显示也要setcontroller.gameObject.SetActive(true);}public static void HideMe(){if(controller != null){controller.gameObject.SetActive(false);}}void Start(){roleView = this.GetComponent<RoleView>();//第一次更新面板roleView.UpdateInfo(PlayerModel.Data);roleView.btnClose.onClick.AddListener(ClickCloseBtn);roleView.btnLevUp.onClick.AddListener(ClickLevUpBtn);//PlayerModel.Data.AddEventListener(roleView.UpdateInfo);PlayerModel.Data.AddEventListener(UpdateInfo);}private void ClickCloseBtn(){HideMe();}private void ClickLevUpBtn(){//通过数据模块 进行升级 达到数据改变PlayerModel.Data.LevUp();}// Update is called once per frameprivate void UpdateInfo(PlayerModel data){if(roleView != null){roleView.UpdateInfo(data);}    }private void OnDestroy() {PlayerModel.Data.RemoveEventListener(UpdateInfo);}
}

对比与总结

好处

1.各司其职,互不干涉 --编程思路更清晰
2.有利开发中的分工 -- 多人协同开发时,同步并行
3.有利于组件重用  -- 项目换皮时,功能变化小时,提高开发效率

坏处

1.增加了程序文件的体量  -- 脚本由一变三
2.增加了结构的复杂性  --对于不清楚MVC原理的人不友好
3.效率相对较低     -- 对象之间的相互跳转,始终伴随着一定开销

扩展

MVC的美中不足

M和V之间存在着联系,也就是数据和界面之间存在着耦合性,当数据结构改变时会牵扯界面逻辑随之改动。
在MVC中当需求变化时,需要维护的对象数量会增加

如这一段

改变了PlayerModel中的变量的话,则MainView里的这个函数可能也要调整。

MVX

数据和界面是必备的内容
我们可以通过改变X元素来优化原本的MVC
也就是改变联系和处理M(数据)和V(界面)的方式

MVP:切断View和Model的耦合,让Presenter处理一切
MVVM:MVP的升级版,让ViewModel和V进行双向数据绑定,更新VM等同于更新V,反之同理
MVE:用EventCenter事件中心来分发消息

学习MVX的目的
不要拘泥于框架结构和设计模式要找到一个适合自己项目
一个稳定的,有序的,能满足项目需求的实现方式

MVP

全称为模型(Model)-视图(View)一主持人(Presenter)

Model提供数据,View负责界面,Presenter负责逻辑的处理

它是MVC的一种变式,是针对MVC中M和V存在耦合的优化

与MVC的区别:

在MVC中View会直接从Model中读取数据而不是通过 Controller
而在MVP中View并不直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部。

同样是上面的项目

MVP_MainView.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MVP_MainView : MonoBehaviour
{//1.找控件public Text txtName;public Text txtLev;public Text txtMoney;public Text txtGem;public Text txtPower;public Button btnRole;public Button btnSkill;// //2.提供面板更新的方法给外部// public void UpdateInfo(string name, int lev, int money, int gem, int power){//     txtName.text = name;//     txtLev.text = "LV." + lev;//     txtMoney.text = money.ToString();//     txtGem.text = gem.ToString();//     txtPower.text = power.ToString();// }
}

MVP_RoleView.cs

public class MVP_RoleView : MonoBehaviour
{//1.找控件public Text txtLev;public Text txtHp;public Text txtAtk;public Text txtDef;public Text txtCrit;public Text txtMiss;public Text txtLuck;public Button btnClose;public Button btnLevUp;//2.提供面板更新的相关方法给外部//方法可选 到时候可以直接在P里面通过访问控件 去修改}

MainPresenter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MainPresenter : MonoBehaviour
{//能够在Presenter中得到界面才行private MVP_MainView mainView;//面板之间的交互都是通过Controller来实现,我们不想让mainView也变成静态被其它访问,//因此可以设置个静态的 Controller,因为Controller也要被外部访问private static MainPresenter presenter = null;public static MainPresenter Presenter{get{return presenter;}}//1.界面的显隐public static void ShowMe(){if(presenter == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/MainPanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);presenter = obj.GetComponent<MainPresenter>();}//如果隐藏形式是setacive,则显示也要setpresenter.gameObject.SetActive(true);}public static void HideMe(){if(presenter != null){presenter.gameObject.SetActive(false);}}private void Start(){//获取同样挂载在一个对象上的 view脚本mainView = this.GetComponent<MVP_MainView>();//第一次更新//mainView.UpdateInfo(PlayerModel.Data);//通过P自己的更新方法来更新UpdateInfo(PlayerModel.Data);//2.界面 事件的监听 来处理对应的业务逻辑mainView.btnRole.onClick.AddListener(ClickRoleBtn);//PlayerModel.Data.AddEventListener(mainView.UpdateInfo);PlayerModel.Data.AddEventListener(UpdateInfo);}private void ClickRoleBtn(){//RoleController.ShowMe();RolePresenter.ShowMe();}//3. 界面的更新private void UpdateInfo(PlayerModel data){if(mainView != null){//mainView.UpdateInfo(data);//以前是把数据M传到V中去更新,现在全部由P来做mainView.txtName.text = data.PlayerName;mainView.txtLev.text = "LV." + data.Lev;mainView.txtMoney.text = data.Money.ToString();mainView.txtGem.text = data.Gem.ToString();mainView.txtPower.text = data.Power.ToString();}    }private void OnDestroy() {PlayerModel.Data.RemoveEventListener(UpdateInfo);}
}

RolePresenter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RolePresenter : MonoBehaviour
{private MVP_RoleView roleView;private  static RolePresenter presenter = null;public static RolePresenter Presenter{get{return presenter;}}public static void ShowMe(){if(presenter == null){//实例化面板对象GameObject res = Resources.Load<GameObject>("UI/RolePanel");GameObject obj = Instantiate(res);//设置父对象obj.transform.SetParent(GameObject.Find("Canvas").transform,false);presenter = obj.GetComponent<RolePresenter> ();}//如果隐藏形式是setacive,则显示也要setpresenter.gameObject.SetActive(true);}public static void HideMe(){if(presenter != null){presenter.gameObject.SetActive(false);}}void Start(){roleView = this.GetComponent<MVP_RoleView>();//第一次更新面板UpdateInfo(PlayerModel.Data);roleView.btnClose.onClick.AddListener(ClickCloseBtn);roleView.btnLevUp.onClick.AddListener(ClickLevUpBtn);//PlayerModel.Data.AddEventListener(roleView.UpdateInfo);PlayerModel.Data.AddEventListener(UpdateInfo);}private void ClickCloseBtn(){HideMe();}private void ClickLevUpBtn(){//通过数据模块 进行升级 达到数据改变PlayerModel.Data.LevUp();}// Update is called once per frameprivate void UpdateInfo(PlayerModel data){if(roleView != null){//直接在p中得到V界面的控件,断开M和V的联系roleView.txtLev.text = "LV." + data.Lev;roleView.txtHp.text = data.Hp.ToString();roleView.txtAtk.text = data.Atk.ToString();roleView.txtDef.text = data.Def.ToString();roleView.txtCrit.text = data.Crit.ToString();roleView.txtMiss.text = data.Miss.ToString();roleView.txtLuck.text = data.Luck.ToString();}    }private void OnDestroy() {PlayerModel.Data.RemoveEventListener(UpdateInfo);}
}

MVP同样由缺点,Presenter中的逻辑很多。

但是之后逻辑修改也只用在Presenter中。

MVVM

全称为模型(Model)-视图(View)-视图模型(ViewModel)
Model提供数据,View负责界面,ViewModel负责逻辑的处理
MVVM的由来是MVP(Model-View-Presenter)模式与WPF结合应用时发展演变过来的一种新型框架

数据绑定

将一个用户界面元素(控件)的属性 绑定到 一个类型(对象)实例上的某个属性的方法。

如果开发者有一个MainViewMode类型的实例,那么他就可以把MainViewMode的“Lev”属性绑定到一个Ul中Text的“Text”属性上。“绑定”了这2个属性之后,对Text的Text属性的更改“传播”MainViewMode的Lev属性,而对MainViewMode的Lev属性的更改同样会“传播”到Text的Text属性

MVVM在Unity中水土不服

因为View对象始终由我们来书写,没有UI配置文件(如WPF中的XAML),要想实现传播需要事件/委托,很麻烦。

硬要在Unity中实现MVVM,需要写三模块,并且还要对V和VM进行数据绑定,工作量大,好处也不够明显

Unity的第三方MVVM框架
Loxodon Framework
https://github.com/vovgou/loxodon-framework
uMVVM
https://github.com/MEyes/uMVVM

MVE

全称为模型(Model)-视图(View)-事件中心(EventCenter)
Model提供数据,View负责界面,EventCenter负责数据传递

好处:

利用事件中心的观察者模式
让M和V层的之间的关系更加灵活多变
减少了目前数据层的负载
将数据层事件全部交由事件中心处理

总结

铁打的M和V,流水的X
数据和界面是必备的内容
我们可以通过改变X元素来优化原本的MVC
也就是改变联系和处理M(数据)和V(界面)的方式

不要拘泥于框架结构和设计模式要找到一个适合自己项目的
一个稳定的,有序的,能满足项目需求的实现方式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19812.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【嵌入式硬件】DRV8874电机驱动

目录 1 芯片介绍 1.1 特性简介 1.2 引脚配置 1.3 最佳运行条件 2 详细说明 2.1 PMODE配置控制模式 2.1.1 PH/EN 控制模式 2.1.2 PWM 控制模式 2.1.3 独立半桥控制模式 2.2 电流感测和调节 2.2.1 IPROPI电流感测 2.2.2 IMODE电流调节 3.应用 3.1设计要求 3.2 设计…

AI换脸FaceFusion一键云部署指南

大家好&#xff0c;从我开始分享到现在&#xff0c;收到很多朋友的反馈说配置很低玩不了AI。本篇是一个云端部署AI项目的指南&#xff0c;帮助大家在云端进行AI项目的部署。我会从云平台的选择、代码部署、保存镜像几个方面进行详细的介绍。没有代码基础的小白也不用担心&#…

乐观锁 or 悲观锁 你怎么选?

你有没有听过这样一句话&#xff1a;悲观者正确&#xff0c;乐观者成功​。那么今天我来分享下什么是乐观锁​和悲观锁。 乐观锁和悲观锁有什么区别&#xff0c;它们什么场景会用 乐观锁 乐观锁基于这样的假设&#xff1a;多个事务在同一时间对同一数据对象进行操作的可能性很…

工厂模式详情

一.介绍工厂模式的用途与特点 工厂方法模式是一种创建型设计模式&#xff0c; 其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例化对象的类型。定义工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口&#xff0c;但让实现这个接口的类来决定实例…

Python导出Jira列表

import requests import urllib3 urllib3.disable_warnings() from jira import JIRA import pandas as pd def login_jira(username,password):jira JIRA("https://jira.cn/",basic_auth(username,password))#projectsjira.project(id13)# jqlproject"云链-…

基于强化学习的控制率参数自主寻优

1.介绍 针对控制建模与设计场景中控制参数难以确定的普遍问题&#xff0c;提出了一种基于强化学习的控制律参数自主优化解决方案。该方案以客户设计的控制律模型为基础&#xff0c;根据自定义的控制性能指标&#xff0c;自主搜索并确定最优的、可状态依赖的控制参数组合。 可…

unity打包的WebGL部署到IIS问题

部署之后会出错&#xff0c;我遇到的有以下几种&#xff1b; 进度条卡住不动 明明已经部署到了IIS上&#xff0c;为什么浏览网页的时候还是过不去或者直接报错。 进度条卡住不动的问题其实就是wasm和data的错误。 此时在浏览器上按F12进入开发者模式查看错误&#xff08;下图…

付费工具逻辑

1.付费推广目的&#xff1a; 传播信息心理暗示&#xff1b;扩大销售&#xff0c;指导消费&#xff1b;树立形象&#xff0c;塑道品牌&#xff1b; 2.付费和免费广告&#xff1a; 付费主要为了增加曝光&#xff1b;免费广告一般比付费广告转化率高&#xff1b; 3.平台广告交…

《Kubernetes部署篇:基于麒麟V10+ARM64架构部署harbor v2.4.0镜像仓库》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;企业级K8s集群运维实战 一、环境信息 K8S版本 操作系统 CPU架构 服务版本 1.26.15 Kylin Linux Advanced Server V10 ARM64 harbor v2.4.0 二、部…

chrome谷歌浏览器开启Gemini Nano模型

前提 确保您的操作系统语言设置为英语(美国) 可能还需要将 Chrome 浏览器的语言更改为英语(美国)。 下载dev或Canary版本Chrome Chrome Canary Chrome Dev 注意:确认您的版本高于 127.0.6512.0。 其中一个Chrome版本不行就切换另外一个版本 绕过性能检查 Tab输入: …

结构体相关习题的补充

结构体相关习题的补充 题目1&#xff1a; 如有以下代码&#xff1a; struct student {int num;char name[32];float score; }stu;则下面的叙述不正确的是&#xff1a;( ) A.struct 是结构体类型的关键字 B.struct student 是用户定义的结构体类型 C.num, score 都是结构体…

正邦科技(day4)

烧录 一、烧录固件二、 通讯模块升级1&#xff1a;USB的方式升级固件2&#xff1a;通过mqtt的方式升级固件3&#xff1a;切换环境 三、 烧录WiFi1&#xff1a;短接2&#xff1a;烧录脚本 设备注意事项&#xff1a; 第一种方式&#xff1a;通信模组和MCU都可以统一烧录BoodLoade…

Oracle Hint /*+APPEND*/插入性能总结

oracle append用法 Oracle中的APPEND用法主要用于提高数据插入的效率。 基本用法&#xff1a;在使用了APPEND选项后&#xff0c;插入数据会直接加到表的最后面&#xff0c;而不会在表的空闲块中插入数据。这种做法不需要寻找freelist中的free block&#xff0c;从而避免了在…

【计算机毕设】基于Spring Boot的课程作业管理系统 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 课程作业管理系统旨在为教师和学生提供一个便捷的平台&#xff0c;用于发布、提交和评定课程作业。本系统旨在提高作业管理的效率&#xff0c;促进教…

Golang反射

文章目录 基本介绍reflect包reflect.Typereflect.Valuereflect.Kind具体类型、空接口与reflect.Value的相互转换 反射应用场景修改变量的值访问结构体的字段信息调用变量所绑定的方法实现函数适配器创建任意类型的变量 基本介绍 基本介绍 在Go中&#xff0c;反射&#xff08;re…

错误 0x80070570:文件或目录损坏且无法读取/无法访问[拒绝访问]-解决方法

1.起因&#xff1a;在挪动&#xff35;盘文件时&#xff0c;出现无法移动的报错提示&#xff1a; and无法访问[拒绝访问]: 2.原因&#xff3b;大多是胡乱拔出&#xff35;盘&#xff3d; &#xff3b;来自0x80070570 文件或目录损坏且无法读取 CHKDSK 修复方法-CSDN博客&#…

【JavaEE进阶】——带你详细了解Spring日志以及配置日志

目录 &#x1f6a9;Spring日志的认识 &#x1f6a9;Spring日志的作用 &#x1f6a9;观察日志 &#x1f6a9;使用日志 &#x1f388;在程序中得到日志对象 &#x1f388;使⽤⽇志对象输出要打印的内容 &#x1f6a9;日志框架的介绍 &#x1f388;门面模式(外观模式&…

Unity实现简单的第一人称控制

先看效果 实现方式 1.首先创建一个脚本 2.编辑脚本内容 付上脚本代码 private float RotationX 0;public float speed 2f;//移动速度// Use this for initializationvoid Start(){Cursor.lockState CursorLockMode.Locked;//锁定鼠标到中心点Cursor.visible false;//隐藏鼠…

(CPU/GPU)粒子继承贴图颜色发射

GetRandomInfo节点(复制贴进scratch pad Scripts) Begin Object Class/Script/NiagaraEditor.NiagaraClipboardContent Name"NiagaraClipboardContent_22" ExportPath/Script/NiagaraEditor.NiagaraClipboardContent"/Engine/Transient.NiagaraClipboardConten…

uni-app+php 生成微信二维码 分销海报

主要代码如下&#xff0c;可直接复制调试参数&#xff1a; //查询当前用户是否有分销海报public function user_poster(){$this->checkAuth();//查询会员信息$user $this->getUserInfoById($this->user_id);if(!empty($user[distribution_img])){$result[data] $use…