来源

从零开始带你开发橙光游戏AVG框架【55课数 收费】
从零开始带你开发橙光游戏AVG框架 unity教程【16课数 免费】

介绍

QuickSheet使用

bug 包报错

可能是我换了untiy版本的原因
Manual sovle

bug ICSharpCode.SharpZipLib重复

导了一个文件夹,有自己的库,也包含GameFramework、UnityGameFramework,暂时先删掉GameFramework、UnityGameFramework就完事了

bug 中文乱码

VS(Visual Studio)更改文件编码
没改utf-8之前修改过,再改成utf-8没用。
再从压缩包拉出来这些乱码的来覆盖掉,也一样没用

stars 无参事件注册

/// <summary>存档,确定取消</summary>
public class EnterBtn : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler
{public AudioSource EnterMusic;//悬停音效public AudioSource DownMusic;//点击音效private void Start(){EnterMusic = gameObject.FindComponentWithTag<AudioSource>(Tags.ENTERMUSIC);DownMusic = gameObject.FindComponentWithTag<AudioSource>(Tags.DOWNMUSIC);}
 /// <summary>/// 获得标签为 tag 的 物体 身上的 T 组件/// </summary>/// <typeparam name="T"></typeparam>/// <param name="go"></param>/// <param name="tag"></param>/// <returns></returns>/// <exception cref="System.Exception"></exception>public static T FindComponentWithTag<T>(this GameObject go, string tag) where T : Component{T res=    GameObject.FindGameObjectWithTag(tag).GetComponent<T>();if (res == null){throw new System.Exception("异常");}return res;}

modify 将开始游戏界面的代码。从UIManager中拆出来

就这结构
GameStart
UIMgr等Mgr
Canvas
Panel

modify GamStart.cs

:MonoBehaviour 作为游戏入口,用来控制脚本顺序,存储脚本。

--------------------------------------------------

modify CameraPos.cs

GameStart

/****************************************************文件:GameStart.cs作者:lenovo邮箱: 日期:2023/4/14 19:58:55功能:游戏入口
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class GameStart : MonoBehaviour{#region 字段AudioMgr audioMgr;#endregion#region 生命void Start(){GameObject.FindGameObjectWithTag(Tags.MAINCAMERA).AddComponent<CameraPos>().Init();//audioMgr.Init();}

CameraPos

/****************************************************文件:作者:WWS日期:2023/04/14 20:10:21功能:看起来有摇晃感*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CameraPos : MonoBehaviour
{public float X;public float speed;//速度 鼠标移动public float rotateX;public void Init(){speed = 0.5f;}void Update(){X = Input.GetAxis(Constants.Mouse_X);   //获得鼠标左右旋转的值rotateX += X * speed;       //乘以速度//Mathf.Clamp,就是说把一个数值规定在 X 和 Y 的数值之间X = Mathf.Clamp( rotateX, -5,5);      transform.eulerAngles = new Vector3(0,X,0);}
}

Tags

/****************************************************文件:Tags.cs作者:lenovo邮箱: 日期:2022/7/15 12:57:58功能:
*****************************************************/public static class Tags
{public const string MAINCAMERA = "MainCamera";

modify LoadCGMgr.cs

未完成 子节点访问父节点的方法,导入QFramework采用事件注册

QFramework 是我跟着 QFramework第三版本 视频做的部分代码,其中包含 事件注册,关键词是 Register,UnRegister,Event,Command
。。。。
点击两个按钮会调用在 确定面板上 的 播放不同音效 的方法.
用 QFramework 可以跑通
。。。。
调用顺序
GameStart
EnterCanvas
EnterPanel
EnterBtn
其中EnterPanel是下文的父节点,EnterBtn是下文的子节点

新建Event

/****************************************************文件:OverButtonEvent.cs作者:lenovo邮箱: 日期:2023/4/15 0:22:20功能:QFramework 第三版本 的事件
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class OverButtonEvent : Event<OverButtonEvent>
{}

父节点注册和调用Event

/****************************************************文件:EnterPanel.cs作者:lenovo邮箱: 日期:2023/4/14 23:49:34功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class EnterPanel : MonoBehaviour
{#region 字段/// <summary>悬停音效</summary>public AudioSource EnterMusic;/// <summary>点击音效</summary>public AudioSource DownMusic;#endregion#region 生命    public void Init(){EnterMusic = gameObject.FindComponentWithTag<AudioSource>(Tags.ENTERMUSIC);DownMusic = gameObject.FindComponentWithTag<AudioSource>(Tags.DOWNMUSIC);OverButtonEvent.Register(PlayEnterMusic);ClickButtonEvent.Register(PlayDownMusic);}private void OnDestroy(){OverButtonEvent.UnRegister(PlayEnterMusic);ClickButtonEvent.UnRegister(PlayDownMusic);}#endregion#region 系统#endregion#region 辅助public void PlayEnterMusic(){EnterMusic.Play();}public void PlayDownMusic(){DownMusic.Play();}#endregion
}

新建Event对应的Command, 将Event塞进Command

/****************************************************文件:OverButtonEvent.cs作者:lenovo邮箱: 日期:2023/4/15 0:22:20功能:QFramework 第三版本 的事件
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class ClickButtonCommand : ICommand
{public void Execute(){ClickButtonEvent.Trigger();}
}

子节点调用Command

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.EventSystems;/// <summary>存档,确定取消</summary>
public class EnterBtn : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler
{#region 系统public void OnPointerDown(PointerEventData eventData){new ClickButtonCommand().Execute();}public void OnPointerEnter(PointerEventData eventData){new OverButtonCommand().Execute();}#endregion}

stars 支持中文

支持中文,先试用下

using System;public static class ResourcesName
{public const string Sprites_丹药 = "Sprites/WindowIMG/丹药";public const string Sprites_五彩石 = "Sprites/WindowIMG/五彩石";

bug 脚本名和节点名没尽量对应

bug 脚本间跨父节点单访问参数

modify Tag的AVGPolt改为PoltCanvas

方便脚本名,标签名,节点名,三者对应

bug 修改 标签 Polt 为 Plot


watch 带标签 CG

类似 AVG/MainCanvas/LoadCGPoltPanel/BG/CG鉴赏/ObjectPanel/PolePre/PoltBG/Polt

modify 新建脚本LoadCGPlotPanel.cs

位置是 AVG/MainCanvas/LoadCGPlotPanel

modify 筛选卡

modify AudioMgr.cs

AudioMgr.cs单例,并且挂到GameStart的子节点上,并且对相关引用进行调整

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AudioMgr : MonoBehaviour
{public List<AudioClip> AudioList;  //音频播放的数组public AudioSource audioSrc;  //音频播放的组件#region 单例private static AudioMgr _instance;public static AudioMgr Instance{get{return _instance;}set{_instance = value;}}#endregionpublic void Init(){Instance = this;AudioList=new List<AudioClip>(6);AudioList.Add( LoadAudioClip("RPGBG") );AudioList.Add( LoadAudioClip("4_孤独之路") );AudioList.Add( LoadAudioClip("5_花散曲终") );AudioList.Add( LoadAudioClip("20絶体絶命の曲") );AudioList.Add( LoadAudioClip("zh05_燃血之时") );AudioList.Add( LoadAudioClip("zh08_狂乱之宴") );}/// <summary>播放音频</summary>public void PlayMusic(int id) {audioSrc.clip = AudioList[id]; audioSrc.Play();  }/// <summary>停止播放播放音频</summary>public void StopMusic() {audioSrc.Stop();  }AudioClip LoadAudioClip(string name){AudioClip audioClip = Resources.Load<AudioClip>("Music/" + name);if (audioClip == null){throw new System.Exception("异常");}return audioClip;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class GameStart : MonoBehaviour
{#region 字段public AudioMgr audioMgr;......#endregion#region 生命void Start(){......//audioMgr=GetComponentInChildren<AudioMgr>();audioMgr.Init();

bug IsUsingDeformableBuffer

unity ‘SpriteRenderer’ does not contain a definition for ‘IsUsingDeformableBuffer’ and no accessible extension method ‘IsUsingDeformableBuffer’ accepting a first argument of type ‘SpriteRenderer’ could be found (are you missing a using

Unity spriteRenderer error what i need to do?
我是2020.3.23fc1,尝试了2没用,尝试了1,有用,没报错了,但是 2D Sprite 估计用到,后面报错再安装

modify AudioSource与AudioMgr

01 将所有 AudioSource 放到 AudioMgr 的子节点上,并且改名了3个。
02 后面有移动了 节点 AVG 上的 AudioSource 到 AudioMgr 的子节点 AVGSrc 上
03 类似AVG/MainCanvas/LoadCGPlotPanel/BG/音乐赏析/BGMusic,也有一个AudioSource

暂时不清楚为什么用那么多AudioSource,放内存应该用字典。(需要同时放?)
原版放在 SettingPanel 上

watch SettingPanel 关系了 音量

也就是做好 SettingPanel 和 AudioMgr 的关系
就是将相关代码 放 AudioMgr,让 SettingPanel 调用(Slider嘛)

modify EnterPanel通过AudioMgr调用AudioSource

前面的 EnterPanel 用到了 这两个 AudioSource ,也放到 AudioMgr 上,通过访问 AudioMgr 来调用
改名为 EnterBtnSrc, DownBtnSrc,省下两个 Tag

两个AudioSource移动 改名 引用 删Tag

EnterPanel 调用

/****************************************************文件:EnterPanel.cs作者:lenovo邮箱: 日期:2023/4/14 23:49:34功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class EnterPanel : MonoBehaviour
{#region 生命     public void Init(){OverButtonEvent.Register(PlayEnterMusic);ClickButtonEvent.Register(PlayDownMusic);}private void OnDestroy(){OverButtonEvent.UnRegister(PlayEnterMusic);ClickButtonEvent.UnRegister(PlayDownMusic);}#endregion#region 系统#endregion#region 辅助public void PlayEnterMusic(){AudioMgr.Instance.EnterBtnSrc.Play();}public void PlayDownMusic(){AudioMgr.Instance.DownBtnSrc.Play();}#endregion
}

modify 将 UIMgr 的部分代码拆到 EnterPanel

Scene 进入游戏---------------------------------

bug 需要传参的事件注册

所以看了
框架搭建 决定版:理论强化篇(第三季) 53课数

自顶向下

自顶向下用方法

自底向上 之一 委托

自底向上用委托、事件

委托要注册,注销。
存在 回调地狱
要声明委托
缺点是,多个子节点都需要访问父节点,每个子节点都要声明委托,麻烦。

父节点PlayerCtrl

namespace FrameworkDesign2021
{public class PlayerCtrl : MonoBehaviour{PlayerAnimationCtrl mAnimationCtrl;void Start(){mAnimationCtrl = transform.Find("Animation").GetComponent<PlayerAnimationCtrl>();// 注册完成的事件mAnimationCtrl.OnDoSomethingDone += OnDoSomethingDone;mAnimationCtrl.DoSomething();}void OnDoSomethingDone(){Debug.Log("动画播放完毕");}void OnDestroy(){// 注销完成的事件mAnimationCtrl.OnDoSomethingDone -= OnDoSomethingDone;}}...
}

子节点 PlayerAnimationCtrl

public class PlayerAnimationCtrl : MonoBehaviour{// 定义委托public Action OnDoSomethingDone = ()=>{};public void DoSomething(){OnDoSomethingDone();}}
}

事件 模块(Module层)之间交互

解除限制,使用自有,需要增加小逻辑,是和模块之间的大颗粒度交互,不合适对象之间的小颗粒度交互

命令 对象之间(Model层)交互

带参数
撤销

bug 找到带参的命令

bug canvas不激活GetComonent不到

modify 将UI的事件id改为枚举,增加可读性

/// <summary>
/// None=1,
/// QuitGame = 2,
/// ReturnMainPanel = 3,
/// SL = 5,
/// Loading = 6,
/// IsLoadPlotBack = 7,
/// IsLoadCG = 8,
/// </summary>
public enum EventID
{None = 1,QuitGame = 2,ReturnMainPanel = 3,/// <summary>存档</summary>SaveFile = 5,/// <summary>打开存档面板,常听的SL大法</summary>OpenSLPanel = 6,/// <summary>剧情</summary>LoadPlot = 7,/// <summary>CG(计算机动画)</summary>LoadCG = 8,}

bug Google.GData.Client

Reference has errors ‘Google.GData.Client’.
不明,莫名其妙的坏了,好了

bug 程序集引用丢失

原本是都在根目录
QFramework
QFrameworkData

改成在Plugins/QFramework就报错了,而且会一直在根目录生成QFrameworkData
QFramework
QFrameworkData

modify AnimationEvent

打算拆出来放在一个文件夹AnimationEvent下

bug TLS Allocator ALLOC_TEMP_THREAD

TLS Allocator ALLOC_TEMP_THREAD, underlying allocator ALLOC_TEMP_THREAD has unfreed allocations, size 40
有些线程没释放
[Report All【没用】]](https://blog.csdn.net/wenshuai537/article/details/123558838)

bug Reference has errors ‘Google.GData.Client’.

Assembly ‘Assets/QuickSheet/GDataPlugin/Editor/Google/Google.GData.Extensions.dll’ will not be loaded due to errors:
Reference has errors ‘Google.GData.Client’.

迷,重启电脑后没了

bug 自己的代码库突然就不被CSharp项目识别了

01 我改了Component拓展方法中 using GameObject = UnityEngine.GameObject;
02 整理时将 QuickSheet 移动到 Plugins,报错;又移动出来,报找不到 meta的 错,重启Unity后就好了
03 重启Unity后,不被CSharp项目识别就好了

modify 整理动画事件

将所有动画事件提取出来,以 节点名_动画名 的方式命名脚本,统一放到一个文件夹

如图所示
01 动画 MainAnim 有两个 事件(也就是方法)
02 这两个方法放在一个脚本里,脚本的命名是 要挂的节点名_动画名
03 将该 动画事件脚本 挂载节点上
原版是将所有的 动画事件都放在一个脚本 AnimManager。动画事件又是 0引用 ,所以难管理。

bug 动画事件调用某些属性顺序

01 动画事件调用某些属性
02 属性在Init()方法中赋值
但 01 比 02 快,导致属性还没赋值就被调用

所以先这样,这是跟Siki学院的Ocean老师学RealFrame时的。就是 等人再干活
Crt 是协程的英文Coroutine,我选的 简写

 /// <summary>关闭菜单按钮</summary>public void HideMainBtn(){StartCoroutine(HideMainBtnCrt());}IEnumerator HideMainBtnCrt(){while (UIMgr.Instance == null|| UIMgr.Instance.MainCanvas == null|| UIMgr.Instance.MainCanvas.MainPanel == null)//需要时间{yield return new WaitForEndOfFrame(); //等一帧 }UIMgr.Instance.MainCanvas.MainPanel.HideMainBtn();}

modify 主界面按钮名

动画认名字【改过变黄,识别不了】(这点不好,应该认uuid)

bug 单例为null

点击 开始游戏 出现的, 照理说这时候什么都初始化好了
F5了,Instance为空
。。。。
MonoBehaviour不能有用new的方式
所以用以下

using UnityEngine;public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>{protected static T mInstance = null;public static T Instance{get{if (mInstance == null){mInstance = FindObjectOfType<T>();if (FindObjectsOfType<T>().Length > 1){Debug.LogWarning("More than 1");return mInstance;}if (mInstance == null){var instanceName = typeof(T).Name;Debug.LogFormat("Instance Name: {0}", instanceName);var instanceObj = GameObject.Find(instanceName);if (!instanceObj)instanceObj = new GameObject(instanceName);mInstance = instanceObj.AddComponent<T>();DontDestroyOnLoad(instanceObj); //保证实例不会被释放Debug.LogFormat("Add New Singleton {0} in Game!", instanceName);}else{Debug.LogFormat("Already exist: {0}", mInstance.name);}}return mInstance;}}protected virtual void OnDestroy(){mInstance = null;}}

stars SetActive()

将大量的SetActive()改成Show()和Hide()

/****************************************************文件:ExtendComponent.ShowHide.cs作者:lenovo邮箱: 日期:2023/4/22 15:32:47功能:QFramework第一季
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public static partial class ExtendComponent
{public static void Show(this GameObject gameObject){gameObject.SetActive(true);}public static void Hide(this GameObject gameObject){gameObject.SetActive(false);}public static void Show(this Transform transform){transform.gameObject.SetActive(true);}public static void Hide(this Transform transform){transform.gameObject.SetActive(false);}public static void Show(this MonoBehaviour monoBehaviour){monoBehaviour.gameObject.SetActive(true);}public static void Hide(this MonoBehaviour monoBehaviour){monoBehaviour.gameObject.SetActive(false);}}

bug unity 运行时busy for卡很久;unity suspendThread loop falied

死锁
猜,断点的地方是用到了映射(自己的一个能得出命名空间、类名、方法名的方法)

modify AVGMachine

将能沉下到各个 Manager 、Canvas、 Panel 的方法沉下去
比如一个方法的参数都是 AudioMgr 中的,直接把这个方法提到 AudioMgr ,再去间接调用

bug C# private不显示

C# private不显示有一会,后面又显示了

modify 区别节点命名

原版是在AVGMainAnim.cs
借点命名都是,如果发生节点丢失很难区分。(虽然有注释)

watch 主菜单花的粒子

/****************************************************文件:作者:WWS日期:2023/04/14 20:10:21功能:看起来有摇晃感*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CameraPos : MonoBehaviour
{public float inputX;public float speed;//速度 鼠标移动public float rotateX;public GameObject Particle;public void Init(){speed = 0.5f;Particle = gameObject.FindChildDeep("Particle");ShowParticle();}void Update(){inputX = Input.GetAxis(Constants.Mouse_X);   //获得鼠标左右旋转的值rotateX += inputX * speed;       //乘以速度inputX = Mathf.Clamp( rotateX, -5,5);        //规定在 X 和 Y 的数值之间transform.eulerAngles = new Vector3(0,inputX,0);}void ShowParticle(){Particle.Show();}
}

bug UnityEditor.Graphs.Edge.WakeUp ()

重启Untiy,猜是编译不及时,好像没转圈圈

NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.Edge.WakeUp () (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)
UnityEditor.Graphs.Graph.DoWakeUpEdges (System.Collections.Generic.List`1[T] inEdges, System.Collections.Generic.List`1[T] ok, System.Collections.Generic.List`1[T] error, System.Boolean inEdgesUsedToBeValid) (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)
UnityEditor.Graphs.Graph.WakeUpEdges (System.Boolean clearSlotEdges) (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)
UnityEditor.Graphs.Graph.WakeUp (System.Boolean force) (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)
UnityEditor.Graphs.Graph.WakeUp () (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)
UnityEditor.Graphs.Graph.OnEnable () (at <1bfd5359178446f5b1ac53f68c0a5db0>:0)

--------------------------------------------------

modify 确定面板 退出游戏

点击悬停音效
原版是直接拖拽节点,我改单例,前面是用无参的事件注册,学会有参在一起改

面板主功能

/****************************************************文件:EnterPanel.cs作者:lenovo邮箱: 日期:2023/4/14 23:49:34功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Random = UnityEngine.Random;public class EnterPanel : MonoBehaviour
{#region 字属Button yesBtn;Button noBtn;   //确认和取消两个按钮Text contentText;public GameObject EnterPanelGo;  //确认面板#endregion#region 生命        public void Init(){InitButton();EnterPanelGo = gameObject;contentText = gameObject.GetComponentDeep<Text>("ContentText");}void InitButton(){ //以后采用事件注册//this.RegisterEvent<OverButtonEvent>( PlayEnterMusic);//this.RegisterEvent<ClickButtonEvent>(PlayDownMusic);yesBtn = gameObject.GetComponentDeep<Button>("YesBtn");noBtn = gameObject.GetComponentDeep<Button>("NoBtn");////yesBtn.gameObject.GetComponent<EnterBtn>();   //markyesBtn.onClick.AddListener( UIMgr.Instance.YesEvent );////yesBtn.gameObject.GetComponent<EnterBtn>();noBtn.onClick.AddListener( NoEvent );}private void OnDestroy(){//  OverButtonEvent.UnRegister(PlayEnterMusic);//   ClickButtonEvent.UnRegister(PlayDownMusic);}#endregion#region 系统#endregion#region 辅助public void NoEvent(){Close();}/// <summary></summary>public void Close(){//当我们按下取消按钮之后//如果我们做动画了GetComponent<Animator>().SetBool(AnimatorPara.Quit, true);  //获得 确认面板上的动画控制器//如果我们没有做动画  只有面板//EnterObject.SetActive(false);   //隐藏确认面板}public void  SetContentText(string value){contentText.text = value;}#endregion
}

面板上的动画事件

/****************************************************文件:EnterPanel_EnterQuit.cs作者:lenovo邮箱: 日期:2023/4/21 20:5:30功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class EnterPanel_EnterQuit : MonoBehaviour
{#region 辅助/// <summary>退出确认面板  就是隐藏 确认面板</summary>public void QuitEnter(){UIMgr.Instance.EnterCanvas.Hide();}#endregion}

按钮音效

同时加到下面4个按钮上

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.EventSystems;/// <summary>存档,确定取消</summary>
public class EnterBtn : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler
{#region 系统public void OnPointerDown(PointerEventData eventData){//new ClickButtonCommand().Execute(); //无参成功,但是有参失败,所以暂时不用AudioMgr.Instance.PlayClickBtnMusic();}public void OnPointerEnter(PointerEventData eventData){//new OverButtonCommand().Execute();AudioMgr.Instance.PlayHoverBtnMusic();}#endregion}

效果

stars 按钮监听 GetButtonDeep

在子节点中找命名为 “ResetBtn” 的按钮, 添加 ResetVolume 的事件, 最后将按钮返回

     ResetBtn = transform.GetButtonDeep("ResetBtn", ResetVolume);
public static Button GetButtonDeep(this Transform root, string childName,   UnityEngine.Events.UnityAction action){Button result   = root.GetButtonDeep(childName);result.onClick.AddListener( action );return result;}/// <summary>/// 深度查找子对象transform引用/// </summary>/// <param name="root">父对象</param>/// <param name="childName">具体查找的子对象名称</param>/// <returns></returns>public static Button GetButtonDeep(this Transform root, string childName){Transform result = null;result = root.Find(childName);if (!result){foreach (Transform item in root){result = FindChildDeep(item, childName);if (result != null){return result.GetComponent<Button>();}}}return result.GetComponent<Button>();}/// <summary>/// 深度查找子对象transform引用/// </summary>/// <param name="root">父对象</param>/// <param name="childName">具体查找的子对象名称</param>/// <returns></returns>public static Transform FindChildDeep(this Transform root, string childName){Transform result = null;result = root.Find(childName);if (!result){foreach (Transform item in root){result = FindChildDeep(item, childName);if (result != null){return result;}}}return result;}

--------------------------------------------------

modify 设置面板

子脚本有ScreenSettings 。语言设置没做,屏幕设置好像没有效果。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Linq;
using Slider = UnityEngine.UI.Slider;
using System;public class SettingsPanel : MonoBehaviour
{#region 字属//这部分应该新建一个SLMgr(Save And Load,设置、存档)来保存public float TextSpeed = 10;   //文本显示的速度public float TextAutoSpeed = 10;   //文本自动跳转下一句的速度public float DialogBoxAlpha = 0.8F;   //对话框文本的透明度//public List<Slider> SliderLst=new List<Slider>();   //获得滚动条合集[SerializeField] ScreenSettings ScreenSettings ;[Header("Button")][SerializeField] Button ResetBtn;[SerializeField] Button BackBtn;[SerializeField] Button GoMainBtn;[SerializeField] Button QuitGameBtn;#endregion#region 生命public void Init(){TextSpeed = 10;TextAutoSpeed = 10;DialogBoxAlpha = 0.8F;//InitSliderLst();//ScreenSettings = gameObject.GetComponentDeep<ScreenSettings>("ScreenSettings");ScreenSettings.Init();//ReadSettingIfExist();SetSliderValue();   //把数据赋值给滚动条的value值//InitButton();}private void Update(){UpdateValue();UpdateSlider();  }#endregion#region 辅助void InitButton(){ResetBtn = transform.GetButtonDeep("ResetBtn", ResetVolume);BackBtn = transform.GetButtonDeep("BackBtn", HideSettingPanel);GoMainBtn = transform.GetButtonDeep("GoMainBtn", GoMain);QuitGameBtn = transform.GetButtonDeep("QuitGameBtn", QuitGame);}void QuitGame(){UIMgr.Instance.QuitGame();}void GoMain(){UIMgr.Instance.GoMainPanel();}/// <summary>隐藏设置界面</summary>public void HideSettingPanel(){SaveValue();  gameObject.Hide();  }void ReadSettingIfExist(){string path = Application.persistentDataPath + "/Setting";if (File.Exists(path))//判断当前文件路径 是否有 Setting的 文件{//如果 有  就执行 读取文件,并且解析文件里面的数据内容BinaryFormatter bf = new BinaryFormatter();FileStream fs = File.Open(path, FileMode.Open);SettingData saveData = (SettingData)bf.Deserialize(fs);//反序列化数据  fs.Close();SetGameData(saveData);}else//如果没有文件{SaveValue();  //存储文件的方法}}void InitSliderLst(){SliderLst = gameObject.GetComponentsInChildren<Slider>().ToList();}/// <summary>更新数据</summary>public void UpdateValue() {AudioMgr.Instance.UpdateValue();UIMgr.Instance.SetDialogBoxAlpha(DialogBoxAlpha)  ;   //把对话框文本的透明度赋值AVGMachine.Instance.TextSpeed = TextSpeed;   //把速度赋值过去}/// <summary>把滚动条里面的参数  赋值给   当前脚本上面的参数</summary>public void UpdateSlider() {TextSpeed = SliderLst[0].value;   //把第一个滚动条的参数赋值给 文字速度TextAutoSpeed = SliderLst[1].value;DialogBoxAlpha = SliderLst[2].value;//AudioMgr.Instance.TotalVolume = SliderLst[3].value;AudioMgr.Instance.BgVolume = SliderLst[4].value;AudioMgr.Instance.EffectVolume = SliderLst[5].value;AudioMgr.Instance.RoleVolume = SliderLst[6].value;}/// <summary>把数据赋值给滚动条的value值</summary>public void SetSliderValue(){SliderLst[0].value = TextSpeed;   //把文字打印的速度 赋值给 第一个滚动条SliderLst[1].value = TextAutoSpeed;   SliderLst[2].value = DialogBoxAlpha; //SliderLst[3].value = AudioMgr.Instance.TotalVolume;  SliderLst[4].value = AudioMgr.Instance.BgVolume;   SliderLst[5].value = AudioMgr.Instance.EffectVolume;   SliderLst[6].value = AudioMgr.Instance.RoleVolume;   }/// <summary>存储数据的方法</summary>public void SaveValue() {SettingData save = CreateSaveGo();    // 接收存档数据信息 BinaryFormatter bf = new BinaryFormatter();  //实例化FileStream fs = File.Create(Application.persistentDataPath +"/Setting");  //创建一个名为 Setting的文件bf.Serialize(fs,save);  //序列化fs.Close();  //关掉}/// <summary>创建存档数据信息</summary>public SettingData CreateSaveGo(){SettingData save = new SettingData();    //实例化一个 存储数据save.TextSpeed = TextSpeed;   save.TextAutoSpeed = TextAutoSpeed; save.WindowAlpha = DialogBoxAlpha;   save.MusicVolume = AudioMgr.Instance.TotalVolume;   save.BGMusic = AudioMgr.Instance.BgVolume;  save.RoleMusic = AudioMgr.Instance.RoleVolume; save.EffectMusic = AudioMgr.Instance.EffectVolume; return save;}/// <summary>设置游戏参数</summary> public void SetGameData(SettingData save){TextSpeed = save.TextSpeed ;   TextAutoSpeed = save.TextAutoSpeed ;  DialogBoxAlpha = save.WindowAlpha ;AudioMgr.Instance.TotalVolume = save.MusicVolume ;AudioMgr.Instance.BgVolume = save.BGMusic ;AudioMgr.Instance.RoleVolume = save.RoleMusic ;AudioMgr.Instance.EffectVolume = save.EffectMusic ;UpdateValue();  //音频数据更新}/// <summary>重置所有选项的按钮</summary>public void ResetSliderValue(int a1,int a2,float a3,float a4,float a5,float a6,float a7) {SliderLst[0].value = a1;SliderLst[1].value = a2;SliderLst[2].value = a3;SliderLst[3].value = a4;SliderLst[4].value = a5;SliderLst[5].value = a6;SliderLst[6].value = a7;}/// <summary>重置音量</summary>  public void ResetVolume() {ResetSliderValue(10,10,0.7f,0.8f,1,1,1);}#endregion}

bug PlotCanvas Get到但没有初始化

SettingsPanel在MainCanvas下
GamePanel在PlotCanvas下

SettingsPanel在Update中调用GamePanel,也就是PlotCanvas的初始化要在MainCanvas之前(调一下顺序)

 /// <summary>更新数据</summary>public void UpdateValue() {AudioMgr.Instance.UpdateValue();UIMgr.Instance.SetDialogBoxAlpha(DialogBoxAlpha)  ;   //把对话框文本的透明度赋值AVGMachine.Instance.TextSpeed = TextSpeed;   //把速度赋值过去}

UIMgr 调用顺序

 void InitCanvas(){MainCanvas = gameObject.GetComponentDeep<MainCanvas>("MainCanvas");EnterCanvas = gameObject.GetComponentDeep<EnterCanvas>("EnterCanvas");PlotCanvas = gameObject.GetComponentDeep<PlotCanvas>("PlotCanvas");AnimCanvas = gameObject.GetComponentDeep<AnimCanvas>("AnimCanvas");WhiteCanvasGo = gameObject.Find("WhiteCanvas");BlackCanvasGo = gameObject.Find("BlackCanvas");BlackCanvasGo.Hide();PlotCanvas.Init();//在MainCanvas之前MainCanvas.Init();       EnterCanvas.Init();AnimCanvas.Init();}

modify 屏幕设置

挂在这里,被 SettingsPanel 调用和初始化

/****************************************************文件:ScreenSettings.cs作者:lenovo邮箱: 日期:2023/4/29 23:51:25功能:屏幕设置
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;public class ScreenSettings : MonoBehaviour
{#region 属性public Button FullScreenBtn;  public Button WindowScreenBtn; public List<Sprite> SpriteLst = new List<Sprite>();  //图片#endregion#region 生命public void Init(){FullScreenBtn = transform.GetButtonDeep("FullScreenBtn",FullScreen); ;WindowScreenBtn = transform.GetButtonDeep("WindowScreenBtn", WindowScreen); InitSpriteLst();FullScreen();}#endregion#region 辅助void InitSpriteLst(){AddSpriteLst("sys_botton_1_full_a");AddSpriteLst("sys_botton_1_win_a");AddSpriteLst("sys_botton_1_full_c #9204", "素材/zanghua/Texture2D/");AddSpriteLst("sys_botton_1_win_c");}void AddSpriteLst(string name, string pathPre = "素材/zanghua/Sprite/"){Sprite sprite = Resources.Load<Sprite>(pathPre + name);SpriteLst.Add(sprite);}/// <summary>窗口模式</summary>public void WindowScreen(){UnSelectBtn();Screen.SetResolution(1920, 1080, fullscreen: false);   WindowScreenBtn.GetComponent<Image>().sprite = SpriteLst[3]; }/// <summary>全屏方法,InitSpriteLst之后</summary>public void FullScreen(){UnSelectBtn();Screen.SetResolution(1920, 1080, fullscreen: true);  FullScreenBtn.GetComponent<Image>().sprite = SpriteLst[2];  }/// <summary>取消按钮的激活状态</summary>  public void UnSelectBtn(){FullScreenBtn.GetComponent<Image>().sprite = SpriteLst[0];WindowScreenBtn.GetComponent<Image>().sprite = SpriteLst[1]; }#endregion}

--------------------------------------------------

modify 驻足回想 MPCPanel

MPC,Music(音乐) Plot(剧情) CG(计算机动画)
。。。。。。
1 总的tab,有MPC三种
2 散的tab,MPC各自的所有内容
3 MPC在面板上显示的内容
。。。。。。
原版只有 TabGround 和 TabBtn 两个脚本,就1,2都是使用同样的TabGround,所以这部分的初始化区别分开,因为里面的PanelGoLst,面板位置关系不一样(不是都能在子节点找到,拖拽的话丢失麻烦)

TabGround基类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;/// <summary>选项卡基类</summary>public class TabGround : MonoBehaviour
{//管理按钮 并且 判断   哪个面板public List<TabBtn> TabBtnLst = new List<TabBtn>();/// <summary>存储数据面板</summary>public List<GameObject> PanelGoLst=new List<GameObject>();   /// <summary>用来存储当前点击的是哪个按钮</summary>public TabBtn selectTabBtn;      public TabBtn tabBtn1;#region 生命protected virtual void Start(){InitTabBtnLst();    InitTab1();InitPanelGoLst();}#endregion#region 辅助public void OnTabSelected(TabBtn tabBtn){//判断当前点击了哪个按钮,没有点击的按钮就切换成未激活的图片selectTabBtn = tabBtn;    //把点击的按钮 传递过去ResetTab();tabBtn.Active();int tarIdx = tabBtn.transform.GetSiblingIndex();   for (int i = 0; i < PanelGoLst.Count; i++){if (i == tarIdx){PanelGoLst[i].Show();}else{PanelGoLst[i].Hide();}}}/// <summary>重置所有按钮的图片</summary>public void ResetTab(){foreach (TabBtn tabBtn in TabBtnLst){if (selectTabBtn != null && tabBtn == selectTabBtn) { continue;//跳过本次循环 }//把按钮的图片切换成对应的 待机未激活 的图片tabBtn.Idle();}}protected virtual void InitTabBtnLst(){}protected virtual void InitPanelGoLst(){}protected virtual void InitTab1(){if (TabBtnLst.Count <= 0){return;}tabBtn1 = TabBtnLst[0];tabBtn1.Active();OnTabSelected(tabBtn1);}#endregion}

总的TabGround

挂在剧情的父节点或以上,我挂的是MPCPanel节点

/****************************************************文件:TabGroup0.cs作者:lenovo邮箱: 日期:2023/4/30 2:1:34功能:接受MPCPanel中的最上层的TabGround
*****************************************************/using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Random = UnityEngine.Random;public class TabGround0 : TabGround
{#region 生命protected override void Start(){InitTabBtnLst();InitTab1();InitPanelGoLst();}#endregion#region 辅助protected override void InitTabBtnLst(){Transform t = transform.FindChildDeep("BottomRight");TabBtnLst = t.GetComponentsInChildren<TabBtn>(includeInactive: true).ToList();foreach (TabBtn btn in TabBtnLst){btn.Idle();}}protected override void InitPanelGoLst(){PanelGoLst.Clear();PanelGoLst.Add( gameObject.FindChildDeep("剧情回放"));PanelGoLst.Add( gameObject.FindChildDeep("CG鉴赏"));PanelGoLst.Add( gameObject.FindChildDeep("音乐赏析"));foreach (GameObject go in PanelGoLst){go.Hide();}PanelGoLst[0].Show();}#endregion}

散的TabGround

挂在这两个节点上
PanelGoLst.Add( gameObject.FindChildDeep(“剧情回放”));
PanelGoLst.Add( gameObject.FindChildDeep(“CG鉴赏”));

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/// <summary></summary>public class TabGround1 : TabGround
{ #region 生命protected override void Start(){InitTabBtnLst();    InitTab1();InitPanelGoLst();}#endregion#region 辅助protected override void InitTabBtnLst(){List<GameObject> gos= gameObject.FindChildDeep("TabGroud").GetChildrenLst();foreach (GameObject go in gos){TabBtnLst.Add(go.GetComponent<TabBtn>());}foreach (TabBtn btn in TabBtnLst){btn.Idle();}TabBtnLst[0].Active();}protected override void InitPanelGoLst(){PanelGoLst = gameObject.FindChildDeep("PanelGoLst").GetChildrenLst();}#endregion}

TabBtn

挂在所有的按钮上。(1,2,3,4这样的选项卡)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Security;
using System;public class TabBtn : MonoBehaviour,IPointerDownHandler
{public TabGround tabGround;  public Image Img; public Sprite idleSprite;public Sprite activeSprite;private void Awake(){tabGround = transform.GetComponentInParent<TabGround>();Img = GetComponent<Image>();InitSprite();}void InitSprite(){ string pathPre = "素材/zanghua/Sprite/";int selfIdx = transform.GetSiblingIndex() + 1;string idlePath = String.Format(pathPre + "sl_menu_page_{0}_a", selfIdx);string activePath = String.Format(pathPre + "sl_menu_page_{0}_c", selfIdx);idleSprite =Resources.Load<Sprite>(idlePath);activeSprite = Resources.Load<Sprite>(activePath);  }public void OnPointerDown(PointerEventData eventData)  {//执行当前 UI 的 逻辑   tabGround.OnTabSelected(this);  //TODO 事件注册的做法//new OnTabSelectCommand().Execute();}public void Idle(){ Img.sprite = idleSprite;}public void Active(){Img.sprite = activeSprite;}
}

modify 音乐赏析

/****************************************************文件:MPCPanel.Music.cs作者:lenovo邮箱: 日期:2023/4/30 4:0:58功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;public partial class MPCPanel : MonoBehaviour
{#region 属性[Header("音乐赏析")]/// <summary>有时面板上看不到按钮事件,测试看的</summary>[SerializeField]  List<Button> btnLst = new List<Button>();[SerializeField] Button StopMusicBtn;[SerializeField] int curId;#endregion#region 生命public void InitMusic(){curId = -1;Transform t = transform.FindChildDeep("MusicLst");for (int i = 0; i < t.childCount; i++){Button btn = t.GetChild(i).GetComponent<Button>();btn.onClick.AddListener(()=>ClickMusicBtn(btn.transform.GetSiblingIndex()) ); //用i不行btnLst.Add(btn);//测试看}//StopMusicBtn = transform.GetButtonDeep("StopMusicBtn",() => AudioMgr.Instance.StopMPCMusic());//}#endregion#region 辅助void ClickMusicBtn(int i){               AudioMgr.Instance.PlayMPCMusic(i);curId= i; }#endregion}

--------------------------------------------------

继续旅程

删掉原版的TabGround,用TabGroundSL:TabGroundSL ,和SaveLoadPanel ,都是挂在SaveLoadPanel 节点上

SaveLoadPanel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine.UI;/// <summary>用来存储和读取文件</summary>
public class SaveLoadPanel : MonoBehaviour
{#region 字属[SerializeField] Image LogoImg;      [SerializeField] Sprite SaveSprite; [SerializeField] Sprite LoadSprite; [SerializeField] Button GoMainBtn; /// <summary>判断当前是存储还是读取</summary>public bool isSave;   /// <summary>获取自身子集下面的 存档预制体的数组</summary>public List<SaveSlot> slotList = new List<SaveSlot>();  #endregionpublic void Init(){LogoImg = gameObject.GetComponentDeep<Image>("LogoImg");SaveSprite = Resources.Load<Sprite>("素材/zanghua/Sprite/sl_title1");LoadSprite = Resources.Load<Sprite>("素材/zanghua/Sprite/sl_title2 #9468");GoMainBtn = transform.GetButtonDeep("GoMainBtn",()=>UIMgr.Instance.GoMainPanel());}#region 辅助/// <summary>把存档预制体 添加进入数据</summary>public void InitSlot(SaveSlot slot){slotList.Add(slot);}/// <summary>把加载界面的logo赋值</summary>public void SetLogoImgLoad(){LogoImg.sprite = LoadSprite;}public void SetLogoImgSave(){LogoImg.sprite = SaveSprite;}/// <summary>加载已拥有的文件数据</summary>public  void LoadFileData(){for (int i = 0; i < slotList.Count; i++){if (File.Exists(Application.persistentDataPath + slotList[i].path))  //查询是否有文件  如果有的话{BinaryFormatter bf = new BinaryFormatter();  //实例化FileStream fs = File.Open(Application.persistentDataPath + slotList[i].path, FileMode.Open);  //打开i数据文件SaveData save = (SaveData)bf.Deserialize(fs);   //把二进制文件 反序列化    然后在强制转换成Save形式slotList[i].saveImg.sprite = Resources.Load<Sprite>("BG/" + save.SaveImg);    //获取存储预制体上面的图片slotList[i].Des.text = save.SaveDes;    //读取 文本 然后赋值fs.Close(); }else{//如果没有查询到文件slotList[i].saveImg.sprite = Resources.Load<Sprite>("BG/" + "黑");    //获取存储预制体上面的图片slotList[i].Des.text = "没有数据";    //没有数据}}}/// <summary>二进制存储数据文件</summary>public void SaveGame(string path, SaveSlot slot){SaveByBin(path, slot);}/// <summary>读取游戏数据文件</summary>public void LoadGame(string path){LoadByBin(path);}/// <summary>二进制存储数据</summary>public void SaveByBin(string path, SaveSlot slot){SaveData save = CreateSaveData(slot);BinaryFormatter bf = new BinaryFormatter();  //实例化FileStream fs = File.Create(Application.persistentDataPath + path);  //创建文件bf.Serialize(fs, save);fs.Close();  //}/// <summary>创建存储文件信息</summary>public SaveData CreateSaveData(SaveSlot slot){SaveData save = new SaveData();   //实例化一下  序列化的脚本save.CurLine = AVGMachine.Instance.curLine;   //把文本下标  保存在save序列化脚本里面save.StoryID = AVGMachine.Instance.curStoryID;save.CurPolt = AVGMachine.Instance.TextInfo;save.Alpha = UIMgr.Instance.PlotCanvas.GamePanel.BG2Alpha;    //把背景图片2的透明度 保存在序列化脚本里面save.BG1 = UIMgr.Instance.PlotCanvas.GamePanel.BG1.sprite.name;   //获得 一号背景图片里面使用的图片名称save.BG2 = UIMgr.Instance.PlotCanvas.GamePanel.BG2.sprite.name;   //获得 2号背景图片里面使用的图片名称save.SaveImg = slot.saveImg.sprite.name;     //获得 存储预制体上的图片save.SaveDes = slot.Des.text;   //获得 存储预制体上的文本return save;   //返回存储数据文件}/// <summary>读取二进制游戏文件</summary>public void LoadByBin(string path){if (File.Exists(Application.persistentDataPath + path))   //判断当前的路径是否拥有文件{BinaryFormatter bf = new BinaryFormatter();  //实例化FileStream fs = File.Open(Application.persistentDataPath + path, FileMode.Open);  //打开i数据文件SaveData save = (SaveData)bf.Deserialize(fs);   //把二进制文件 反序列化    然后在强制转换成Save形式fs.Close();  //关闭SetGame(save);    //把反序列化出来的数据文件 传递给setgame}}/// <summary>把读取出来的游戏数据 在赋值回去</summary>public void SetGame(SaveData save){AVGMachine.Instance.curLine = save.CurLine;   //把下标赋值AVGMachine.Instance.curStoryID = save.StoryID;AVGMachine.Instance.TextInfo = save.CurPolt;AVGMachine.Instance.LoadUpdateBG(save.BG1, save.BG2, save.Alpha);   //传递  背景1和2的图片名称 和 背景图片2的透明值AVGMachine.Instance.GoState(TypeState.TYPING);   //把当前的状态切换成 typing 打字状态UIMgr.Instance.PlotCanvas.enabled = true;   //显示剧情面板gameObject.SetActive(false);  //关闭自身面板}#endregion}

TabGroundSL:TabGroundSL

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/// <summary></summary>public class TabGroundSL : TabGround
{ #region 生命protected override void Start(){InitTabBtnLst();    InitTab1();InitPanelGoLst();}#endregion#region 辅助protected override void InitTabBtnLst(){List<GameObject> gos= gameObject.FindChildDeep("TabGround").GetChildrenLst();foreach (GameObject go in gos){TabBtnLst.Add(go.GetComponent<TabBtn>());}foreach (TabBtn btn in TabBtnLst){btn.Idle();}TabBtnLst[0].Active();}protected override void InitPanelGoLst(){PanelGoLst = gameObject.FindChildDeep("SaveLoadObjLst").GetChildrenLst();}#endregion}

--------------------------------------------------

modify 开始游戏

01 运行原版的,先是 黑屏Canvas 闪一下(显示又隐藏)。MainCanvas不变,MainPanel(主菜单界面)隐藏。然后显示 GamePanel(StartAVG)
02 黑屏Canvas 的滑动,有动画事件,单独提取出来(没引用一个个看动画器看麻烦了),放在BlackCanvas_BlackCanvas (所在的节点名_动画名)

BlackCanvas_BlackCanvas

/****************************************************文件:BlackCanvas_BlackCanvas.cs作者:lenovo邮箱: 日期:2023/4/21 20:23:34功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class BlackCanvas_BlackCanvas : MonoBehaviour
{#region 辅助(方法顺序就是在动画中的顺序。不要移动顺序)/// <summary>关闭菜单按钮</summary>public void HideMainBtn(){StartCoroutine(HideMainBtnCrt());}/// <summary>开始游戏</summary>public void StartGame(){StartCoroutine(StartGameCrt());//在MonoBehaviour中使用}/// <summary>avg开始运行</summary>public void StartAVG(){AVGMachine.Instance.StartAVG();}/// <summary>关闭黑屏</summary>public void HideBlack(){gameObject.Hide();  //关闭 自身}#endregion#region 协程IEnumerator StartGameCrt(){//第一种写法while (UIMgr.Instance == null)//需要时间{yield return new WaitForEndOfFrame(); //等一帧 }UIMgr.Instance.StartGame();  //调用开始游戏方法}IEnumerator HideMainBtnCrt(){while (UIMgr.Instance == null|| UIMgr.Instance.MainCanvas == null|| UIMgr.Instance.MainCanvas.MainPanel == null)//需要时间{yield return new WaitForEndOfFrame(); //等一帧 }UIMgr.Instance.HideMainBtn();}#endregion}

stars enabled

/****************************************************文件:ExtendComponent.ShowHide.cs作者:lenovo邮箱: 日期:2023/4/22 15:32:47功能:
*****************************************************/using Codice.Client.BaseCommands;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.TerrainAPI;
using UnityEngine;
using Random = UnityEngine.Random;public static partial class ExtendComponent
{......public static void Enabled(this Behaviour behaviour){behaviour.enabled = true;}public static void Disabled(this Behaviour behaviour){behaviour.enabled = false;}}

bug Asset database transaction committed twice!

虽然不影响运行

bug 开始游戏,仍然在主菜单,并且PlotCanvas被隐藏

开始游戏,仍然在主菜单,并且PlotCanvas被隐藏

原版是HideMainBtn,我调用HideMainPanel才能
PlotCanvas初始化不Hide

--------------------------------------------------

modify PlotCanvas.GamePanel 工具按钮(除了 自动、跳过)

GamePanel

/****************************************************文件:GamePanel.cs作者:lenovo邮箱: 日期:2023/4/21 8:41:10功能:
*****************************************************/using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;
using Random = UnityEngine.Random;public class GamePanel : MonoBehaviour
{#region 字段[SerializeField] Button NextBtn;[Header("角色")]public GameObject RoleCGrpLstGo;  public CanvasGroup RoleACGrp;   //获得角色A号位置的 画布组public CanvasGroup RoleBCGrp;   //获得角色B号位置的 画布组public CanvasGroup RoleCCGrp;   //获得角色C号位置的 画布组public float RoleAAlpha = 0;    //A号人物的  Alpha 的值public float RoleBAlpha = 0;    //B号人物的  Alpha 的值public float RoleCAlpha = 0;    //C号人物的  Alpha 的值//public CanvasGroup BG1Group;   //第一个背景画布public CanvasGroup BG2Group;  //第二个背景画布[Header("选择按钮")]public GameObject ChoiceBtnLstGo;   public Button ChoiceBtnA;  public Button ChoiceBtnB;  public Button ChoiceBtnC;  //[Header("Image")]/// <summary>对话框背景</summary>public Image ContentBGImg;   public Image BG1;   //获得背景图片  用来替换背景public Image BG2;   //获得背景图片,  只不过这个是第二个背景图片public Image RoleImg;   //获得人物名称 的背景图片//[Header("Text")]/// <summary>对话文本</summary>public Text DialogText;   /// <summary>用来显示人物名称的文本</summary>public Text RoleText;    public Text BtnDesText;    [Header("float")]public float TarSpeed = 2f;    //人物显示的渐变速度public float BG2Alpha = 0;  //背景图片2 的 目标透明度[Header("右下的按钮")][SerializeField] Button CloseBtn;[SerializeField] Button SettingsBtn;[SerializeField] Button SkipBtn;[SerializeField] Button AutoBtn;[SerializeField] Button LoadBtn;[SerializeField] Button SaveBtn;[SerializeField] Button ShowPlotBtnLstBtn;[SerializeField] GameObject PlotBtnLstGo;[Header("Auto Skip")]/// <summary>判断是否开始了自动跳转按钮功能</summary>public bool isAuto;   /// <summary>判断是否开始了快速跳过功能</summary>public bool isSkip;   /// <summary>自动跳转的待机图片</summary>public Sprite AutoIdleSprite;   /// <summary>自动跳转的激活图片</summary>public Sprite AutoActiveSprite;  /// <summary>快速跳转的待机图片</summary>public Sprite SkipIdleAprite;   /// <summary>快速跳转的激活图片</summary>public Sprite SkipActiveSprite;  /// <summary>获得自动跳转按钮身上的图片组件</summary>public Image AutoBtnImg;  /// <summary>获得快速跳转按钮身上的图片组件</summary>public Image SkipBtnImg;  #endregion#region 生命public void Init(){InitRoleCanvasGroup();RoleAAlpha = 0;RoleBAlpha = 0;RoleCAlpha = 0;//BG1Group = transform.GetComponentDeep<CanvasGroup>(GameObjectName.BG1);BG2Group = transform.GetComponentDeep<CanvasGroup>(GameObjectName.BG2);//NextBtn = transform.GetButtonDeep("NextBtn",AVGMachine.Instance.UserClicked );InitChoiceBtnLst();InitPlotBtnLstAndImg();//ContentBGImg = transform.GetComponentDeep<Image>(GameObjectName.ContentBGImg);BG1 = transform.GetComponentDeep<Image>(GameObjectName.BG1);BG2 = transform.GetComponentDeep<Image>(GameObjectName.BG2);RoleImg = transform.GetComponentDeep<Image>(GameObjectName.RoleImg);//DialogText = transform.GetComponentDeep<Text>(GameObjectName.DialogText);RoleText = transform.GetComponentDeep<Text>(GameObjectName.RoleText);BtnDesText = transform.GetComponentDeep<Text>(GameObjectName.BtnDesText);//TarSpeed = 2f;BG2Alpha = 0;//AutoIdleSprite = LoadSprite("dialog_menu_auto_a") ;AutoActiveSprite = LoadSprite("dialog_menu_auto_c");SkipIdleAprite = LoadSprite("dialog_menu_skip_a");SkipActiveSprite = LoadSprite("dialog_menu_skip_c");}void Update(){if (Input.GetKeyDown(KeyCode.A)){ShowRoleA(1);   ShowRoleB(1);   ShowRoleC(1);   }if (Input.GetKeyDown(KeyCode.B)){ShowRoleA(0); ShowRoleB(0); ShowRoleC(0); }if (Input.GetKeyDown(KeyCode.C)){SetDialogText("jkakfkalgfhjlsglfjhgasljhfgshjafa");}if (Input.GetKeyDown(KeyCode.D)){SetRoleText(true, "不知道");}if (Input.GetKeyDown(KeyCode.E)){SetRoleText(false, "不知道");}#region   角色A的 透明渐变            //如果A号角色身上的画布的透明度 不等于 我们手动设置的 透明值的话if (RoleACGrp.alpha != RoleAAlpha)  {RoleACGrp.alpha = Mathf.Lerp(RoleACGrp.alpha, RoleAAlpha, TarSpeed * Time.deltaTime);    //角色A的透明值    使用lerp   渐变到 我们设置的alhpa值if (Mathf.Abs(RoleACGrp.alpha - RoleAAlpha) < 0.1f)    //如果玩家的透明度 减去  我们设置的透明度 的绝对值   小于0.1的话   {RoleACGrp.alpha = RoleAAlpha;     //把目标的透明值 设置给  A号玩家的透明纸}}#endregion#region   角色B的 透明渐变if (RoleBCGrp.alpha != RoleBAlpha)   //如果A号角色身上的画布的透明度 不等于 我们手动设置的 透明值的话{RoleBCGrp.alpha = Mathf.Lerp(RoleBCGrp.alpha, RoleBAlpha, TarSpeed * Time.deltaTime);    //角色A的透明值    使用lerp   渐变到 我们设置的alhpa值if (Mathf.Abs(RoleBCGrp.alpha - RoleBAlpha) < 0.1f)    //如果玩家的透明度 减去  我们设置的透明度 的绝对值   小于0.1的话   {RoleBCGrp.alpha = RoleBAlpha;     //把目标的透明值 设置给  A号玩家的透明纸}}#endregion#region   角色C的 透明渐变if (RoleCCGrp.alpha != RoleCAlpha)   //如果A号角色身上的画布的透明度 不等于 我们手动设置的 透明值的话{RoleCCGrp.alpha = Mathf.Lerp(RoleCCGrp.alpha, RoleCAlpha, TarSpeed * Time.deltaTime);    //角色A的透明值    使用lerp   渐变到 我们设置的alhpa值if (Mathf.Abs(RoleCCGrp.alpha - RoleCAlpha) < 0.1f)    //如果玩家的透明度 减去  我们设置的透明度 的绝对值   小于0.1的话   {RoleCCGrp.alpha = RoleCAlpha;     //把目标的透明值 设置给  A号玩家的透明纸}}#endregion#region 背景图片2 渐变显示和隐藏if (BG2Group.alpha != BG2Alpha){//如果背景图片2 身上的 画布的 透明度  不等于 我们设置的目标透明度BG2Group.alpha = Mathf.Lerp(BG2Group.alpha, BG2Alpha, TarSpeed * Time.deltaTime);   //背景图片2的渐变值if (Mathf.Abs(BG2Group.alpha - BG2Alpha) < 0.1f){BG2Group.alpha = BG2Alpha;  //直接把透明度 赋值给  画布组上面的透明度}}#endregion}#endregion#region 系统#endregion#region 辅助private void InitRoleCanvasGroup(){RoleCGrpLstGo = gameObject.FindChildDeep("RoleCGrpLstGo");RoleACGrp = transform.GetComponentDeep<CanvasGroup>("RoleACGrp");RoleBCGrp = transform.GetComponentDeep<CanvasGroup>("RoleBCGrp");RoleCCGrp = transform.GetComponentDeep<CanvasGroup>("RoleCCGrp");}Sprite LoadSprite(string spriteName){return Resources.Load<Sprite>("素材/zanghua/Sprite/"+ spriteName);}private void IntiPlotImg(){SkipBtnImg = SkipBtn.GetComponent<Image>();AutoBtnImg = AutoBtn.GetComponent<Image>();}void InitChoiceBtnLst(){ChoiceBtnLstGo = gameObject.FindChildDeep("ChoiceBtnLstGo");ChoiceBtnA = transform.GetButtonDeep("ChoiceBtnA",()=>AVGMachine.Instance.ProcessChoiceBtnMSG(ChoiceBtnA));ChoiceBtnB = transform.GetButtonDeep("ChoiceBtnB",()=>AVGMachine.Instance.ProcessChoiceBtnMSG(ChoiceBtnB));ChoiceBtnC = transform.GetButtonDeep("ChoiceBtnC",()=>AVGMachine.Instance.ProcessChoiceBtnMSG(ChoiceBtnC));}void InitPlotBtnLstAndImg(){PlotBtnLstGo = gameObject.FindChildDeep("PlotBtnLstGo");CloseBtn = transform.GetButtonDeep("CloseBtn", HideAnimPoltBtn);SettingsBtn = transform.GetButtonDeep("SettingsBtn", UIMgr.Instance.OpenSettingsPanel);SkipBtn = transform.GetButtonDeep("SkipBtn", SkipPlot);AutoBtn = transform.GetButtonDeep("AutoBtn", AutoPlot);LoadBtn = transform.GetButtonDeep("LoadBtn", UIMgr.Instance.ShowLoadPanel);SaveBtn = transform.GetButtonDeep("SaveBtn", UIMgr.Instance.ShowSaveLoadPanel);ShowPlotBtnLstBtn = transform.GetButtonDeep("ShowPlotBtnLstBtn", ShowPlotBtnLstGo);IntiPlotImg();}/// <summary>更新背景图片 在读取存档之后</summary>public void LoadUpdateBG(string bg1, string bg2, float alpha){BG1.sprite = Resources.Load<Sprite>("BG/" + bg1);     //把背景1和2的图片赋值BG2.sprite = Resources.Load<Sprite>("BG/" + bg1);BG2Alpha = alpha;  //把透明度赋值给 背景2的透明度}public void LoadContent(Story01Data story){ShowRoleA(story.Adisplay);  ShowRoleB(story.Bdisplay);  ShowRoleC(story.Cdisplay);  }public void ClearContent(){ShowRoleA(0);ShowRoleB(0);ShowRoleC(0);}/// <summary>给对话文本赋值</summary>public void SetDialogText(string value){DialogText.text = value;}public void SetRoleText(bool isShow, string value){     //第一个布尔 是判断 是否要显示人物名称的背景图片   第二个 字符串 是   要显示的人物名称 //判断是否要显示人物的名称,  如果要实现 就设置人物的名称if (isShow){//如果当前要显示人物名称RoleImg.gameObject.SetActive(true);   //显示 人物名称的背景图片RoleText.text = value;   //把传递进来的人物名称 赋值}else{//如果不显示人物的名称和背景图片RoleImg.gameObject.SetActive(false);   //隐藏人物名称的背景图片}}/// <summary>调用显示按钮的方法</summary>public void ShowBtnList(Story01Data story){ShowBtnList(story.Ischoice, story.Isa, story.Isb, story.Isc);}/// <summary></summary>public void ShowBtnList(bool value, bool A, bool B, bool C){//显示或者隐藏按钮ChoiceBtnA.SetActive(value);ChoiceBtnB.SetActive(value);ChoiceBtnC.SetActive(value);// 判断当前按钮在当前剧情中是否要显示或者隐藏ChoiceBtnA.SetActive(A);ChoiceBtnB.SetActive(B);ChoiceBtnC.SetActive(C);}/// <summary>隐藏全部的按钮</summary>public void HideBtnList(){//显示或者隐藏按钮ChoiceBtnA.Hide();ChoiceBtnB.Hide();ChoiceBtnC.Hide();// 判断当前按钮在当前剧情中是否要显示或者隐藏ChoiceBtnA.Hide();ChoiceBtnB.Hide();ChoiceBtnC.Hide();}/// <summary>把传递进来的图片 添加到 号位置的图片</summary>public void ChangeRoleSprite(AVGAssetCfg cfg){RoleACGrp.GetComponent<Image>().sprite = cfg.charaA;RoleBCGrp.GetComponent<Image>().sprite = cfg.charaB;RoleCCGrp.GetComponent<Image>().sprite = cfg.charaC;}/// <summary>设置按钮里面的内容</summary>public void SetChoiceBtnText(Story01Data story){ChoiceBtnA.GetComponentInChildren<Text>().text = story.Btnatext ;ChoiceBtnB.GetComponentInChildren<Text>().text = story.Btnbtext;ChoiceBtnC.GetComponentInChildren<Text>().text = story.Btnctext;}/// <summary>设置按钮的名称</summary>public void SetChoiceBtnName(Story01Data story){ChoiceBtnA.name = story.Btnaname;ChoiceBtnB.name = story.Btnbname;ChoiceBtnC.name = story.Btncname;}/// <summary> /// 更换背景图片/// </summary>/// <param name="img">图片类型</param>/// <param name="img2"><是第二个的背景/param>/// <param name="alpha">第二个背景图片的alpha透明度</param>public void ChangeBG(Sprite img, Sprite img2, int alpha){BG1.sprite = img;  BG2.sprite = img2; BG2Alpha = alpha;  }/// <summary>判断是否显示人物名称和背景图片</summary>public void ShowRoleName(Story01Data story){UIMgr.Instance.SetRoleText(story.Isrole, story.Roletext );    //第一个布尔 是判断 是否要显示人物名称的背景图片   第二个 字符串 是   要显示的人物名称 }#region    判断ABC三个位置的角色 是否显示或者隐藏bool IsAlphaLegal(int value){ if (value != 0 && value != 1){return false;}return true;}/// <summary>调用显示角色位置的方法</summary>public void ShowRoleA(int value){if (IsAlphaLegal(value) == false){return;}RoleAAlpha = value;  }/// <summary>调用显示角色位置的方法</summary>public void ShowRoleB(int value){if (IsAlphaLegal(value) == false){return;}RoleBAlpha = value;}/// <summary>调用显示角色位置的方法</summary>public void ShowRoleC(int value){if (IsAlphaLegal(value) == false){return;}RoleCAlpha = value;  }public void SetDialogBoxAlpha(float dialogBoxAlpha){ContentBGImg.GetComponent<CanvasGroup>().alpha = dialogBoxAlpha;  }/// <summary>隐藏对话框背景</summary>internal void HideContentBG(){ContentBGImg.Hide();  }internal void HideAnimPoltBtn(){PlotBtnLstGo.GetComponent<Animator>().SetBool("Open", false);}internal void ShowPlotBtnLstGo(){PlotBtnLstGo.Show();ContentBGImg.Show();}internal void HidePlotBtn(){PlotBtnLstGo.Hide(); ContentBGImg.Hide(); }internal void ShowAnimPoltBtn(){PlotBtnLstGo.Show(); ContentBGImg.Show();PlotBtnLstGo.GetComponent<Animator>().SetBool("Open", true);   }#region 右下按钮internal void SetPlotBtnDesText(string btnName){BtnDesText.text = btnName;}internal void EnabledBtnDesText(){BtnDesText.Enabled();}internal void DisabledBtnDesText(){BtnDesText.Disabled();}internal void SkipPlot(){if (isSkip){//如果开启了自动跳转isSkip = false;//关闭  快速跳转的功能SkipBtnImg.sprite = SkipIdleAprite;  //把图片切换成待机状态AVGMachine.Instance.isSkip = false;  //当前不可以快速跳转剧情}else{if (isAuto){  //如果当前开启了自动状态 //如果开启了自动跳转isAuto = false;//关闭自动跳转下一行的功能AutoBtnImg.sprite = AutoIdleSprite;  //图片切换成待机图片AVGMachine.Instance.isAuto = false;  //当前不可以自动跳转到下一句}//如果 为false 代表没有开启isSkip = true;   //为true 开启//执行  快速跳转的功能SkipBtnImg.sprite = SkipActiveSprite;  //把图片切换成激活状态AVGMachine.Instance.isSkip = true;  //当前可以快速跳转剧情}}internal void AutoPlot(){if (isAuto){isAuto = false;//关闭自动跳转下一行的功能AutoBtnImg.sprite = AutoIdleSprite;  //图片切换成待机图片AVGMachine.Instance.isAuto = false;  //当前不可以自动跳转到下一句}else{//如果 为false 代表没有开启isAuto = true;   //为true 开启//执行  自动跳转下一行的功能AutoBtnImg.sprite = AutoActiveSprite;  //图片切换成激活图片AVGMachine.Instance.isAuto = true;  //当前可以自动跳转到下一句}}#endregion#endregion#endregion
}

modify GameBtn


/****************************************************文件:作者:WWS日期:2023/05/01 17:14:52功能:PlotCanvas.GamePanel右下的工具按钮*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;public class GameBtn : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{/// <summary>按钮的名称</summary>public string BtnName;#region 系统public void OnPointerEnter(PointerEventData eventData){UIMgr.Instance.PlotCanvas.GamePanel.EnabledBtnDesText();UIMgr.Instance.PlotCanvas.GamePanel.SetPlotBtnDesText(BtnName);}public void OnPointerExit(PointerEventData eventData){UIMgr.Instance.PlotCanvas.GamePanel.DisabledBtnDesText();}#endregion}

stars SetActive

Button之类
Button
:Selectable
:UIBehaviour
:MonoBehaviour
:Behaviour // Behaviours are Components that can be enabled or disabled.

 public static void SetActive(this Behaviour behaviour,bool state){behaviour.gameObject.SetActive(state);}

modify 处理人物SO

/****************************************************文件:ResourcesInitRole.cs作者:lenovo邮箱: 日期:2023/5/2 15:27:9功能:初始化Assets/Resources/Role下的两个AVGAssetCfg,防止丢失
*****************************************************/using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;public class ResourcesInitRole
{[MenuItem(DefinePath.MenuItem_AVG + "01 定位Role【AVGAssetCfg】", false, 0)]//按钮在菜单栏的位置public static void ActiveAVGAssetCfgSO() //文件夹{Common.Selection_ActiveObject( "Assets/Resources/Role");}[MenuItem(DefinePath.MenuItem_AVG + "01 初始化Role【AVGAssetCfg】", false, 0)]//按钮在菜单栏的位置public static void InitAVGAssetCfgSO() //文件夹{AVGAssetCfg role02 = AssetDatabase.LoadAssetAtPath<AVGAssetCfg>("Assets/Resources/Role/2.asset");AVGAssetCfg role03 = AssetDatabase.LoadAssetAtPath<AVGAssetCfg>("Assets/Resources/Role/3.asset");role02.charaA = LoadRoleSprite("cuimianshi");role02.charaB = LoadRoleSprite("xiao");role02.charaC = LoadRoleSprite("yinxiao");role03.charaA = LoadRoleSprite("xiao");role03.charaB = LoadRoleSprite("cuimianshi");role03.charaC = LoadRoleSprite("yinxiao");AssetDatabase.SaveAssets();AssetDatabase.Refresh();}private static Sprite LoadRoleSprite(string spriteName){return Resources.Load<Sprite>("RoleIMG/"+spriteName);}
}

bug SO数据丢失

Resources/Role/2 不会
Resources/Role/3 的数据 sprite 经常在运行游戏后丢失为 none(执行一次选项按钮后)

modify PlotCanvas.LoadDiaTextPanel

这个是之前对话的记录面板,在GamePanel时滚动滑轮触发。
但是问题时好像不是随时记录的

--------------------------------------------------

watch QuickSheet插件的使用

里面有说明文档 Assets/QuickSheet/Doc/Unity-Quicksheet.pdf

01 新建(这两个连锁的)
Excel Settings
Excel Machine

02 新建表格,Excel Machine 中加入表格,确定 Sheet,属性类型。配置Editor,Runtime文件夹路径(不包括Assets)。然后Generate。(我这里报错了)

03 解决小bug后,右键reimport

bug 插件小bug

手动改回来 //

整体待改进--------------------------------------------------

就是节点间的访问
事件注册的使用

从零开始带你开发橙光游戏AVG框架(仿 葬花 )相关推荐

  1. 教你从头写游戏服务器框架

    本文由云+社区发表 作者:韩伟 前言 大概已经有差不多一年没写技术文章了,原因是今年投入了一些具体游戏项目的开发.这些新的游戏项目,比较接近独立游戏的开发方式.我觉得公司的"祖传" ...

  2. golang游戏服务器框架_教你从头写游戏服务器框架

    需求 由于"越通用的代码,就是越没用的代码",所以在设计之初,我就认为应该使用分层的模式来构建整个系统.按照游戏服务器的一般需求划分,最基本的可以分为两层: 底层基础功能:包括通信 ...

  3. 教你从头写游戏服务器框架 1

    本文由云+社区发表 作者:韩伟 前言 大概已经有差不多一年没写技术文章了,原因是今年投入了一些具体游戏项目的开发.这些新的游戏项目,比较接近独立游戏的开发方式.我觉得公司的"祖传" ...

  4. Silverlight游戏设计(Game Design):(四)从零开始搭建游戏主体框架

    思路已俨然清晰,接下来要做的是从零开始搭建游戏的主体框架.Silverlight作为RIA界的新宠儿,不仅在游戏开发方面性能优越,在企业开发领域的优异表现同样日益显著.像我们这些长期从事.NET开发的 ...

  5. 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(2)

    导语 上一期我们带大家完成了魔塔游戏每一层的初始化画面的制作: 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(1) 这一期我们会带大家进一步复现我们的魔塔小游戏,主要内容包括英雄类 ...

  6. 如何从零开始用 C++ 开发一款游戏引擎?

    原文链接:https://hackernoon.com/build-a-game-engine-from-scratch-in-c 游戏开发一直很能激励学生学习高级计算机科学.可能有些人认为游戏是孩子 ...

  7. 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(3)

    导语 上一期我们主要带大家写了勇士类,以及勇士与一些简单的地图元素接触时所触发的事件: 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(2) 这一期我们会带大家进一步复现我们的魔塔小 ...

  8. 游戏开发心得——书籍篇——《游戏引擎框架》-专业工具

    游戏开发心得--书籍篇--<游戏引擎框架>-专业工具 FOR THE SIGMA FOR THE GTINDER FOR THE ROBOMASTER 简介: 学习<游戏引擎框架&g ...

  9. arduino nano 蓝牙_探索 Golang 云原生游戏服务器开发,5 分钟上手 Nano 游戏服务器框架...

    介绍 Nano 是什么? 轻量级,方便,高性能 golang 的游戏服务器框架. nano 是一个轻量级的服务器框架,它最适合的应用领域是网页游戏.社交游戏.移动游戏的服务端.当然还不仅仅是游戏,用  ...

最新文章

  1. 20线程测试cpu性能软件,CPU常用跑分软件 你知道那些?
  2. ueditor初始化
  3. comparing ORB and AKAZE
  4. mysql事务和非事物_mysql事务型与非事务型表1.8.5.3. 事务和原子操作
  5. 吴恩达CS229速查表
  6. 32乘法运算_算术运算指令
  7. hibernate运行很慢?查一张只有几条记录的表都要一俩分钟?[问题记录]
  8. 高斯过程和高斯过程回归
  9. 软件工程概论网站系统开发基础及目标概述
  10. postgresql使用pg_rman备份恢复
  11. JAVA数据类型的强制转换
  12. 联想无线网卡 linux驱动,联想R7000 Ubuntu无线网卡驱动
  13. cass打开dwg文件无效_CAD文件打开时图形文件显示无效怎么办
  14. 学习方法和态度比什么都重要
  15. PMP-PMBOK图解项目管理(436页PPT、完整版-经典)
  16. android动态mac地址,Android 版本兼容 — Android 6.0 和 7.0后获取Mac地址
  17. 禅道项目管理系统安装后显示为空白
  18. 首都经贸大学计算机科学与技术专业,河北经贸大学经济管理学院的计算机科学与技术专业怎么样啊...
  19. ArrayList类的详解
  20. Sentinel持久化

热门文章

  1. php 六边形 属性图 能力数值图,css怎样做出六边形图片
  2. vue评价星星加笑脸(娃娃头像)
  3. 润乾报表日志文件的配置方法
  4. 代码随想录Day7| 454、383、15、18
  5. warning: #1300-D: XXX inherits implicit virtual 报警
  6. [python]7-4 乘坐公交(列表)
  7. PHP Secure E-mails
  8. AidLux AI 应用案例悬赏征集活动正式启动!
  9. 【传智汇第七期】探讨项目方案决策思路,百度高级工程师PHP专场
  10. C.十面埋伏(DFS连通块)