Unity-卡通渲染
效果展示:
原模型:
简单分析卡通渲染又叫非真实渲染(None-Physical Rendering-NPR),一般日漫里的卡通风格有几个特点:
人物有描边
有明显的阴影分界线,没有太平滑的过渡
以下就根据这两点来实现卡渲效果;
描边法线外扩实现描边方式多种,比如卷积区分边界;
这里使用更简单的两个Pass,一个只用纯色画背面,利用法线外扩顶点,根据深度的不同这个纯色的背面会被显示出来,同时又不会遮挡正面;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647Pass{ Tags {"LightMode"="ForwardBase"} //裁剪正面,只画背面 Cull Front CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" ...
Unity-可复用背包工具
Demo展示
设计思路游戏中有非常多的背包样式,比如玩家道具背包,商城,装备栏,技能栏等;每个形式的背包都单独写一份逻辑会非常繁琐,所以需要有一套好用的背包工具;
这些背包有几个共同的特点:
1.有多个排列好的方格子;
2.每个方格子中有内容时,可被拖动且拖动逻辑相同;
3.可添加使用删除格子中的物品;
因此根据这些特点,使用ScrollView等组件,提取两个类,分别负责数据管理和拖动逻辑;
前期准备界面设置制作三个界面,一个滚动背包面板,一个丢弃面板,一个单独物品的预制体;
关键组件:ScrollView,content中添加GridLayoutGroup;
物品配表1.使用Excel配置物品属性表,同时创建字段和excel标签相同的类,用于json序列化;
2.Excel转Json,最简单方式;
之后将转成功的Json内容存到txt文本中,并导入项目;
LitJson库我这里使用的LitJson,一个非常简单轻量的库;https://litjson.net/
直接导入项目或者打包成dll放进项目;
使用时只需要读取Txt文本,转成string,直接调用Api即可,支持数组 ...
Unity-笼中窥梦效果
效果
思路5个面用5个RenderTexture来接受5个摄像机分别获取的小场景图像;
RenderTexture就当成屏幕来理解,MainCamera是把画面显示在屏幕上,屏幕就是最大的RenderTexture且允许里面有子渲染;
把子摄像机拍摄到的画面当成纹理贴图理解,RenderTexture是从子摄像机画面上取样再根据宽高比缩放显示画面;
RenderTexture贴图是不会跟据面与主摄像机位置改变做变化的(其实可以理解为公告牌,这个贴图里的内容一直朝向主摄像机);
要实现上面的效果,在主摄像机空间下,顶点着色器阶段记录裁剪空间下顶点投影到屏幕的坐标,在片元着色器阶段,根据上面记录的屏幕坐标归一化到NDC坐标系(透视除法),再映射根据游戏窗口大小做缩放(屏幕映射),根据这个结果做纹理采样;
Shader123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354Shader "Unlit/WindowsShader" ...
Python转Json升级版
Python转Json升级版
将excel文件夹中所有xslx文件全部转换json文件,存放在data文件夹中;
excel中的格式,从序号为2的行开始,2行为key;1行可以自由写注释;
使用时用双击excel_to_json.py文件即可;
使用条件
1.安装python,配置环境变量;
2.安装excel库openpyxl;
cmd中输入pip install openpyxl执行;
脚本
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051import openpyxlimport jsonimport ioimport os# excel表格转json文件def excel_to_json(excel_file, json_f_name): jd = [] heads = [] book = openpyxl.load_workbook(excel_file) sheet = book[u'Sheet1 ...
Unity-计时器
Demo展示
介绍游戏中有非常多的计时功能,比如:各种cd,以及需要延时调用的方法;
一般实现有一下几种方式:
1.手动计时
12345678910111213float persistTime = 10ffloat startTime = Time.time;if(Time.time - startTime > persistTime){ Debug.Log("计时结束");}float curTime = 0;curTime += Time.deltaTime;if(curTime > persistTime){ Debug.Log("计时结束");}
2.协程
1234567891011private float persistTime = 10f;IEnumerator DelayFunc(){ yield return persistTime; Debug.Log("计时结束");}private void Start() ...
Unity-对象池管理
Unity对象池管理Demo展示
逻辑在游戏中会出现大量重复的物体需要频繁的创建和销毁;比如子弹,敌人,成就列表的格子等;
频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性保持作用的对象我们会使用对象池将其管理起来,用空间换效率;
对象池的要对外提供创建销毁对象的接口,已经添加对象池的接口;
对内要提供创建对象,根据路径查找预制的接口;
整体逻辑如下:
加载/添加对象池添加资源路径,分为Resources文件夹下和SteamingAssets文件下资源;
Resources加载时路径不需要后缀,SteamingAssets需要后缀,根据path路径开头的判断加载方式,同时对路径做处理;
SteamingAssets需要根据平台添加路径头Application.streamingAssetsPath;
Resources需要去掉格式后缀,如.perfab;
这里我测试只使用Resources路径,正式项目自行处理;
存放预创建好的对象:
1private Dictionary<string,List<GameObject>> pool; ...
Win32窗口图标修改
程序图标修改点击解决方案右键添加-资源文件;
添加icon,新建或导入都可;
要求图片必须是.ico格式,甚至可以手绘;
图片大小16x16 ;48x48;64x64;
添加完成后关闭所有选项卡,保存;
这时解决方案里会多一个resource.h的头文件,里面记录了导入的ico的宏定义;
在创建窗口的地方,icon调用Loadicon的Win32Api,记得包含resource的头文件;
鼠标修改鼠标修改同上;直接调用Api;
LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1));
此外还可以直接加载外部文件来修改,文件必须和sin解决方案同级目录;
LoadCursorFromFile("basic.cur");
游戏中鼠标会有动态的修改,比如按下抬起是显示不同的样式,可以通过以下代码修改;
12345678if (GetAsyncKeyState(VK_LBUTTON)){ SetClassLong(m_hWnd, GCL_HCURSOR,(long)LoadCursor(m_hIn ...
Win32鼠标事件
鼠标事件鼠标事件种类分为:
1.左键按下抬起
2.右键按下抬起
3.鼠标移动(坐标)
4.滑轮上下滑动
5.鼠标进入移出客户区
对应的事件代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364class Event{public: enum class Type { LPress, LRelease, RPress, RRelease, WheelUp, WheelDown, Move, Enter, Leave, Invalid };private: Type type; bool leftIsPressed; bool rightIsPressed; int x; int y;public: Event() noexcept : type(Type::Invalid), leftIsPressed(false), ri ...
Win32键盘事件
枚举区分键盘状态:
1.Press,按下
2.Release,松开
3.Invaild,无效
记录按键的char值;
定义键盘事件Event;
使用bites表存所有key的状态,使用bites原因一共键位个数不超过256个,所以足够了;
使用两个队列Queue分别记录键盘事件和char值;
检测到VM_KEYDOWN的系统消息时,调用按下的回调事件,将keystate更改为true,push事件;
检测到VM_KEYUP和VM_CHAR抬起一样;
tips:在窗口不为焦点窗口时需要清空两个队列;
在WindowsProc函数下拦截消息:
1234567891011121314151617181920/*****************键盘消息******************/ case WM_KILLFOCUS: //焦点窗口 kbd.ClearState(); break; case WM_KEYDOWN: //这里由于alt,f系列键位不会被检测,所以添加syskeyDown case WM_SYSKEYDOWN: //按下后是否重复调用事件,autorepeat为 ...
Win32窗口框架
WindowClass单例,负责窗口初始化注册和取消注册;
负责提供静态方法;
放在Window类内部,方便初始化时,wndProc(HandleMsgSetup)的赋值;
1234567891011121314class WindowClass{public: static const char* GetName() noexcept; static HINSTANCE GetInstance() noexcept;private: WindowClass() noexcept; //初始化窗口,创建窗口结构体 ~WindowClass(); WindowClass(const WindowClass&) = delete; //单例,禁用拷贝构造和同类赋值 WindowClass& operator=(const WindowClass&) = delete; static constexpr const char* wndClassName = "Direct3D Engine Window"; static W ...