自由学习记录(19)
unity核心也算是看完了吧,但觉得的确是少了点东西,之后再看mvc框架,和网络开发,,感觉有必要想想主次顺序了,毕竟在明年的3月之前尽量让自己更有贴合需求的能力
先了解一些相关概念,不用看懂,注意一些要出现的词,大致理解一下,留个印象即可
mvc先开荒吧----over
Addressables
看上去应该不是很新的东西,像是对之前功能的集成升级
Addressables 是 Unity 提供的一个资源管理系统,用于简化和优化游戏资源的加载、存储和更新。它是 Unity 对传统 Asset Bundles 的升级,提供了更高效、更灵活的方式来管理和加载游戏中的资源,特别是在 热更新 和 跨平台开发 中发挥了重要作用。
Addressables 系统的核心功能
-
资源标识(Addressable):
- 资源在 Addressables 中被赋予一个 地址,这个地址可以是任何字符串或 GUID,用于标识资源。开发者可以通过地址来访问、加载、卸载资源,而不需要知道资源的具体位置或路径。
- 这种机制让资源的管理更加灵活,因为你可以在游戏运行时动态加载和卸载资源,而不必依赖传统的路径和文件夹结构。
-
按需加载:
- Addressables 支持 异步加载,即在需要时加载资源,而不是在启动时一次性加载所有资源。这有助于减少内存占用,并提高游戏启动和运行时的性能。
- 通过 异步加载,可以避免游戏启动时的大量资源加载,从而提升用户体验。
-
资源分组和打包:
- Addressables 允许开发者将资源按 分组 来管理,每个组可以打包成一个 Asset Bundle(资源包)。这些资源包可以在运行时通过网络或本地路径进行加载,避免了资源文件的重复打包,提高了资源的重用性。
- 开发者可以通过简单的设置来控制哪些资源需要下载,哪些可以从本地加载,或者哪些需要在某些条件下更新。
-
跨平台支持:
- Addressables 系统可以在多个平台上使用,并且支持平台特定的资源管理。通过 Addressables,开发者能够更容易地管理和加载不同平台(如 iOS、Android、PC 等)上的资源。
- 通过智能资源打包和版本管理,可以为不同平台提供优化过的资源包。
-
资源更新和热更新:
- Addressables 支持通过 远程加载 资源,这意味着资源可以存储在服务器上,并且可以在游戏运行时从服务器动态下载和更新。这对于实现 热更新 和 内容更新(例如:增加新的关卡、角色、皮肤等)非常重要。
- 当更新了资源包后,玩家可以在不重新安装游戏的情况下,动态加载新资源。
-
内存管理和资源卸载:
- Addressables 提供了智能的资源卸载机制,帮助开发者有效地管理内存。当一个资源不再需要时,Addressables 会将其从内存中卸载,以避免内存泄漏和高内存消耗的问题。
- 卸载资源时,开发者可以手动或自动控制资源的生命周期和内存释放。
Addressables 的优势
-
易于管理和加载资源:
- 通过地址来标识资源,开发者不再需要直接操作文件路径和资源引用,代码更加简洁、清晰。
- 资源的加载变得更加灵活,可以支持动态加载、卸载和资源更新。
-
提升性能:
- 支持异步加载和按需加载,减少了游戏启动时的资源加载时间,提高了内存的使用效率。
- 地址化资源可以根据平台和需求进行优化,避免冗余资源的加载。
-
简化资源更新:
- 通过远程加载和服务器管理,Addressables 使得资源更新更加高效和灵活,特别适合需要 热更新 和 持续内容更新 的游戏。
- 通过对资源的版本管理,开发者可以精确控制每次更新的内容。
-
支持大型项目和跨平台开发:
- Addressables 适合用于大型项目,特别是资源多且复杂的游戏。它能有效地管理资源的生命周期,避免因加载大量资源而导致的性能瓶颈。
- Addressables 可以在多个平台之间共享资源,减少了不同平台资源管理的复杂度。
-
集成简单:
- Unity 的 Addressables 系统集成较为简单,提供了 API 和 编辑器工具,帮助开发者快速设置、管理和打包资源。
- 通过 Unity 编辑器,可以轻松标记资源为 Addressable,并定义资源的加载行为。
Addressables 的工作流程
-
设置资源为 Addressable:
- 在 Unity 编辑器中,将资源标记为 Addressable。这样,Unity 会为该资源分配一个 唯一地址,并允许你在代码中通过该地址访问该资源。
-
创建资源分组:
- 你可以将资源组织成不同的 分组,并为每个分组配置不同的加载策略(例如:本地加载、远程加载、异步加载等)。
- 每个分组会被打包为一个 Asset Bundle,可以在运行时通过网络或本地路径加载。
-
打包和构建资源:
- 使用 Unity 编辑器的 Addressables 面板,你可以将所有 Addressable 资源打包成 Asset Bundles,并根据平台和需求生成资源包。
- Unity 会自动处理资源依赖关系,确保加载的资源和依赖资源的正确性。
-
加载资源:
- 在游戏运行时,你可以通过代码使用 Addressables API 来加载和访问资源。例如,可以使用
Addressables.LoadAssetAsync<T>
异步加载资源。 - 你可以指定加载方式(同步或异步),并在加载完成后执行回调。
- 在游戏运行时,你可以通过代码使用 Addressables API 来加载和访问资源。例如,可以使用
-
卸载资源:
- 使用
Addressables.Release
来卸载不再需要的资源,释放内存。
- 使用
-
远程加载与更新:
- 资源可以从远程服务器下载,支持实时更新和 热更新。当更新资源时,客户端会根据配置的地址从服务器下载新的资源包,并在游戏运行时替换旧的资源。
示例:如何在 Unity 中使用 Addressables
-
设置资源为 Addressable:
- 右键单击资源,选择 Addressable,并给资源分配一个地址,例如
playerModel
。
- 右键单击资源,选择 Addressable,并给资源分配一个地址,例如
-
加载资源:
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;public class AddressablesExample : MonoBehaviour
{public AssetReference playerModel;void Start(){// 异步加载资源playerModel.LoadAssetAsync<GameObject>().Completed += OnResourceLoaded;}private void OnResourceLoaded(AsyncOperationHandle<GameObject> handle){if (handle.Status == AsyncOperationStatus.Succeeded){// 实例化加载的资源Instantiate(handle.Result);}}
}
总结
Addressables 是 Unity 中的一个强大资源管理系统,提供了高效的资源加载、管理和更新机制。它通过引入地址标识资源、支持异步加载和按需加载、大规模资源打包、跨平台支持等功能,使得开发者能够更好地管理游戏中的资源,尤其适合大型游戏和需要频繁更新的游戏项目。对于热更新、资源管理、性能优化等方面,Addressables 提供了极大的便利。
Unity 热更新
Unity 热更新 是指在游戏运行时,不需要重新启动游戏,就能动态更新游戏中的 代码、资源 或 逻辑,从而实现快速修复、功能扩展或优化。它让开发者在不发布新版本的情况下,向已经发布的游戏客户端推送更新内容,从而提升用户体验并减少版本更新的频率。
热更新的核心目的是通过 修改游戏资源 或 代码,直接在用户设备上进行更新,而不需要重新下载并安装整个新版本的应用。
热更新的主要内容:
-
代码热更新:
- 通过热更新,开发者可以在不重新发布游戏包的情况下,更新游戏中的 脚本(如 C# 代码),修复bug或添加新功能。
- 代码热更新通常需要借助一些外部工具和框架,如 IL2CPP(Unity的脚本引擎)、Mono、或者使用更高级的插件来实现对代码的动态加载。
-
资源热更新:
- 热更新不仅限于代码,还可以包括 游戏资源(如图像、音频、模型等),通过网络下载更新的资源包,并在游戏运行时替换原有资源。
- Unity 提供了 Asset Bundles(资源包) 和 Addressable Asset System(可寻址资源系统)等功能,可以帮助开发者打包和更新资源。
热更新的工作原理:
-
热更新框架:大多数 Unity 游戏使用第三方热更新框架,例如 XLua、ILRuntime 或 HotFix 等,它们提供了在运行时加载和替换代码的能力。这些框架一般允许开发者将热更新的代码与游戏主代码分离开来,便于后续更新和维护。
-
资源管理:Unity 的 Asset Bundle 和 Addressable Assets 系统支持将游戏资源打包为独立的文件,在游戏运行时动态下载和替换资源。这些资源通过网络请求获取并在本地缓存,使得资源的更新无需重新安装游戏。
-
服务器支持:通常,热更新的资源和代码会被存储在服务器上,游戏客户端通过 HTTP 或其他协议从服务器下载更新。客户端在启动时或运行过程中会检查是否有新的资源或代码版本,并下载相应内容。
-
更新方式:
- 增量更新:更新的内容是增量的,即只下载和替换发生变化的部分,减少下载时间和流量。
- 全量更新:有时也会推送全量更新,用户需要重新下载新的资源包或完整的游戏内容。
热更新的优势:
-
快速修复:通过热更新,开发者可以快速修复游戏中的 bug,而无需等待应用商店审核和发布新版本。尤其在手游和大规模在线游戏中,快速修复是非常重要的。
-
减少发布频率:开发者可以减少版本更新的频率,不必每次改动都发布一个新的应用包,节省了更新过程中的时间和资源。
-
优化游戏体验:可以通过实时更新游戏资源和内容,提供 新的功能、关卡或活动,让玩家在不重新下载游戏的情况下,体验到新的内容。
-
支持多平台:对于多平台开发,热更新可以帮助开发者在不同平台之间同步更新,不需要为每个平台单独发布更新。
热更新的挑战:
-
安全性问题:热更新涉及在运行时加载和执行外部代码,这可能导致安全风险。需要特别注意防止恶意代码注入或篡改。
-
兼容性问题:游戏的资源或代码更新可能会与现有版本不兼容,尤其是在更新多个系统或组件时,需要确保更新的内容在不同版本的客户端中都能正常运行。
-
存储和性能问题:如果热更新资源过多或过大,可能会对玩家的设备存储和游戏性能产生负面影响。
-
复杂的管理:热更新的管理和版本控制较为复杂,尤其是在多个更新版本同时在线时,需要确保版本间的一致性和正确性。
Unity 热更新的常见实现方法:
-
Asset Bundles + Server:利用 Unity 的 Asset Bundle 技术,开发者可以将资源打包成文件,并通过服务器向客户端推送更新。在客户端加载时,动态更新游戏中的资源。
-
XLua / ILRuntime 等热更新框架:
- XLua:通过 Lua 脚本热更新,让 C# 代码与 Lua 脚本交互,允许在不编译的情况下动态加载 Lua 脚本代码,从而实现热更新。
- ILRuntime:类似于 XLua,它允许开发者通过解析和执行 IL 代码来进行代码热更新,支持在运行时加载和执行 C# 代码。
-
Addressable Assets:Unity 提供的 Addressable Assets 系统能更方便地管理和更新资源,支持按需下载和加载资源。可以将资源分包,并通过服务器进行热更新。
总结:
Unity 热更新是一种非常强大的机制,它允许开发者在游戏发布后进行快速的更新,避免了繁琐的版本更新过程。通过热更新,开发者可以迅速修复 bug,更新资源,增加新功能,而不需要玩家重新安装游戏。虽然热更新在开发中带来很多便利,但它也有一定的技术挑战和安全性风险,需要合理规划和实现。
MVC(Model-View-Controller)
讲的很多,看上去也没什么用,但是就是这么回事,能体会到意思,说的也没错,但说的又太俗套
MVC(Model-View-Controller)是一个经典的设计模式,广泛应用于软件开发中,尤其是 Web 开发 和 桌面应用,但它同样也可以用于 游戏开发。MVC 主要目的是将应用的不同责任划分为三个部分,从而使代码更加 解耦,提高维护性和可扩展性。
在游戏开发中,MVC模式 的三个部分分别是:
-
Model(模型):表示游戏的 数据 和 状态。它负责管理游戏的核心逻辑、规则和数据存储,比如玩家的分数、游戏的关卡、物体的位置等。Model 不关心如何显示这些数据或如何与用户交互,它只是数据的提供者。
-
View(视图):负责 显示 游戏的内容,包括图形界面、动画、UI元素等。它接收来自 Model 的数据,并将这些数据显示给用户。View 并不直接改变数据,只负责展示。
-
Controller(控制器):负责处理用户的 输入(如键盘、鼠标、触摸屏等),并决定如何 更新模型 或 通知视图更新。它是用户和模型/视图之间的桥梁,接收用户操作后将其转化为具体的 游戏行为,并可能修改模型中的数据,进而影响视图的显示。
MVC在游戏开发中的应用:
在游戏开发中,MVC 的主要优势是将游戏的 业务逻辑 和 用户界面 分开,从而让你能更容易地管理和修改它们。具体来说:
1. Model(模型)
- 包含游戏的 状态 和 数据结构。例如,游戏中的角色、敌人、得分、关卡等都是模型的一部分。它通常包含计算和算法,例如角色的移动、物理引擎的计算等。
- 该层通常由 游戏引擎(如Unity或Unreal)提供的核心组件支持,涉及 状态管理、物理系统、碰撞检测、路径寻路 等功能。
例如:
- 游戏的 分数 是一个模型数据,模型负责追踪和计算分数,而视图只负责显示它。
- 游戏中的 玩家位置 是一个模型数据,模型负责更新玩家的坐标,而视图则负责在屏幕上显示玩家的位置。
2. View(视图)
- 视图负责 渲染 画面,显示游戏的图形内容。在MVC中,视图并不关心游戏的 规则,它只是用来显示 数据(例如从模型中提取的数据)。
- 在游戏中,视图通常由 渲染引擎 或 UI 系统 实现,负责把模型的数据转换成 视觉呈现。
例如:
- 在一个角色扮演游戏(RPG)中,视图负责渲染 角色的外观、动画、血条 等。
- 游戏的 UI元素(如分数、生命值)也是视图的一部分。
3. Controller(控制器)
- 控制器是连接用户输入与游戏逻辑之间的桥梁。它负责 响应用户输入(如按键、鼠标点击等),并根据这些输入做出相应的 行为变化。控制器会更新模型中的数据,并可能通知视图更新显示。
- 在某些情况下,控制器也可能会管理不同的 游戏状态(如主菜单、游戏进行中、暂停等),根据当前的游戏状态来决定不同的行为。
例如:
- 在一个平台游戏中,玩家按下方向键时,控制器会将输入传递给模型,更新玩家的位置,然后通知视图重新渲染玩家的新位置。
- 在一个赛车游戏中,控制器可以接收玩家的加速或刹车操作,然后根据操作调整车的速度(模型),并更新视图中的赛车位置。
MVC在游戏开发中的优点:
- 解耦:MVC将游戏的 数据、显示 和 用户交互 分开管理,使得每个部分可以独立工作。这使得游戏的开发、维护和调试变得更容易。
- 可扩展性:由于 视图 和 控制器 独立,游戏逻辑(模型)可以在不改变用户界面的情况下进行修改和优化,反之亦然。
- 易于测试:模型与视图、控制器解耦,模型的测试更加独立,尤其是当需要进行功能测试和单元测试时,模型可以直接在不需要显示界面的情况下进行测试。
- 协作开发:多人协作开发时,开发人员可以独立于不同的部分工作。一个开发者可以负责模型的逻辑实现,另一个负责视图的UI设计,而控制器部分则用于处理数据和交互。
示例:一个简单的 2D 游戏中的 MVC 框架
假设你正在开发一个简单的 跳跃游戏,其中玩家的任务是跳过障碍物,避免碰到它们。
-
Model(模型):管理游戏的状态,比如玩家的位置、得分、是否碰撞等。
- 例如,玩家的位置可以是
(x, y)
坐标,游戏会不断更新这些位置,并计算碰撞状态。
- 例如,玩家的位置可以是
-
View(视图):负责展示游戏中的元素,比如背景、玩家角色、障碍物、得分等。
- 例如,视图会在屏幕上显示当前的玩家角色,并根据模型中存储的位置动态渲染它。
-
Controller(控制器):处理玩家输入(如按键)并更新模型。
- 例如,玩家按下空格键时,控制器会调用模型方法来让玩家角色跳跃,并更新视图以显示角色的新状态。
总结
MVC 是一种 结构化设计模式,用于将游戏的不同功能模块化。通过分离数据(Model)、显示(View)和用户交互(Controller),它使得游戏的 开发、维护和扩展 更加高效和灵活。在大型游戏项目中,采用 MVC 模式有助于简化开发流程,提升代码质量和可读性。
finish---
打包之后的游戏图标在这里设置
场景切换的时候,不需要布局那么大,想清楚当前的场景切换到下一场景后,哪些玩家操作产生的数据也要给到下一场景
处理这种一个场景中玩家操作影响总和到下一场景中的关系输出
写代码逻辑的疏通在于信息的打包,虽然会略显冗余,但对逻辑疏通是很快的
单例不变的数据,加上数据清空的方法,可以避免多次切场景的数据遗留
C#值类型的引用
C# 中的 int
是值类型。值类型存储在栈中,而引用类型(如类)存储在堆中。因为 int
是值类型,当你将它传递给方法或赋值给另一个变量时,实际上是将其值复制一份。
使用 ref
和out关键字,可以使参数转为引用传递的。这意味着方法可以直接修改传入的变量。如果参数需要预先赋值,使用 ref
;如果参数在方法内赋值,使用 out
。
基本上是对值类型的使用,但用在引用类型上也可以有妙用(out
的作用)
public void CreateObject(out MyClass obj) {obj = new MyClass(); // 必须赋值
}
必须换掉这个引用装的整个对象。但ref就基本上对引用类型完全没用了
怪物波数创建逻辑
报错原因在于挂在单个怪物身上的脚本,因为对塔可以造成生命值的修改,而这个生命值挂载的地方是在UI面板上而不是塔上,所以想抠塔的血就必须让UI面板存在
这样直接单独写逻辑,之后要的时候再和UI上的数据变化连接,是可以更有包容性的
数据一旦从资源区转入游戏内存后,就会一直存在,场景的切换完全不影响
抑制玩家的规律推断能力,游戏功能可以如此实现,有出怪点但是不固定,让玩家找不到规律,是对游戏性的提升,但又存在一些规律,比如出怪点的权重设置,出怪点的方向性模糊
any state
Animator 中,Any State
是一个特殊的状态,它允许你从任何其他状态(包括其他的具体状态)直接过渡到一个指定的目标状态
右键点击 Any State
,选择 “Make Transition”,然后将箭头拖动到 Attack
状态。这将创建一个从 Any State
到 Attack
的过渡。
- 点击连接的箭头,进入过渡设置。
- 在条件部分,添加条件:
isAttacking
为true
。 - 当角色处于
Idle
、Run
或Jump
状态时,按下空格键会立即触发攻击动画,无论当前状态是什么。
public class PlayerController : MonoBehaviour {private Animator animator;void Start() {animator = GetComponent<Animator>();}void Update() {// 检测攻击输入if (Input.GetKeyDown(KeyCode.Space)) { // 假设空格键为攻击按钮animator.SetBool("isAttacking", true);}// 其他输入控制(例如移动、跳跃等)// ...}// 在攻击动画结束时,可以重置状态public void OnAttackAnimationEnd() {animator.SetBool("isAttacking", false);}
}
角色将从 Any State
转移到 Attack
状态,而不会经过其他状态。
如果在状态机中使用了自转移,可能会导致状态抖动(jittering),特别是在 Any State
到第一个状态的转换中。这种抖动通常是因为以下几个原因:
-
频繁触发:自转移使得状态机在进入状态后不断重复该状态
-
条件冲突:如果有多个条件在状态机中同时有效,可能会导致状态机反复在两个或多个状态之间切换。例如,当一个状态的条件未满足时,状态机会试图回到
Any State
,然后又迅速再切换回来。
解决方法
-
去掉自转移:在
Any State
到目标状态之间移除自转移可以防止状态机在同一状态中不断切换,从而减少抖动。 -
明确条件:确保从
Any State
进入状态的条件是稳定的,不会频繁触发。例如,如果有参数控制状态的变化,确保这些参数的变化是连贯的,不会在很短的时间内反复变化。 -
使用合适的动画过渡时间:设置合理的过渡时间,使得动画能够自然过渡,而不是瞬间切换。
Any State
转移到某个具体状态的动画时,通常不需要设置“transition to self”
自转移意味着当状态保持不变时,状态机会不断重复该动画。
作为PlayerObject类,再给外界一个可以刷新,初始化玩家当前数据的方法,
为了射线检测,在枪上设置空物体作为开火点,提供射线方向
LayerMask位掩码
layerMask
是一个整数,每一位代表一个层。例如,第一位(1)代表 Layer 0,第二位(2)代表 Layer 1,依此类推。- 如果你希望选择多个层,可以通过按位或(|)操作组合它们。
假设你想要选择 Layer 8 和 Layer 9,你可以这样做:
int layerMask = (1 << 8) | (1 << 9); // 选择 Layer 8 和 Layer 9
Unity 还提供了一些方便的方法来创建 LayerMask。例如,你可以直接在 Inspector 中选择层,然后使用 LayerMask.GetMask
方法来获取掩码:
int layerMask = LayerMask.GetMask("LayerName1", "LayerName2");
荣格