自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

Morris-w的专栏

从零开始

  • 博客(43)
  • 收藏
  • 关注

原创 Shader入门精要总结(一)渲染流水线

这个阶段由应用主导,通常由CPU负责,开发者对这个阶段拥有绝对控制权。在这一阶段,主要有三个任务首先,需要准备好场景数据,例如相机,视椎体,场景中的模型,光源其次,为了提高渲染性能,需要做一个粗粒度剔除的工作,把那些不可见的物体剔除,这样就不再需要移交几何阶段最后,设置好每个模型的渲染状态,包括但不限于使用的材质,使用的纹理,使用的shader ,最终输出渲染图元,即渲染所需几何信息,一般是点,线,三角面等,这些图元最终会被传递到下一阶段。

2024-07-20 20:50:39 640

原创 Unity UGUI ContentSizeFitter源码浅析

这里ILayoutSelfController继承自ILayoutController,先执行了ILayoutSelfController类的设置,在执行了非ILayoutSelfController的设置,最后递归遍历子结点。这里往当前RectTransform 的父亲上寻找符合条件的RectTransform,继续调用MarkLayoutRootForRebuild。首先看MarkLayoutForRebuild方法,调用自LayoutRebuilder的MarkLayoutForRebuild方法。

2024-01-31 03:35:04 491

原创 Unity UGUI Button源码浅析

在往上,来到StandaloneInputModule类的ReleaseMouse方法和ProcessTouchPress方法。对OnPointerClick溯源,调用侧来自ExecuteEvents类的Execute方法。这是一个为鼠标/键盘/控制器输入而设计的BaseInputModule类。再往上溯源多次,最终来到EventSystem的Update方法。此方法用来计算和处理任何鼠标按钮状态的变化。

2024-01-30 04:29:20 491

原创 Unity UGUI Selectable部分源码浅析

物体的可交互属性需要一起判断m_GroupsAllowInteraction 和 m_Interactable。设置状态属性,如果是Editor模式,如果正在运行,那么立即改变,没有过渡,如果非Editor模式,那么有过渡。判断是否高亮,即鼠标移上去的时候,需判断三个状态,鼠标在UI范围内,没有点下,没有选择。当焦点移动到另一个可选择对象时,调用此方法,确定选择的对象。将元素从可选择物体数组列表中移除,同时标记为脏。即时清除状态,将Selectable的状态还原。取消激活时,将自身标记为脏。

2024-01-30 01:52:35 686

原创 Unity RectMask2D源码浅析

其中m_ForceClip 强制裁剪设置主要有两种情况AddClippable和RemoveClippable的情况,都索引自MaskableGraphic类的UpdateClipParent方法。这里会通过MaskUtilities.GetRectMaskForClippable寻找父物体上的RectMask2D组件,这个方法会在激活,取消激活,父节点改变,canvas改变等时候调用。

2024-01-27 00:24:48 634

原创 Unity Mask合批情况验证

mask1首尾2个drawcall,IM1和IM2合批,1个drawcall,mask2首尾2个drawcall,IM3和IM4合批,一个drawcall,再加上相机的默认HDR开启drawcall,总共7个批次。这里和RectMask2D有所不同,IM3在完全不在Mask范围时,是会参与渲染的,但是如果在RectMask2D情况下,是不会参与渲染的。经过计算此种情况的visiableList:mask1,IM1,IM2,mask2,IM3,IM4。发现mask1和mask2的首尾进行了合批。

2024-01-24 05:59:20 526

原创 RectMask2D的合批情况验证

注意,虽然此处被RectMask2D裁剪了,但是在计算深度时属于需要渲染的UI元素,所以绿色图片此时的depth应该是1。经过实际测试,RectMask2D在裁剪区域完全相同且位置完全重合的情况下能够合批。但是当RectMask2D位置不重合时,就不能合批。

2024-01-23 03:48:33 507

原创 RectMask2D不能合批的原因

三张图片的shader和贴图都是一样的,三张图用的都是一个图集里的图,在经过深度计算等一系列操作后,是能够合批的,根据合批规则,应该就是_ClipRect属性改变导致shader不同导致不能合批。发现是因为shader里的_ClipRect属性不一样了导致的。但是给其中一张图加上RectMask2D,发现不能合批了。一般情况下,在这种情况下三个Image会合批。

2024-01-22 00:16:09 442

转载 unity 增量式GC

为什么使用增量式垃圾回收C#语言使用托管内存和自动垃圾回收,这意味着它使用自动化方法跟踪内存中的对象,然后释放不再使用对象的内存。这种做法的优点是,开发者不必手动跟踪释放不需要的内存,因为垃圾回收器会自动执行此操作,这样会使开发者的工作更轻松,同时避免出现潜在Bug。缺点是垃圾回收器需要一些时间完成工作,而开发者或许不希望将特定时间用于此处。Unity使用的是贝姆垃圾回收器(Boehm–Demers–Weiser garbage collector),该回收器利用了Stop-The-World机制,这

2021-10-22 16:43:21 5206

原创 Lua实现矩阵的方式

一.嵌套表local mt={}for i=1,10 do local row={} mt[i]=row for j=1,10 do row[j]=0 endendmt是一个大表,在这个表中有10个小表,每个表中有10个元素二.索引合并for i=1,10 do local aux=(i-1)*10 for j=1,10 do mt[aux+j]=0 endend通过将第一个索引乘以一个合适的常量

2021-08-23 01:13:33 1043

原创 A*寻路的基础实现

本篇文章的算法来源于这里在原来的实现基础上,改为使用UI中的Image表现路径,并且加上了F,G,H的数值显示A*的核心公式,F=G+H,F表示到达这个点的总代价,G表示从起点到达这个点的代价,H表示这个点到终点的代价还有两个集合,open和close,分别代表待检查的点集合和一斤检查过的点集合大概流程1.将待检查的点从open中拿出来,放入close,一般是open里面F最小的点2.获得这个点周围所有的点3.检查这些周围点中是否有障碍物,如果有,直接去掉4.检查周围点中是否有已经在open

2021-08-22 23:21:43 163

转载 Unity批处理

绘制调用批处理要在屏幕上绘制游戏对象,引擎必须向图形 API(例如 OpenGL 或 Direct3D)发出绘制调用。绘制调用通常为资源密集型操作,图形 API 为每次绘制调用执行大量工作,从而导致 CPU 端的性能开销。此开销的主要原因是绘制调用之间的状态变化(例如切换到不同材质),而这种情况会导致图形驱动程序中执行资源密集型验证和转换步骤。Unity 使用两种方法来应对此情况:动态批处理:对于足够小的网格,此方法会在 CPU 上转换网格的顶点,将许多相似顶点组合在一起,并一次性绘制它们。静态批处

2021-08-10 21:44:29 580

原创 基础二分模板

1.第一个大于目标值的元素public int Search(int[] num,int target) { int left=0; int right=num.Length-1; while(left<=right) { int mid=((right-left)>>1)+left; if(num[mid]<=target) { left

2021-08-09 22:07:06 54

原创 背包提示面板踩坑

在做背包面的道具提示面板时,因为想让面板相对鼠标有一个偏移,所以设置了提示面板每帧跟随鼠标,在进入格子的时候显示,离开格子的时候不显示,这个时候发现一个问题,如果提示面板和鼠标离得太近,鼠标射线会射到提示面板,从而影响格子UI的OnPointerEnter和OnPointerExit方法,导致提示面板一闪一闪解决方案有两个1.直接修改提示面板和鼠标的相对距离,使鼠标和提示面板不重叠2.在提示面板上添加Canvas Group 组件,取消勾选Interactable和Blocks Raycasts

2021-07-17 21:19:53 406

原创 C# HashSet<T>源码浅析

所在框架版本:.Net Framework 4.0.303191.部分变量private const int Lower31BitMask = 2147483647;private const int StackAllocThreshold = 100;private const int ShrinkThreshold = 3;private const string CapacityName = "Capacity";private const string ElementsName = "E

2021-06-21 22:03:55 179

原创 C# Queue<T>源码浅析

所在框架版本:.Net Framework 4.0.303191.部分变量private T[] _array; //元素数组private int _head; //队头private int _tail; //队尾private int _size; //元素个数private int _version; //版本号[NonSerialized]private object _syncRoot;private const int _MinimumGrow = 4;

2021-06-20 23:27:39 245

原创 C# stack<T>源码浅析

所在框架版本:.Net Framework 4.0.303191.部分变量private T[] _array; //元素数组private int _size; //元素个数private int _version; //版本号[NonSerialized]private object _syncRoot; private const int _defaultCapacity = 4; //默认容量private static T[] _emptyArray = ne

2021-06-20 21:14:33 114

原创 C# List<T>源码浅析

所在框架版本:.Net Framework 4.0.303191.部分变量private const int _defaultCapacity = 4; //默认容量private T[] _items; //元素数组private int _size; //元素个数private int _version; //版本号[NonSerialized]private object _syncRoot; private static readonly T[] _emptyArra

2021-06-18 04:01:39 470

原创 C# Dictionary<T>源码浅析

所在框架版本:.Net Framework 4.0.303191.Entry结构体,键值对存放的位置private struct Entry { public int hashCode; // 除符号位以外的31位hashCode值, 如果该Entry没有被使用,那么为-1 public int next; //下一个Entry元素的下标索引,如果没有下一个就为-1 public TKey key; //存放元素的键 public TVa

2021-06-16 21:44:24 484

原创 C#使用Array.Sort对二维数组排序

二维数组需要这样定义int[][] nums= new int[][] { new int[]{ 1, 2 }, new int[]{ 3, 4 } };有这几种方式,表示拿每个一维数组的第二个元素比较Array.Sort(nums, (x, y) => x[1].CompareTo(y[1]));Array.Sort(nums, (a, b) => a[1] - b[1]); Array.Sort(nums, (a, b) => { return p1[1] - p2

2021-04-06 20:11:22 1907 1

原创 Unity下换装的主要流程

首先,美术可能会给这样一个游戏物体,里面含有所有的部位,并且每个部位上都有SkinnedMeshRenderer可以先剥离一个只含有骨骼信息的预制体出来,方便等会儿再这个预制体上生成需要两个字典,第一个字典用来存储模型上的所有SkinnedMeshRenderer信息,因为模型里面每个部位会有多个不同的装扮,所以嵌套了一个字典,还有一个字典用来存储target上的SkinnedMeshRenderer信息1.生成需要的两个预制体在这里把原始模型和带骨骼的空预制体target生成2.保存需要

2021-03-07 21:46:07 594

原创 在单例模式下判断某个游戏物体是否显示的情况

比如某个脚本的单例是这种模式private static Character _instance; public static Character Instance { get { if (_instance == null) { _instance = FindObjectOfType(typeof(Character)) as Character;

2021-02-24 02:57:32 152

原创 Unity自带的JsonUtility使用实例

实例代码:Json文件,Item.json{ "Infolist": [ { "id":1, "name":"血瓶", "type":"Consumable", "description":"回血用", "capacity":10, "buyPrice":10, "sellPrice":5, "hp":10, "mp":0, "sprites":"Sprites/Ite

2021-02-02 01:55:25 1136

原创 Lua零碎

四舍五入取整写法,math.floor(x+0.5)保留几位小数且四舍五入,string.format("%0.1f",math.floor( x*10+0.5)/10))

2021-01-20 20:44:42 147

原创 GetEnumerator()方法在现有集合中的调用

GetEnumerator()用来返回支持 IEnumerator 的对象,在用现有集合调用GetEnumerator()方法时,所使用的集合对象必须是静态的public class Test { static int[] num = new int[] { 1,2,3}; //public static List<int> list = new List<int>(num); //List<int>.Enumer

2021-01-05 21:21:44 505

原创 基础排序算法

1.冒泡排序public void BubbleSort(int[] num){ for(int i=0;i<num.Length;i++) { for(int j=0;j<num.Length-1;j++) { if(num[j]>num[j+1]) { Swap(num, j, j + 1); }

2020-12-20 21:52:43 102

原创 二叉树的前,中,后,层序遍历

public class TreeNode{ int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; }}1.前序遍历递归版:public void PreOrde(TreeNode root) { if(root==null) { return; } Wri

2020-12-19 23:19:28 106 1

原创 unity 状态机模式

public enum Transition //状态转换操作的枚举{ NullTransition = 0, StartButtonClick, PauseButtonClick,}public enum StateID //状态枚举{ NullStateID = 0, Menu, Play, Pause, GameOver,}/// <summary>/// This class

2020-10-24 15:34:14 432

原创 C#迭代器手动调用确保执行finally块

public class Program { static void Main() { IEnumerable<int> MyIterator(DateTime dateTime) { try { for(int i=1;i<=100;i++) {

2020-10-23 01:44:54 64

原创 LeetCode 33. 搜索旋转排序数组

解法一:先用二分法找到旋转数组中的最小值,然后分别在最小值的左边和右边进行二分查找,保持时间复杂度是O(logn)+O(logn),最终还是O(logn)public class Solution { public int Search(int[] nums, int target) { if(nums==null || nums.Length<=0) { return -1; } int left .

2020-07-29 01:32:52 77

原创 LeetCode 349. 两个数组的交集

public class Solution { public int[] Intersection(int[] nums1, int[] nums2) { Dictionary<int,int> dic=new Dictionary<int,int>(); //输出的数组中不能有重复,考虑用字典来存储 Array.Sort(nums1); .

2020-07-29 01:15:18 70

原创 LeetCode 167. 两数之和 II - 输入有序数组

本题最好的方法是双指针法,但是这里解释一下二分法public class Solution { public int[] TwoSum(int[] numbers, int target) { for(int i=0;i<numbers.Length;i++) { int left=i+1; //从当前元素的下一个元素开始查找 int right=.

2020-07-29 01:08:20 70

原创 LeetCode 69. x 的平方根

当x较大时,中间变量mid由于类型是int(和函数返回值类型一致), mid * mid会溢出,导致实际结果可能是负数,所以要先强转成long再相乘,或者用mid和x/mid比较。public class Solution { public int MySqrt(int x) { int left=0; int right=x; int ans=-1; while(left<=right) { .

2020-07-29 01:07:50 66

原创 剑指offer 53-1 在排序数组中查找数字 I

public class Solution { public int Search(int[] nums, int target) { int first=FirstIndex(nums,target); int last=LastIndex(nums,target); int count=0; if(first>-1 && last>-1) { count=la.

2020-07-29 01:06:27 81

原创 C#匿名类型的生成

有如下匿名类型代码namespace ListNode{ public class Program { static void Main() { var patent1 = new { Title = "Bifocals", YearOfPublication = "1784"

2020-07-12 18:42:24 409

原创 C# 匿名数组

public class Program { public static void Main() { (string Team, string[] Players)[] worldCup2006Finalists = new[] { ( TeamName: "France", Players: new stri

2020-07-11 21:59:54 3663

原创 C#零碎三

枚举总是具有一个基础类型,可以使除char之外的任意整型

2020-05-31 20:43:19 179

原创 C#静态构造函数

除了静态字段和方法,C#还支持静态构造函数,用于对类(而不是类的实例)进行初始化。静态构造函数不显示调用。相反,“运行时”在首次访问类时自动调用静态构造函数。“首次访问类”可能发生在调用普通构造函数时,也可能发生在访问类的静态方法或字段时。由于静态构造函数不能显示调用,所以不允许任何参数。静态构造函数的作用是将类中的静态数据初始化成特定值,尤其是在无法通过声明时的一次简单赋值来获得初始值的时候。class Employee { static Employee()

2020-05-12 01:21:44 221

原创 属性:取值和赋值方法的访问修饰符

如前所述,好的实践是不要从属性外部访问其字段,否则为属性添加的验证逻辑或其他逻辑可能失去意义。C#2.0允许在属性的实现中为get或set部分指定访问修饰符(但不能为两者都指定),从而覆盖为声明属性指定的访问修饰符。class Program { static void Main() { Employee employee = new Employee(); employee.Initialize(42);

2020-05-09 01:08:06 176

原创 C#零碎 二

在面向对象编程中,封装的作用不仅仅是组合数据和行为,还能隐藏类中的数据和行为的实现细节,使类的内部工作机制不暴露。这减少了调用者对数据进行不恰当修改的几率,同时防止类的使用者根据类的内部实现来编程...

2020-05-08 00:05:21 151

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除