GameFrameWork框架(Unity3D)使用笔记(二)ProcedureChangeScene

GameFramework教程✨三、流程 大家好,我是SKODE。 小提示:选中左侧目录,可快速找到所需内容 本系列博客地址:传送门 E大该章链接:传送门 一、什么是流程 贯穿游戏运行时整个生命周期的有限状态机。通过流程,将不同的游戏状态进行解耦将是一个非常好的习惯。对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。如果想增加流程,只要派生自 ProcedureBase 类并实现.. 阅读详情
AI摘要

本文介绍了一个游戏项目的启动流程ProcedureLaunch及场景转换流程ProcedureChangeScene的设计与实现过程,包括配置加载、资源预加载、场景切换等内容。

目录

前言:

ProcedureBase

启动流程ProcedureLaunch

场景转换流程ProcedureChangeScene


前言:

        上一篇中已经成功引入了框架,并且创建了游戏入口GameEntry。本篇的主要内容为创建游戏的启动流程ProcedureLaunch,场景转换流程ProcedureChangeScene(本来要写菜单流程但是最后发现篇幅太大。。。。)

        (再次强调,本系列笔记偏实践,主要记录使用过程,对于具体的框架讲解可以搜到很多大佬的教程,同时也非常建议自行阅读源码,可以学到很多。)

        如果看过StarForce可以看到它里面做了很多的流程,比如版本检测、资源检测、更新、预加载、场景切换、初始化资源等。而我这里就不全部模仿了。

        在这次的案例中,我先只写几个必要的流程,先能跑起来再说。


ProcedureBase

        首先在写流程之前,先实现一个基类ProdecureBase(实际上框架中已经有一个同名类了),对框架中的ProcedureBase进行进一步解耦。从StarForce的代码中可以看到这么做的一个具体作用:

//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------

namespace StarForce
{
    public abstract class ProcedureBase : GameFramework.Procedure.ProcedureBase
    {
        // 获取流程是否使用原生对话框
        // 在一些特殊的流程(如游戏逻辑对话框资源更新完成前的流程)中,可以考虑调用原生对话框进行消息提示行为
        public abstract bool UseNativeDialog
        {
            get;
        }
    }
}

        于是咱也整一个:

        


namespace ShadowU
{
    /// <summary>
    /// 流程抽象类
    /// </summary>
    public abstract class ProcedureBase : GameFramework.Procedure.ProcedureBase
    {
        public abstract bool UseNativeDialog
        {
            get;
        }
    }
}


启动流程ProcedureLaunch

        目前先不搞配置加载啥的(有的话在这个流程Enter里写上),一开始只是很简单的打开主菜单,所以运行第一帧直接跳到菜单流程ProcedureMenu:

using GameFramework.Fsm;
namespace ShadowU
{
    public class ProcedureLaunch : ProcedureBase
    {
        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
            //一帧后直接转到菜单流程
            ChangeState<ProcedureMenu>(procedureOwner);
        }
    }

}

        最后别忘了设置一下启动流程(先保存代码):

        


场景转换流程ProcedureChangeScene

       下一步我们需要把菜单展现给玩家,但是我们目前只有一个启动场景,加载菜单的话需要加载一个菜单场景并且加载UI预制体。

        所以在写菜单流程之前,需要先写一下场景切换流程。

        切换场景需要用到场景名,StarForce中配置了场景名和场景ID的配置表(流程之间传递的实际上是场景名对应的ID)。获取场景ID的方式就是通过GameEntry.Config来获取配置表中对应场景名的ID(配置表应该是交给策划填写)。

        所以我也来用一用GameEntry.Config。

        首先创建默认配置表:

        

        然后我这里直接在ProcedureLaunch里面预加载资源(规范点应该创建个预加载流程)。

        首先在这个流程里写一个加载配置的函数:

        (注:这里的AssetUtility类我直接从StarForce搬过来了,实际上就是把文件转换为路径用的。) 

        然后关于m_LoadedFlag字典的用处看完了整个代码和注释就知道了:

//ProcedureLaunch
using GameFramework.Fsm;
using GameFramework.Event;
using UnityGameFramework.Runtime;

using System.Collections.Generic;

namespace ShadowU
{
    public class ProcedureLaunch : ProcedureBase
    {
        private Dictionary<string, bool> m_LoadedFlag = new Dictionary<string, bool>();//用来标记是否已经加载
        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnEnter(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner)
        {
            base.OnEnter(procedureOwner);
            //注册事件
            GameEntry.Event.Subscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);

            m_LoadedFlag.Clear();
            //预加载配置
            PreloadResources();
        }

        protected override void OnLeave(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);
            //注销事件
            GameEntry.Event.Unsubscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);

        }

        protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

            foreach(KeyValuePair<string,bool> loadedFlag in m_LoadedFlag)
            {
                if (!loadedFlag.Value)
                {
                    return;//说明有资源没有加载成功
                }
            }

            //通过加载的配置表来设置下一个转换场景的ID
            procedureOwner.SetData<VarInt32>("NextSceneId",GameEntry.Config.GetInt("Scene.Menu"));
            //一帧后直接转到菜单流程
            ChangeState<ProcedureChangeScene>(procedureOwner);
        }

        private void PreloadResources()
        {
            LoadConfig("DefaultConfig");
        }

        private void LoadConfig(string configName)
        {
            string configAssetName = AssetUtility.GetConfigAsset(configName, false);
            m_LoadedFlag.Add(configAssetName, false);
            GameEntry.Config.ReadData(configAssetName, this);
        }

        private void OnLoadConfigSuccess(object sender, GameEventArgs e)
        {
            LoadConfigSuccessEventArgs ne = (LoadConfigSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadedFlag[ne.ConfigAssetName] = true;  //资源加载成功了则设置一下标记为true
            Log.Info("Load config '{0}' OK.", ne.ConfigAssetName);
        }

        private void OnLoadConfigFailure(object sender, GameEventArgs e)
        {
            LoadConfigFailureEventArgs ne = (LoadConfigFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Can not load config '{0}' from '{1}' with error message '{2}'.", ne.ConfigAssetName, ne.ConfigAssetName, ne.ErrorMessage);
        }

    }

}

       此外别忘了在场景中设置一下:

        然后下面就可以开始写ProcedureChangeScene的逻辑了

        主要要实现的逻辑如下:

         监听场景加载成功、失败、进行中、加载场景依赖资源事件
            1、停止所有声音(咱这里暂时不写,先玩一波静音游戏好叭)
            2、隐藏所有实体
            3、卸载所有场景
            4、还原游戏速度
            5、根据NextSceneId从Scene配置表搜出场景资源文件名,获取场景相对路径。使用GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName), Constant.AssetPriority.SceneAsset, this);同步加载追加场景。其中drScene是从Scene配置表根据id找出的DRScene对象, AssetName是资源名。

        直接看代码吧结合注释应该能理解。

        但是,代码里面

        首先要先写一个DRScene(场景数据表行类)。但是我打开了StarForce的这个类的定义我发现它的这个好像是某个工具自动生成的:

         那这个是用什么生成的呢?

        细心点的话就会发现StarForce里的这个:

        (或者烟雨大佬的博客也提到过这个)

        咱能力有限,就先不复刻(抄)这个生成工具了。

        先直接写DRScene类。

        一个数据表行类要完成的也是重写基类的这些东西:

        然后就仿造StarForce开写(抄)呗。

        然后代码中又用到一个没写过的类DataTableExtensions.cs,里面是一些通用的方法啥的,看看就懂了,直接复制过来用吧。。。。

        然后其中又用到一个没写过的类Constant,没事,里面保存的是一些常量啥的,直接复刻(抄)过来。。。

        然后稍微调整一下DRScene内容,就复刻(抄)完啦:

        然后别忘了补上数据表:

        (注:这里数据表的创建方式是先在Excel里面输入数据然后导出为记事本文件。然后!再把记事本另存为,改编码为UTF-8,否则Unity的Inspector里面会乱码.)

        

         (仿照StarForce写的,然后把音乐相关删了)

         最后,在ProcedureLaunch里面读取一下数据表:

 (小总结:数据表使用流程:创建txt,编写对应的数据表行类,Load数据表,使用数据表)

        (都快忘了要干啥来着)

        下面继续写ProcedureChangeScene的逻辑!

        通过阅读StarForce源码可以知道,开头我们列举的ProcedureChangeScene需要实现的逻辑可以放在OnEnter里面实现掉,然后OnUpdate里面实现状态机的状态切换。最终的代码如下(其中需要一个主游戏的流程ProcedureMain)(主要就看看OnEnter和OnUpdate里面的代码):

//ProcedureChangeScene.cs
using GameFramework.Fsm;
using GameFramework.Event;
using GameFramework.DataTable;
using UnityGameFramework.Runtime;
using UnityEngine;
namespace ShadowU
{
    public class ProcedureChangeScene : ProcedureBase
    {
        private const int MenuSceneId = 1;   //菜单场景的ID

        private bool m_ChangeToMenu = false; //是否转换为菜单
        private bool m_IsChangeSceneComplete = false; //转换场景是否结束
        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnEnter(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner)
        {
            base.OnEnter(procedureOwner);

            m_IsChangeSceneComplete = false; //如果为true的话 则在update中会切换流程

            //注册事件
            GameEntry.Event.Subscribe(LoadSceneSuccessEventArgs.EventId,OnLoadSceneSuccess);
            GameEntry.Event.Subscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Subscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Subscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);

            //隐藏所有实体
            GameEntry.Entity.HideAllLoadingEntities();
            GameEntry.Entity.HideAllLoadedEntities();

            //卸载所有场景
            string[] loadedSceneAssetNames = GameEntry.Scene.GetLoadedSceneAssetNames();
            foreach (string sn in loadedSceneAssetNames)
                GameEntry.Scene.UnloadScene(sn);

            //还原游戏速度
            GameEntry.Base.ResetNormalGameSpeed();

            //获取下一个场景的ID
            int sceneId = procedureOwner.GetData<VarInt32>("NextSceneId");
            m_ChangeToMenu = sceneId == MenuSceneId; //判断是否是转到菜单
            IDataTable<DRScene> dtScene = GameEntry.DataTable.GetDataTable<DRScene>();
            DRScene drScene = dtScene.GetDataRow(sceneId); //获取数据表行
            if(drScene == null)
            {
                Log.Warning("Can not load scene '{0}' from data table.", sceneId.ToString());
                return;
            }
            GameEntry.Scene.LoadScene(AssetUtility.GetSceneAsset(drScene.AssetName),Constant.AssetPriority.SceneAsset,this);
        }

        protected override void OnLeave(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);

            GameEntry.Event.Unsubscribe(LoadSceneSuccessEventArgs.EventId, OnLoadSceneSuccess);
            GameEntry.Event.Unsubscribe(LoadSceneFailureEventArgs.EventId, OnLoadSceneFailure);
            GameEntry.Event.Unsubscribe(LoadSceneUpdateEventArgs.EventId, OnLoadSceneUpdate);
            GameEntry.Event.Unsubscribe(LoadSceneDependencyAssetEventArgs.EventId, OnLoadSceneDependencyAsset);
        }

        protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

            if (!m_IsChangeSceneComplete)   
            {
                return;  //还没完成场景切换
            }
            if (m_ChangeToMenu)
            {
                ChangeState<ProcedureMenu>(procedureOwner);   //菜单
            }else
            {
                ChangeState<ProcedureMain>(procedureOwner);   //游戏运行流程
            }
        }
        
        private void OnLoadSceneSuccess(object sender,GameEventArgs e)
        {
            LoadSceneSuccessEventArgs ne = (LoadSceneSuccessEventArgs)e;
            if(ne.UserData != this)
            {
                return;
            }
            Log.Info("Load scene '{0}' OK.", ne.SceneAssetName);

            m_IsChangeSceneComplete = true;
        }
        private void OnLoadSceneFailure(object sender, GameEventArgs e)
        {
            LoadSceneFailureEventArgs ne = (LoadSceneFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Load scene '{0}' failure, error message '{1}'.", ne.SceneAssetName, ne.ErrorMessage);
        }

        private void OnLoadSceneUpdate(object sender, GameEventArgs e)
        {
            LoadSceneUpdateEventArgs ne = (LoadSceneUpdateEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' update, progress '{1}'.", ne.SceneAssetName, ne.Progress.ToString("P2"));
        }

        private void OnLoadSceneDependencyAsset(object sender, GameEventArgs e)
        {
            LoadSceneDependencyAssetEventArgs ne = (LoadSceneDependencyAssetEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Info("Load scene '{0}' dependency asset '{1}', count '{2}/{3}'.", ne.SceneAssetName, ne.DependencyAssetName, ne.LoadedCount.ToString(), ne.TotalCount.ToString());
        }
    }
}

        然后运行!

        按照剧本应该要报错了,啊确实出了问题:

        尴尬,抄都不会抄了我。。。。

        于是去改一下:

        顺便把场景加到build settings里面:

         然后测试运行:

 

         搞定!

        下面开始写菜单流程!

2023/6/28

感谢各位大佬反映出这篇博客的错误!!!

上面的步骤有个疏漏:在LoadDataTable(string dataTableName)中,通过

m_LoadedFlag.Add(dataTableAssetName, false);

添加了一个加载标记,此时需要写一个和

 类似的回调函数,并且注册在LoadDataTableSuccessEvent事件中,用来在数据表加载成功后设置标记为true。否则的话会一直卡在update()里面。

补充下面这些代码在ProcedureLaunch.cs里面:

        private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
        {
            LoadDataTableSuccessEventArgs ne = (LoadDataTableSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadedFlag[ne.DataTableAssetName] = true;
            Log.Info("Load data table '{0}' OK.", ne.DataTableAssetName);
        }

        private void OnLoadDataTableFailure(object sender, GameEventArgs e)
        {
            LoadDataTableFailureEventArgs ne = (LoadDataTableFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName, ne.DataTableAssetName, ne.ErrorMessage);
        }

 

 

        

 

        

        

        

        

GameFramework框架详解之 Procedure 流程管理 GameFramework框架给我们提供了Procedure(流程)模块,可以帮助我们管理游戏中的各个阶段。Procedure可以将游戏过程划分为多个步骤(即流程),分别对应游戏中的各个阶段,并可以在不同流程之间进行切换。例如,游戏中可能有启动流程、登录流程、主菜单流程、游戏关卡流程等。Procedure基于状态机的思想,将每个流程看作一个状态,通过切换状态来执行不同的流程。在每个流程中,可以设置一系列回调函数,以实现对流程的控制和管理。 阅读详情

相关推荐

【GameFramework框架内置模块】13、流程(Procedure)

流程(Procedure)可以帮助我们管理游戏中的各个阶段。在StarForceProcedure基于FSM状态机的思想,将每个流程看成一个状态,通过切换状态来执行不同的流程。在每个流程中,设置回调函数,可以对流程进行控制和管理,比如下载的操作,等待下载完毕再切换状态。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2057

【Unity】 HTFramework框架(五)Procedure流程管理器

索引Procedure模块简介使用Procedure自定义流程启用流程设置默认流程切换流程 Procedure模块简介 Procedure是框架的核心模块,也是最基本的模块,他贯穿整个框架的始终,从框架的生命周期开始,到生命周期结束,都会在流程间完成,同时,他又是一个强化版的有限状态机,当在多个流程间切换直至最终流程时,便代表整个系统的结束。 使用Procedure 自定义流程 使用Procedu...

神码编程 4965

2024东南大学533复试C++程序设计笔试真题精讲

【东南553复试C++】2024东南大学533复试C++程序设计笔试真题精讲

转遍世界 3415

GameFrameWork框架(Unity3D)使用笔记(八) 实现场景加载进度条

游戏在转换场景的时候,需要花费时间来加载相关的资源。而这个过程往往因为游戏场景的规模和复杂度以及玩家电脑配置的原因花费一小段时间(虽然这个项目里用不到)。目前大多数游戏在转换关卡这种时候都会有个加载界面,显示加载进度。这样玩家可以对啥时候能加载好有个心理预估(判断要不要因为加载太久浪费时间不如卸载游戏(开个玩笑))。那本篇的任务就是探究如何在UGF框架下实现加载场景的进度条功能。

HowToPause的博客 4699

scGPT-spatial 复现

文章摘要:Spatial scGPT项目复现流程 本文详细介绍了复现Spatial scGPT项目的完整流程,包含数据预处理、模型训练等关键步骤。首先需要使用scanpy加载H5AD文件并进行归一化、对数变换等预处理。然后构建基因词汇表(vocab),提取基因表达值和空间坐标信息。接着使用DataCollator进行数据分箱、掩码和填充处理。最后搭建TransformerModel进行训练。文章特别指出了需要自行补全的缺失部分,包括基因词汇表构建、空间坐标提取、数据集类定义和训练主循环脚本等。作者还提供了详

victory0431的博客 1683

模拟量传输4-20ma电流

大家可能会非常熟悉RS232,RS485,CAN等工业上常用的总线,他们都是传输数字信号的方式。那么,我们用什么方式来传输模拟信号呢?工业上普遍需要测量各类非电物理量,例如温度、压力、速度、角度等,这些都需要转换成模拟量电信号才能传输到几百米外的控制室或显示设备上。工业上最广泛采用的是用4~20mA电流来传输模拟量。 采用电流信号的原因是不容易受干扰,因为工业现场的噪声电压的幅度可能达到数V,但是噪声的功率很弱,所以噪声电流通常小于nA级别,因此给4-20mA传输带来的误差非常小;电流源内阻趋于无穷.

tangdongming的博客 1万+

GameFramework框架——StarForce案例之游戏流程大体知识总结

目录 一、 ProcedureLaunch流程 二、ProcedureSplash流程 三、ProcedureCheckVersion流程 *四、ProcedureUpdateVersion流程 五、ProcedureCheckResources流程 六、ProcedureUpdateResources流程 七、ProcedurePreload流程【预加载流程】 八、ProcedureChangeScene流程 九、ProcedureMenu流程 十、ProcedureMain流程 一

两水先木示的博客 2170

【Unity动画系统】详解Root Motion动画在Unity中的应用(一)

什么时候勾选Bake into pose,当不希望动画带动游戏对象旋转时。在旋转的动画中一般是不用勾选的,因为就需要用它来带动我们的角色对象旋转。但在比如前进、后退、待机等动画来说,我们就可以勾选这里,以避免因动画文件本身的瑕疵而给我们带来的旋转。loop match:代表了这个动画在角度上的吻合度。如果这个动画在播放中转角过大,那么就会显示红色,告诉我们如果勾选bake into pose,则会带来不好的效果。

weixin_60154963的博客 6804

GameFrameWork框架(Unity3D)使用笔记(五)游戏主流程ProcedureMain

前面已经完成了UI界面切换等功能,但是真正的游戏内容主体部分还没有开始,下面就来实现游戏的主流程。本篇的内容又用到了GF的一个新模块:Entity。这一次我们主要实现的就是在场景中生成主角。

HowToPause的博客 2545

形状记忆合金热机械本构模型的ABAQUS子程序实现与Fortran\_ABAQUS编程实践

本文详细介绍了如何使用ABAQUS子程序实现形状记忆合金的热机械本构模型,并通过Fortran_ABAQUS进行编程实践。我们首先介绍了问题的背景和目标,然后讲解了如何在Fortran_ABAQUS子程序中实现热变形模型、应力应变关系和相变模型,最后进行了ABAQUS模拟,并分析了模拟结果。希望通过本文的讲解,能让大家更深入理解ABAQUS子程序以及Fortran的使用,也希望能对大家在进行相关学习或研究工作时提供一些帮助。

qq_38334677的博客 1327

Dify智能体开发:Dify文件上传

相较于聊天文本,文档文件能够承载大量的信息,例如学术报告、法律合同。受限于 LLM 自身仅能够支持文件或图片,难以获取文件内更加丰富的上下文信息,应用的使用者不得不手动复制粘贴大量信息与 LLM 对话,增加了许多不必要的使用成本。

王国平的博客 2590

【Unity 3D】GameFramework、QFramework框架简介及应用实战(超详细 附源码)

【Unity 3D】GameFramework、QFramework框架简介及应用实战(超详细 附源码)

showswoller的博客 1万+

Python 实战:全面解析“微信搜一搜”内容爬取,从入门到企业级架构

本文将带你从零搭建爬虫项目,采用 Requests、Scrapy、Selenium、Proxy 池、中间人监控(如 Fiddler/mitmproxy)、分布式调度、数据库持久化、断点续抓等方案,实现可持续、抗封能力强的内容抓取系统。理解“微信搜一搜”页面结构与 Javascript 渲染逻辑;使用 Scrapy 框架搭建分布式爬虫;使用 Selenium 模拟浏览器抓取;构建代理池提升爬取成功率;对抗验证码、IP 封禁与 cookie 过期问题;

2201_76125261的博客 1393

【无标题】GameFrameWork框架接入Adressable,CatAsset,YooAsset,X-asset资源管理方案

GameFrameWork框架完美接入Adressable,CatAsset,YooAsset,X-asset

weixin_43838912的博客 3463

Android 车联网——CarAudioService介绍(六)

CarAudioService 是 Android Automotive OS 中的一个重要组件,用于管理车辆中的音频功能。它是 Android Auto 的一部分,负责处理车辆音频的播放、控制和路由。CarAudioService 使用标准的 Android 组件架构,基于 Binder 通信机制,提供了一组 API,用于管理车辆音频。它包括以下主要功能:音频路由管理:CarAudioService 可以让开发者控制音频的路由,即将音频发送到不同的输出设备,例如车辆的扬声器、耳机等。

小旭的专栏 3201

ArcGISEngine.rar_ArcEngine CSHARP_arcengine教程_arcgis engine_engi

arcengine 入门教程含有源代码希望对大家有很大的帮助

Unity 状态机

【代码】Unity 状态机。

lee2813的博客 542

SAE USCAR2-8 2022.pdf

SAE USCAR2-8 2022.pdf

Unity实现场景切换的方法

很多游戏和程序都不止在一个场景中运行,就需要进行场景视图的切换,在Unity中实现场景切换的方法非常简单,几句话就能说清楚: 1、Unity中切换场景使用的是Application.LoadLevel()函数,括号中加入场景的名称或编...

alayeshi的专栏 5万+

最新2025江西省村界村级行政区划矢量shp数据下载

最新2025江西省村界村级行政区划矢量shp数据,几万个面,属性包含村、社区乡、街道镇、市多级属性,非常准确

【音频硬件设计】基于JL7033C芯片的Soundbar系统原理图:集成蓝牙、FM、HDMI ARC与多输入音频处理方案

内容概要:本文档为JL7033C Soundbar标准硬件原理图(V1.0),详细展示了基于JL7033C主控芯片的Soundbar音响系统的完整硬件设计方案,涵盖电源管理、音频输入输出、蓝牙/NFC/红外/USB/SD卡等外设接口、HDMI ARC与同轴光纤数字音频输入、麦克风接入、充电与电池保护电路等模块。文档提供了详细的电路设计、关键元器件选型建议(如TVS、ESD管、晶振参数)、PCB布局规范(如AGND/GND分区、差分走线)、电源域定义及安全设计规范,并包含多种可选设计方案(如SD检测方式、充电IC选型、MIC供电方式等),适用于开发具备多功能输入、内置充电、语音交互能力的条形音响产品。;适合人群:从事音频产品硬件设计的电子工程师、嵌入式系统开发人员以及音响类产品研发团队成员,需具备一定的模拟/数字电路基础和PCB设计经验。;使用场景及目标:①用于指导基于JL7033C芯片的Soundbar产品硬件开发与电路设计;②帮助工程师理解多源音频输入整合、电源管理、抗干扰布局、静电与浪涌防护等关键技术实现方案;③作为产品打样、测试和优化的设计参考依据。;阅读建议:此资源以工程图纸为主,建议结合杰理官方数据手册和应用笔记配合阅读,重点关注各功能模块的接口定义、电源设计要点及安全规范,在实际开发中严格遵循推荐参数和布线规则,避免因设计偏差导致功能异常或可靠性问题。

Unity Game FrameWork—框架学习—流程对状态机封装

IFsm:接口功能,获取有限状态机(名称、持有者、状态数量、是否正常运行、持续时间、当前状态,所有状态、数据(设置、移除、获取))、开始有限状态机、是否存在有限状态机状态。m_Fsms中的流程类是在ProduceManager流程管理器的初始化方法Initialize中创建状态,foreach流程轮询会判断流程是否销毁,销毁即跳过,只执行当前流程的Update。定义了流程的初始化、进入、轮询、离开、销毁生命周期方法。分析完代码,流程的本质其实是状态机,创建流程就是创建状态机,流程是对状态机进行了一层封装。

qq_37619255的博客 681

Unity GameFramework StarForce 流程介绍

根据提供的案例参考即可实现自己的组件。

zzzsss123333的博客 1558

(001)UnityGameFrameWork Procedure 的流程

游戏启动流程

WGYHAPPY的博客 279

GameFrameWork框架(Unity3D)使用笔记(六)游戏主流程ProcedureMain——从数据表加载出所需实体

养成实体从数据表配置中加载的好习惯。

HowToPause的博客 1807

【亲测免费】 GameFramework-at-YooAsset 使用教程

GameFramework-at-YooAsset 是一个结合了 GameFramework 和 YooAsset 的开源项目,旨在为游戏开发者提供一个高效、灵活的资源管理解决方案。GameFramework 是一个轻量级的游戏框架,而 YooAsset 是一个强大的资源管理系统,两者结合可以大大提升游戏开发的效率和资源管理的便捷性。 ## 项目快速启动 ### 环境准备 在开始之前,请确保...

gitblog_00744的博客 1521

Unity Game FrameWork—框架学习—组件对模块封装

我们再往下看一下实体管理器的接口是在哪实现的,通过断点调试可以看到,此时的模块名称变为了EntityManager。框架的结构已经很清晰了,里面还有很多未知的东西,比如数据提供者,数据持有者是什么东西,还不是很清楚,希望可以通过这个框架对游戏的整个流程以及各个模块有一个全面的了解。我们以实体组件为例,在实体组件中调用base.Awake()完成组件的注册之后,会立即获取模块。实体组件获取的模块是实体管理器的接口。这时,我们可以明白,组件通过管理器的接口创建管理器,组件的方法大多是调用管理器的方法来实现。

qq_37619255的博客 587

GameFrameWork框架(Unity3D)使用笔记(一)Entry

GameFrameWork框架(Unity3D)使用笔记(一)Entry。本篇讲解了如何引用框架以及创建GameEntry。

HowToPause的博客 6942

GameFramework-at-YooAsset 项目教程

GameFramework-at-YooAsset 项目的目录结构如下: ``` GameFramework-at-YooAsset/ ├── Assets/ │ ├── GameFramework/ │ │ ├── Base/ │ │ ├── Config/ │ │ ├── Editor/ │ │ ├── Runtime/ │ │ ├── Scrip...

gitblog_00916的博客 1248

Gameframework资源管理适配其他资源管理方案

由于我们实际使用的过程中只会使用上面定义的接口,所以可以直接return了。两个版本由于是单独构建的,因此无法实现一次打包,两个版本互用的情况。使用mono来实现这个接口,在启动应用的时候注册到GFAdapterResourceManager 中,操作和ufg的editor资源加载方案相似。实现CustomResourceManagerBase,简单的把ugf中的editor相关的移植过来。在做之前,我们需要研究一下,常用的几款资源管理方案。此处的接口是按照ugf的接口进行提出的,方便适配。

zweiluan的博客 1071
上一篇: 游戏开发者的操作系统课设的正确打开方式(Unity3D)
下一篇: GameFrameWork框架(Unity)学习资料汇总(持续更新)
咖啡咖_CoffCa
博客等级 码龄6年 116粉丝 58原创
评论 17
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡咖_CoffCa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值