Unity异步加载方式
异步方案
逻辑放在 Update / LateUpdate
容易出错,且依赖于 Monobehavior
协程:通过开启协程进行异步操作
消耗大:每帧消耗40kb GC
与主线程在同一核心
依托于 Monobehavior
C# 内置 async / await Task
不需要依赖 Monobehavior
但涉及到多线程分配,不符合 Unity 设计,且消耗大
Unity Task
不依赖 Monobehavior
在主线程中与 Unity 协同
实现协程的效果,且不产生 GC消耗
异步网络资源需要手动释放,不释放会一直调用
协程
协程的本质是迭代器,协程函数的调用会实例化一个接口对象
IEnumerator 类是函数对象容器,依次执行容器里面的函数,也就是不断执行注册给这个委托的函数
每执行完一次有一个当前的返回值,yeild return返回
等待时间返回 waitsecond类,通过这个类里面的计时器,每帧更新计时器
yeild抽出两个yeild之间的函数代码放到IEnumerator容器中
每帧都要判断(每个Update执行一次IEnumera ...
Unity Dots介绍
Dots 概述什么是Dots
Data Oriented Technology Stack 面向数据的技术栈
The C# Jobs:多线程控制
The Burst compiler:更快速的编译器
Unity Mathematics
Collections
Entities:数据和模组分开
为什么要用DotsUnity 传统方法
面向对象的方法原本数据在内存中随机分布,每次需要调用一个组件或者方法的时候在内存上找毫无规律,查找效率慢
只有一个主线程,虽然有协程,实际上也是在主线程上控制的
GameObject 在使用时,在调用其某些属性时,其他属性也还在 GameObject 上,浪费内存空间
Unity Dots 特点
与面向对象的设计相比,Dots面向数据和内存,可以多线程能够更好的应用到多核CPU
ECS 的数据是有规律存放,在找的时候可以很快找到并且更快找到其类似的数据,提高了效率,有利于批量处理
Data 和 Component 分开,在不需要某些 Component 时可以关闭
在大型开放世界,多人场景,需要多线程加载的情况效果最好
怎么用Dots
EC ...
3DRPG游戏开发核心功能09-背包UI系统
主要技术:UGUI,背包显示与功能,背包数据库,世界物品拾取与掉落,武器装备
背包基本UI
步骤
建立 UI-canvens,子物体panel,设置 panel 背景图片比例
对素材UI需要进行缩放,选中素材本身,Inspector 窗口Sprite Editor 绿色框线外是保持比例不缩放的,只对绿色框内进行缩放
然后将Panel的ImageType设置为Sliced
新建标题图片文本框,新建退出按钮
Set Native Size 恢复原始尺寸
新建背包内格子
格子网格化控制使用Grid Layout Group
每个格子添加 图像(背包物品) 和 文本(数量)
最终效果
世界地图上的物品
人物收集到物品 添加到背包
地图上的物体 挂载rigibody和collider,数据等
123456789101112131415161718# ItemData_SOpublic enum ItemType { Useable, Weapon, Armor } [CreateAssetMenu(fileName = " ...
3DRPG游戏开发核心功能08-场景转换与传送
主要技术:同异场景传送,协程,ShaderGraph,TimeLine切换动画
传送门
传送门:同场景传送 不同场景传送
可传送状态(Player 碰撞传送门触发)且按下E
判断 传送场景类型 TransitionType { SameScene, DifferentScene }
遍历该场景内的终点,选择对应终点 destinationTag
通过协程传送 destinationTag 位置给 Player 位置 SetPositionAndRotation
Shader Graph 创造传送门
创建Shader Graph
URP 创建
右键QUAD平面显示
Shader设置
创建Shader保存,创建Material 挂载 shader
同场景传送
传送点
123456789101112131415161718192021222324252627282930313233343536# TransitionPoint// 传送门 传送当前场景或其他场景 其他场景判断哪一个终点 E键传送public class TransitionPoint : Mo ...
3DRPG游戏开发核心功能07-UI设置
主要技术:UI,Cavens,血条显示,玩家信息UI,主菜单UI
血条显示UI
新建UI -> Cavens(UI挂载在上面) -> image(血条)
2D Sprite:2D图形插件
血量显示:设置两层血条,上层按血量比例显示
Action 方法
12345using System;// Action方法 攻击的时候更新参数public event Action<int, int> UpdateHealthBarOnAttack; // 血条UI和任务升级属性等 UpdateHealthBarOnAttack?.Invoke(CurrentHealth, MaxHealth);
取子物体,按子物体顺序 0 1 2 ,子物体的子物体 0 0, 01……
1healthSlider = UIbar.GetChild(0).GetComponent<Image>();
12345678910111213141516171819202122232425262728293031323334353637383940414243444 ...
3DRPG游戏开发核心功能06-特殊敌人
主要技术:Animator Override Contraller,Animator Behavior,判断角色前后关系,粒子系统
制作更多敌人独立 CharacterStates
N 个 Enemy 的 CharacterStates 导入的 CharacterData_SO 数据不应该是一样
1234# CharacterStates// 模板数据,n只敌人数据不一致 public CharacterData_SO templateData; public CharacterData_SO characterData;
多增加一个 CharacterData_SO 类型的变量记录当前敌人数据
123456789void Awake(){ // 两只史莱姆不会互相影响 if (templateData != null) { // 复制数据模板,新生成一个 CharacterData_SO 类型的 templateData characterData = Instantiate(templateData) ...
3DRPG游戏开发核心功能05-观察者模式订阅广播
主要技术:泛型单例模式,观察者模式,接口,游戏管理器
Singleton 泛型单例模式单例模式:Manager变量需要实例化才能使用,使用单例模式所有 Manager 变量都可以做 T ,不需要在每个Manager脚本里面实例化
protected virtual void Awake() 子类继承访问可重载
protected override void Awake() 子类继承重载
123456789101112131415161718192021222324252627282930313233343536373839# Singleton// 泛型类创建<T> 继承于MonoBehaviour T:Singleton<T> T为singleton类型public class Singleton<T> : MonoBehaviour where T:Singleton<T> { // 所有Manager变量都可以做T private static T instance; // ...
3DRPG游戏开发核心功能04-数值文件和保存数据
主要技术:Scripts Object 数值文件,角色升级系统,JSON数据保存
Scripts Object 数值文件
CharacterData 人物数值
生命数值
在菜单中创建数值文件类型
[CreateAssetMenu(fileName ="New Data", menuName = "Character Stats/Data")]
生命基础数值类型(玩家和敌人各一个)
12345678910111213141516# CharacterData_SO[CreateAssetMenu(fileName ="New Data", menuName = "Character Stats/Data")]public class CharacterData_SO : ScriptableObject{ [Header("Stats Info")] // 最大血量 public int maxHealth; // 当前血量 public in ...
3DRPG游戏开发核心功能03-敌人及玩家控制
主要技术:Animator,Shader Graph,敌人状态切换及动画,玩家攻击控制
Animator 动画控制器
新建 Animator Controller,控制角色各种动画效果的切换
Blend Tree
通过float类型速度判断停止-走路-跑步用Blend Tree是比较方便的
右键新建 Blend Tree
12345private void SwitchAnimation(){ // 直接用agent可以获得速度 返回浮点值 anim.SetFloat("Speed", agent.velocity.sqrMagnitude);}
Animator
切换状态时不需要退出动画,从一个状态切换回默认状态需要播放完动画,Exit设置为1
设置多层Animator,权重越大越优先执行
Shader Graph
可视化Shader:这里用于控制遮挡显示
修改物体表面,就是修改物体的 Material,也可以通过写Shader,创建对应的Material,即可将Shader效果赋给物体
创建Shader
Pro ...
3DRPG游戏开发核心功能02-鼠标控制和相机特效
主要技术:射线判断鼠标位置,鼠标添加事件,ShaderGraph,Cinemachine,Post Postcessing
鼠标管理器
事件:通过点击或其他判定实现一个函数方法
创建鼠标点击事件
定义完事件之后,优先想将什么函数加进去
public event Action<Vector3> OnMouseClicked:OnMouseClicked是一个事件,在里面添加函数
添加方法:在PlayerController中将位移函数MoveToTarget 注册到事件中,MouseManager.Instance.OnMouseClicked += MoveToTarget
添加方法:在PlayerController中将移动到敌人位置函数EventAttack 注册到事件中,MouseManager.Instance.OnEnemyClicked += EventAttack;
选中 NavMeshAgent - Destination 就是 agent 的目标点,将目标点传给 NavMeshAgent 的位置移动
射线判断鼠标点击位置
射线是通过碰撞体判断的 ...
3DRPG游戏开发核心功能01—场景搭建
主要技术:URP,PolyBrush,NavMeshAgent
通用渲染管线
该项目基于 Universal RP(URP) 通用渲染管线
设置项目为 URP
Project -> Rendering -> Universal Render Pipeline -> PipelineAssert
Project seeting
升级场景中的素材至 URP
Edit -> Render Pipeline -> Universal Render Pipeline -> Upgrade Project Materials to UniversalIRP Material
URP设置
场景构建天空盒
Skybox 设置在 Materials里面
灯光设置
Lighing_Scene
Lighing_Environment
fog:Lighing_Environment
地面设置
v:放置Prefabs时,拖起物体按v顶点自动吸附
Ctrl+Shift:物体自动吸附表面
SceneCamera 和 GameCamera ...
A*最短路径算法实现
A*算法原理
用来解决什么问题
最短路径问题
A*寻路就是用来计算玩家行进路径的,通过它可以计算出避开阻挡的最短路径
基本原理
不停的找自己周围的点,选出一个新的点作为起点再循环找
详细原理
寻路消耗公式
f (寻路消耗)= g(离起点的距离) + h(离终点的距离)
离起点 g:勾股定理和直线距离,父对象离起点的距离+自己离父对象的距离
离终点 h:曼哈顿距离,直接算x,y格子差
开启列表
开启和关闭作为容器
关闭列表
每次往关闭列表放点,都要判断该点和终点是否一样
最后开启列表为空,关闭列表仍没有终点值说明是死路
每次从新的点找周围的点时,如果周围的点已经在开启/关闭列表中,就不用查找
格子对象的父对象
从关闭列表最后一个点(终点)依次找父对象,就是链表
取父对象而不是关闭列表的原因:路径上有阻挡,关闭列表的点不对,可能要换掉前面的点,关闭列表里面的点可能有不对是绕路的,通过父对象找到的才是对的,通过父对象回溯。
步骤
起点放入关闭列表,设置起点父对象为空
遍历起点周围8个点,放到开启列表,并记录其父对象(上一步)
选出最合适的点,最优放 ...