- 博客(51)
- 收藏
- 关注
原创 Lua踩坑——跨文件调用函数
作为lua的新手,目前遇到的第一个小问题,虽然不是个多么深奥复杂的问题,但是给自己开个头吧——记录每一次试错的过程,作为以后的参考;场景是lua的跨文件调用:文件1:library.lualocal ecsfunction={}function ecsfunction:test() print("我太帅了")end文件2:test.lualocal thisTest=require("library")if not thisTest then print("shit")end
2020-12-11 12:10:24
4393
2
原创 ECS架构笔记
ECS由三个部分构成:Entity:实体、个体。由多个component组成Component:组件、数据。由数据组成System:系统。由逻辑组成Component:component其实是数据,只有变量没有函数(可以有初始化和改变自身量值的函数)。component之间不可以互相通信(都没函数了咋通信)。class Component{int a;float b;double c;char d;}Entity:一个Entity其实像是一个对象,可以代表游戏世界中的任意对象,
2020-12-08 16:52:54
1013
原创 Lua:lua调用C++
接上一篇文章:C++调用Lua本文在上一篇文章的基础上,使用Lua调用C++。使用文章:https://zhuanlan.zhihu.com/p/96848521的方法。本文的Lua版本为5.3.5Lua调用C++具体过程为:1,Lua调用C++中的函数Average2,Average返回结果给Lua#include <stdio.h>#include <string.h>#include <iostream>extern "C"{#inclu
2020-11-29 17:08:59
1159
原创 Lua: C++调用Lua
按照这个链接中的方法做的,具体过程略有不同https://blog.csdn.net/freebazzi/article/details/31419835一、将Lua源码做为静态库导入VS1,新建一个Win32控制台应用程序2,点击下一步,到应用程序设置界面类型选择:静态库附加选项:去掉预编译头点击完成3,添加Lua源码首先打开Lua的源代码压缩包,解压,其中有doc,src,makefile和readme四个文件,src就是source的缩写,打开src。Lua的底层其实是C语言
2020-11-28 16:40:02
408
原创 Lua:实现常见的数据结构
--1,数组--一维数组t={1,2,3,4,5,6}print(t[1])--输出:1--二维数组:t={{1,2,3},{4,5,6},{7,8,9}}print(t[1][1])--输出:1--2,链表t={1,2,3,4,5,6}n=table.getn(t)list=nullfor i=1,n do list={val=t[i],next=list}endprint(list.val,list.next.val,list.next.next.val)--输出:
2020-11-22 22:19:54
228
原创 Lua:元表以及元方法
元表 metatable例如a=10b=20print(a+b)我们可以得到30,但是如果两个table类型相加呢?a={"10"}b={"20"}print(a+b)输出结果是:lua: hello world.lua:3: attempt to perform arithmetic on global 'a' (a table value)stack traceback: hello world.lua:3: in main chunk [C]: ?>Exit co
2020-11-22 22:17:47
125
原创 Lua:变量、赋值、索引以及流程控制
变量lua中的变量全部是全局变量,变量的默认值为nilfunction joke() c=5 --全局变量 local d=6;--局部变量endjoke()print(c,d)--c是5,d是nil------------------------do local a=6; c=6; print(a,c)--6 6endprint(a,c)--6,5赋值1,交换x,y=y,xa[i],a[j]=a[j],a[i] 2,合并变量+空格+..+空格+变量3,返回值a
2020-11-20 17:02:53
324
原创 Lua:八种数据类型
nil空,lua的变量默认为全局变量,如果想消除这个全局变量,就把该变量赋值为nil即可。相当于NULLboolean布尔值,在判断语句中,lua中把false和nil看做假,其他都为真print(type(true))--booleannumber双精度浮点(double),lua中的数字都是该精度print(type(10.4*3))--numberstring用双引号或者单引号表示的字符串,尽量用双引号,与其他语言保持统一string1="This is string1"s
2020-11-19 21:34:08
613
原创 图形学入门:渲染管线总结
首先,什么是渲染管线?渲染管线就是将3D空间中的事物转化为2D平面图(降维打击)。计算机图形渲染管线分为三个大的阶段:一、应用程序阶段二、几何阶段三、光栅化阶段应用阶段(主要由CPU负责)一、剔除剔除总共分为四步:1,距离剔除 (默认不开启,details->LOD)当从近向远拉镜头的时候,会看到有物体突然消失的效果,UE4会自动进行一个检查,看一个物体是否超出了某个距离,如果超过了,那么就不渲染它。在下一帧中,就不会被渲染。它不仅适用于物体,还适用于粒子。2,视锥体剔除(默认
2020-09-21 22:21:10
926
原创 图形学入门:坐标变换
在几何阶段,我们不妨想象这样一个过程:我们在真实世界中,是如何拍照的呢?1,寻找拍摄对象(模型变换)2,摆放相机(相机变换)3,调节相机参数(投影变换)4,拍照(视口变换)->光栅化(下一阶段)首先看一下坐标变换的原理:蓝色坐标系在红色坐标系中的表示:首先由于蓝色坐标系跟红色坐标系的坐标方向是相反的,所以在矩阵中,单位向量的值为负值。模型变换将本地坐标变换为世界坐标:比如我想要将一个模型导入UE4,这个模型本身是有形状的,它各个顶点的相对位置都是固定的,所以有一个本地的坐标。而我
2020-09-21 21:20:28
1318
转载 UE4反射原理(转)
转自:https://blog.csdn.net/mohuak/article/details/81913532https://blog.csdn.net/u012999985/article/details/529020651. UE4反射系统什么是反射系统在UE4里面,你无时无刻都会看到类似UFUNCTION()这样的宏。官方文档告诉你,只要在一个函数的前面加上这个宏,然后在括号里面加上BlueprintCallable就可以在编辑器里面调用了。按照他的指示,我们就能让我们的函数实现各种各样特
2020-09-20 13:41:40
1034
原创 UE4的C++基础:uproperty
凡事在关卡里能看到的大部分都是Actor。Actor的初始化void ULevel::RouteActorInitialize(){ for(int32 Index =0;Index<Actors.Num();++Index){ AActor* const Actor=Actors[Index]; if(Actor&&!Actor->IsActorInitialized()) { Actor->PreInitializeComponents(); } }
2020-09-05 19:49:37
1016
原创 UE4实时渲染:移动端渲染费率
在知乎上偶然看到一篇文章,照着总结一下,以备日后之用。移动端对渲染效率的影响程度排列如下:1,材质数量当材质数量大于16时对帧速率影响较大。2,DrawCall数量想要提高渲染效率,减少DrawCall的数量是最直接有效的方法:具体减少DrawCall的方式有:1,Cull Distance Volume 剔除距离2,Precompute Visibility Volume 计算可视性3,Merge Actors 合并模型3,动态阴影设置动态阴影的地物渲染消耗约为没有设置动态阴影
2020-09-03 16:57:00
415
原创 帧同步进阶
帧同步储备知识点网络协议:TCP或者UDP,一般是采用可靠的UDP。ProtoBuf:谷歌制定的一种数据传输与存储格式:随机数种子:游戏中难免会出现一些产生随机数的场景,但是如果是帧同步的话,就要保证各个客户端生成的随机数是一致的,否则就会出现数据不同的情况。但是要实现这样一个生成随机数的需求,就需要使用随机数种子,而这实际上并不算是真正的随机。帧:帧可以是通常意义上的一个帧,也就是一个图片里的信息,也可以表达是一个短暂的时间片。在帧同步机制中,玩家并不是操作一次就上传一次操作,而是积攒一个事件片
2020-08-25 17:58:31
1418
原创 帧同步与状态同步入门
帧同步和状态同步是游戏客户端和服务器通信的两种方式:适合帧同步的情况:1,网络波动较大,比如移动端网络。2,追求即是反馈,例如FPS、MOBA,SPT(这是啥游戏?)3,控制大量单位,RTS(星际魔兽)简易模型1,状态同步发操作、收状态。客户端上传指令->服务端下发状态->客户端播放状态2,帧同步发操作、收操作操作发送给服务器、服务器转发给客户端、客户端表现。(把所有玩家的操作发给所有玩家,包括发送者自己)控制100个单位移动需要多少数据量?状态同步是定时的发送
2020-08-25 11:48:41
1217
原创 实时渲染入门:静态光照和动态光照
光照也是实时渲染的最重要的部分之一,和反射一样,光照和阴影在实时渲染中的开销也很大,因此一部分计算被分流到预先计算/预算渲染中,而静态光照是指所有预先计算而非实时渲染的光照。静态光照和静态阴影从流程来看:1,静态光照是预先计算的,并将大部分结果存储在光照贴图中。2,性能方面很迅速,但是占用内存3,在预先计算光照时要花费较长的时间4,每当模型发生了变化,就要重新渲染5,模型需要光照贴图UV,这额外的准备步骤也需要消耗时间从质量来看:1,静态光照可以处理辐射和全局光照2,可以获得真实的阴影效
2020-08-18 20:16:58
3458
原创 实时渲染入门:反射
实时反射很难实现,这也许是除了光照以外最难实现的技术。反射总共有三种。反射捕获首先执行的就是反射捕获,同时也是优先级最低的。它就是在一个特定的位置捕获一张静态立方体贴图 。它具有以下特点:1,非常快速2,预先计算3,不太准确4,作用于局部所谓的预先计算,就是打开关卡的一刻重新捕获。效果等同于Play->Update Reflection Captures。如果运行游戏或者应用,它也会在加载时更新。如果打包游戏或者应用,它会将纹理烘焙进游戏,而不再在加载时捕获了。它实际会将捕获的图片
2020-08-18 15:22:24
689
原创 实时渲染入门:(四)纹理、着色器、材质
纹理(Texture)纹理在导入时会被压缩。这个纹理跟视频编码里的纹理是相同的概念,也就是图像的轮廓和边缘,这里老师讲了一些压缩方面的东西,主要是格式相关,比如DXTC1,就没有阿尔法通道,而BC70是质量最高的方式。压缩纹理是因为内存和带宽空间有限,每个着色器的纹理也同样存在上限。多级渐进纹理(Mipmap)一张图片的多级渐进纹理,由许多个由原来图片1/4纹理的图片构成。每个图片都是前者的1/4。比如导入一张图片,原始分辨率为20482048,第一层就是10241024,第二层就是512*51
2020-08-16 21:56:15
951
原创 实时渲染入门:(四)光栅化、遮蔽和G-Buffer
光栅化光栅化就是把3D数据转换为像素的过程。如果要渲染一个三角形,那么我们要知道哪些像素块要被染色。这个过程就是光栅化的过程。而这个过程是在后台进行的,我们无法进行改动。在光栅化中有一个性质,一个像素点永远只会同时用于显示一个多边形。而在光栅化过程中,并不是逐个像素询问的,而是以22大小的矩形进行询问的。过度着色让着色范围超出本应有的区域。比如这里有两个三角形,左侧的三角形犹豫22大小的访问机制,会遍历12个像素块,另一方面,应该着色的部分就会被着色。但是这个时候旁边有一个三角形,在决定要
2020-08-16 19:58:12
3359
1
原创 实时渲染入门:(三)几何结构渲染
在CPU确定了所有对象的位置,并且知道了需要渲染哪些对象之后,渲染就正式开始了。而几何体是第一个被渲染的对象。一,预通道/Early Z Pass(这里的Z是深度)此时我们知道了所有需要被渲染的对象以及对象的位置,但是不知道渲染的顺序,也就是不知道哪些对象应该首先被渲染,哪些对象应该之后被渲染。从宏观上看,渲染的顺序并不是按照像素排列顺序,也不是按照线条渲染,而是逐个对象渲染。按照顺序是:首先渲染背景,接着逐个渲染对象。但是这个时候就会出现一个问题,如果需要被渲染的对象是重叠在一起的,那么被挡住
2020-08-16 16:26:26
754
原创 实时渲染入门:(二)渲染前和遮挡
cpu,gpu不是同时对于同一帧进行处理的,cpu首先处理A帧,然后交给绘制线程,此时cpu去处理B帧,而gpu负责渲染。一开始cpu要计算所有模型的位置,以及变换信息等等,这个过程非常复杂。然后要计算哪些对象或者内容是可见的,这样就可以只渲染可见的部分(因为渲染所有对象太慢了),计算完后会简历两个列表,一个列表存储所有可见的对象,另一个列表存储所有不可见的对象,这个过程大多由CPU完成。这个过程分为四步:1,距离剔除(Distance Culling)2,视锥体剔除(Frustum Culli.
2020-08-16 12:36:29
465
原创 实时渲染入门:(一)概论
在看实时渲染之前,首先可以回顾一下我们在玩游戏当中的概念:FPS与单帧渲染时间提到FPS大家可能会想到枪战,但那个是第一人称射击(First Person Shooting)。在玩网络游戏的时候,屏幕的右上角可能会有fps这个东西,比如LOL。游戏当中的视觉体验,一般与fps成正比,这个fps的全称就是Frames Per Second,即帧率。与之相同的,就是单帧渲染时间,单位是ms,即渲染一帧所需要的毫秒数,该值越低,说明性能越高。我在B站找到的第一个UE4相关的渲染课程,讲的就是实时渲染,里面会
2020-08-14 12:08:23
615
原创 网络编程面试题(二)HTTP相关
从浏览器输入地址到呈现页面中间发生了什么事情(通信过程)1,浏览器(客户端)进行地址解析。浏览器获取到一个字符串,并把它进行补全,成为一个URL。2,将解析出的域名进行dns解析。DNS解析,将域名转换为IP地址。有如下几个步骤:1,先查看浏览器dns缓存中是否有域名对应的ip。2,如果没有,则产看操作系统dns缓存中是否有对应的ip(例如windows的hosts文件)。3,依旧没有就对本地区的dns服务器发起请求,4,如果还是没有,就直接到Root Server域名服务器请求解析。3,
2020-08-12 15:32:24
132
原创 网络编程面试题(一)三握四挥拥塞控制
TCP一,socket与tcp协议栈之间的关联三次握手:1,客户端连接服务器:服务端此时处于listen状态,客户端发送:syn序列号seq12345.2,服务器回应客户端:确认ack和acknum=12346syn和seq-32143,客户端回应服务器ack和acknum=3215acknum:表示这个数字以前的全部确认完成。客户端与服务器在这个过程中总共产生两次交互。第一次交互:服务端侧会形成一个syn队列,队列上会生成一个tcb节点,而这个节点会存在于tcp的整个生命周
2020-08-11 20:17:24
243
原创 UE4进阶:智能指针(一)
首先了解一下UE4中的Uobject,Uobject本身就可以回收和释放,基本上所有的类都继承自Uobject,所以引擎会自动释放。但如果不是继承自Uobject的类,可能就无法释放掉内存,甚至可能出现野指针问题。UE4中的共享指针是TSharedPtr,使用格式为TsharedPtr name;例如这里的一个类,不继承自Uobject,但是是AActor中的一部分。class TaskA{public:int32 a;float b;}class ATaskActor:public AA
2020-08-07 22:05:35
1016
原创 UE4进阶:游戏框架
以一个MMORPG游戏为例,当打开游戏时,服务端会通知客户端加载地图(World)。World容纳了一个游戏里的所有物体,而所有物体都继承自Actor。GameInstance: 优先级最高,在切换关卡的时候,GameInstance中的数据是保留的。GameMode:在联网状态下,GameMode是服务端的角色。它包含了玩家的登陆信息,定义游戏类型,客户端是不能访问GameMode的。GameSession:存在于服务端,拥有T玩家,加入玩家,重新开始,该房间的状态等等。GameStarte
2020-08-07 16:11:32
1349
原创 C++智能指针(二)shared_ptr和weak_ptr
shared_ptr共享指针的最显著特点就是计数器。 shared_ptr<string> p0; cout << p0.use_count() << endl; shared_ptr<string> p1(new string("hello")); cout << p1.use_count() << endl; shared_ptr<string> p2 = p1; cout << p2.use_
2020-08-04 14:57:35
220
原创 C++面试用题(三)move语义、构造函数、深浅拷贝、右值引用
移动语义C++11的特性:move语义,一些对象构造的时候可以获取到已有的资源,而不需要通过拷贝来申请新的内存,这样移动而非拷贝将会大幅度提升性能。首先看一个简单的例子: string str = "fuck"; vector<string> v; v.push_back(str); cout << v[0] << endl; cout << str << endl; //这里使用move v.push_back(move(str
2020-08-03 21:12:56
779
原创 C++智能指针(一)
unique_ptrunique_ptr管理一个指针对象,并负责它的生命周期。当它被销毁时,其析构函数会删除关联的原始指针。string* str = new string("hello world"); cout << *str << endl; unique_ptr<string> pointer(new string("hello world")); cout << *pointer << endl; system("pause"
2020-08-03 10:37:44
138
原创 C++设计模式:对象创建模式——工厂方法
对象创建通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。工厂机制:通过虚函数创建一个多态的new。设计原则:避免抽象类依赖具体类。class SplitterFactory {public: ISplitter* CreateSplitter() { return new BinarySplitter; }};class ISplitter {public: virtual void
2020-08-01 15:45:34
127
原创 C++设计模式:单一职责划分—修饰模式
在写一个面向对象的程序时,如果程序要扩展功能,使用继承的方法,会导致代码量急剧膨胀。例如:下面的例子就是写一个文件分割器,基类是stream类,而流可能是文件、网络、内存的流,然后在文件、网络、内存的流中,对于基类中的三个纯虚函数进行重写。每扩展一个功能,就要写针对FileStream,NetworkStream,MemoryStream这三个主体类中的所有功能函数进行编写。class stream{public: virtual char Read(int number)= 0; virtua
2020-08-01 12:31:13
176
原创 C++面试用题(二)const和Lambda表达式
constconst在C++中用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。一、修饰普通类型变量const int a =7;int b=a;a=8;//不被允许最后a仍然是8,在加上了const关键字后,a就被编译器认为是一个常量,不允许修改。如果非要改,可以在const前面再加上Volatile关键字。 volatile const int a = 9; int *p = (int*)&a; *p = 8; cout << a <<
2020-07-30 21:18:08
1940
原创 虚幻四基础:组件
SceneComponent场景组件,组件有变量和变换:变换包含了缩放和旋转。点击Add Component,新建蓝图脚本组件(英语忘记了)然后会出现这个框,可以通过勾选“显示所有类”找到SceneComponent。然后会提示把该组件放在哪里。这样就创建了一个组件。Audio就是音频组件,可以对声音进行控制,甚至可以设置衰减半径,使一个音源具有衰减特性。ParticleSystem:放粒子系统的。比如在蓝图中创建一个粒子然后可以在Particles的右侧,有一个Template中
2020-07-28 21:26:59
1077
原创 虚幻四基础:蓝图之间的通信
太久没写了,中间去了趟成都找女朋友玩,罪过罪过。首先创建一个Actor控件,也就是默认的带有三维坐标的白色小球,可以设置形状。然后将这个控件拖入到关卡蓝图里。比如要实现一个打印当前类名字的功能:Custom Event:自定义一个函数:连接到Print String。然后Get Display Name获取当前类的名字,连接到Get Class获取Self自己的类。然后连到Event BeginPlay。就可以实现这样的功能。然而这个功能并不是从外部调用的,而是内部实现的。所以要尝试从蓝图通信,
2020-07-28 14:59:05
1084
原创 C++面试用题(一)
堆和栈的区别:(注意不是数据结构里的堆和栈)栈(stack)由编译器自动分配释放,存放函数的参数值,局部变量的值。堆(heap)由程序员分配释放,如果不释放,最后程序结束时会被操作系统回收。全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在同一区域,未初始化的全局变量和未初始化的静态变量在相邻的另一区域。int a;//系统在栈中为b开辟空间int* a=new int;//程序员在堆中申请空间存放aa=(int*)malloc(sizeof(i
2020-07-22 15:16:12
111
原创 虚幻4基础:UMG控件(一)
Removed from Focus Path判断当前的要对哪个控件进行操作。点击一个Button,然后鼠标离开,就会触发该事件。也就是监听用户对一个可交互的控件进行的访问。Added to Focus Path这个就和上面的相对应。On Preview Mouse Button Down当鼠标敲击控件的时候,可以获取到该控件的坐标。点击右上方的Designer,放置两个按钮,一个image,一个button。运行,这个时候按钮会出现在屏幕上面。然后点击按钮,就会触发这个事件。另一方面
2020-07-19 21:38:30
2689
原创 虚幻4基础:GameMode接口
位置打开GameMode实例的生成(Spawn Default Pawn)Functions—>Override—>Spawn Default Pawn For:生成一个Pawn。如果本身没有人物,没有调用这个函数,则会默认生成一个人物,但是如果调用了这个函数,则不会默认地生成实例。Spawn Default Pawn For:通过Controller获取一个默认的Pawn Class,但是Get Default Pawn Class for Controller默认返回的是一个
2020-07-19 14:44:25
1769
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人