UE4
ue4、5常用的类有哪些
1、 UObject :这个就是UE的所有类的基类。
2、 Actor :可以放置或再生在关卡中的UObject类。
3、 Pawn : Pawn类继承自Actor类,它代表了游戏中可由玩家或AI控制的角色。在UE5中,Pawn类封装了与移动、碰撞和输入等相关的功能。游戏中的主角和敌人通常都是Pawn类的子类,通过控制Pawn的移动和动作,玩家可以与游戏世界进行互动。
4、 Character :Character类是Pawn类的子类,专门用于表示游戏中的角色。与普通的Pawn类相比,Character类提供了更多关于动画、碰撞体积和角色属性等的功能。它是制作角色类的首选,常用于创建主角和NPC等角色。
5、 GameMode类:GameMode类定义了游戏的规则和玩法。每个关卡都需要指定一个GameMode类,它决定了游戏的开始、结束条件以及其他特定的规则。开发者可以通过自定义GameMode类来实现独特的游戏玩法和定制规则。
6、GameState类:GameState类用于存储与游戏状态相关的信息,例如玩家分数、时间等。它在服务器和客户端之间同步游戏状态,确保多人游戏中所有玩家都能看到相同的游戏状态。
7、PlayerController类 :PlayerController类管理玩家在游戏中的输入和控制。它负责处理玩家的按键输入、鼠标移动等操作,并将其转换为游戏中的具体动作。每个玩家都有一个对应的PlayerController实例
8、HUD类 : HUD类用于在屏幕上显示游戏中的信息,如玩家的血量、道具栏、任务目标等。开发者可以通过HUD类自定义游戏UI,并将游戏信息直观地展示给玩家
9、UMG Widget类:UMG Widget类是用于创建用户界面的类。它提供了一个可视化的UI编辑器,允许开发者通过拖拽和放置来设计游戏中的UI元素,如按钮、文本、图像等。UMG Widget类使得创建美观、交互式的用户界面变得更加简单。
说一下drawcall
在计算机图形学中,DrawCall是指将图形数据发送给GPU进行绘制的过程。在UE中,一个DrawCall通常对应着一次绘制调用,它包含了要绘制的物体的所有渲染指令。大量的DrawCall会导致CPU频繁地向GPU发送绘制命令,从而降低游戏性能。
UE中的DrawCall计算通常通过几个主要因素进行估算。首先是可见物体的数量。如果屏幕上要绘制的物体数量很大,那么DrawCall的数量也会相应增加。因此,优化场景中的物体数量,使用空间分割技术(如视锥体剔除)来排除不可见物体,是提高性能的有效方法。
其次,每个物体的材质数量和复杂度也会影响DrawCall。使用不同材质的物体需要多次DrawCall来绘制,因此减少物体的材质数量和使用简化的材质将有助于减少DrawCall的数量。
此外,物体的几何复杂度也是影响DrawCall的重要因素。高面数的物体会导致更多的DrawCall,因此对于性能优化,我们需要注意场景中的物体细节和模型优化,如使用LOD(Level of Detail)技术来降低远处物体的面数,减少DrawCall的数量。
对于大型开放世界游戏,玩家的视野范围可能非常广阔,这会导致更多的DrawCall。因此,优化开放世界游戏的一个关键技术是使用流加载技术,只加载玩家视野范围内的资源和物体,以减少DrawCall和加快游戏加载速度。
说一下多播单播事件委托
C++
面向对象的3个特性
1、封装:将类的的一些成员变量或者方法藏起来,不允许外界直接操作,类内部向外提供接口
2、继承:子类继承父类的一些方法属性,根据继承方式的不同会继承不同的作用域的属性方法,只允许降级继承,允许同名方法,想调用父类的同名方法时候,可以通过父类的命名空间去调用
3、多态:重写虚函数,用指向子类对象的父类指针去调用该方法。
什么是多态
多态是不同继承关系的类对象去调用同一函数产生了不同行为,被调用的函数是虚函数,而且派生类重写过虚函数
什么是虚函数
函数前面加virtual的是虚函数,虚函数可以被子类重写
还有个纯虚函数,纯虚函数是指该函数是没有实现具体方法,完全交给派生类去实现,这个时候,那个类为抽象类,不能实例化。
讲述一下哈希
将无限长的字符转化成有限长的或者固定的数字,这是个不可逆的过程。
通常我们用来检查密码检查、文件对比、数据检索之类的功能。
简单实现的话大概就是把字符通过一些算法转成对应的哈希表里面的key值,如果有冲突的话,有两种比较简单的方法去解决它,一种是封闭寻址法,有冲突的时候,通过一个链表去插入数据,不过这种查找效率有点低;另外一种是开放寻址法,如果下个位置有空位直接插进去
当然一般我们业务上很少需要自己去写哈希算法,我们都会有成型的哈希算法,常用的有MD5跟sha。md5是128bits,sha有256跟512bits。具体用哪个就看业务需求了。
二叉树
二叉树是一种数据结构,比较常用的有平衡树、红黑树
在说二叉树之前,得说一下列表(有序数组)跟链表的优缺点,
列表因为有下标,所以查询速度会比较快,但是插入删除的时候,需要把插入的数据后面的数据都往后移动,这性能消耗还是相对比较高的。
链表的话,就反过来了,插入的时候,直接改链接的指针就好了,但是查询的时候,就需要遍历整个链表。这效率也比较慢。
这时候就有二叉树了,可以实现快速的查找,也可以快速的删除,查找。这是有序数组和链表不能比的。
它是由节点和边构成的,每个节点最多有两个子节点。根节点没有父节点,每个叶子节点都没有子节点。
常用的遍历方式有前序遍历、中序遍历和后序遍历。
前是根左右顺序、中是左根右、后是左右根顺序。
设计模式
就是前人总结出来的对于特定问题的解决方案
比较常用的设计模式有单例、观察者、工厂、代理、装饰等等。
设计模式有6大原则:单一职责(一个类只负责一项职责)、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则
单例:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,有好几种方式,饿汉、懒汉。
饿汉式单例模式就是在类加载的时候就立即初始化,并且创建单例对象。不管你有没有用到,都先建好了再说。它绝对线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。线程安全,没有加任何锁、执行效率比较高。类加载的时候就初始化,不管后期用不用都占着空间,浪费了内存。
懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则直接返回,没有则新建。在多线程的时候,为了兼顾性能和线程安全问题,我们可以通过双重检查锁的方式来创建懒汉式的单例。
观察者:拥有一些值得关注的状态的对象通常被称为目标, 由于它要将自身的状态改变通知给其他对象, 我们也将其称为发布者 (publisher)。 所有希望关注发布者状态变化的其他对象被称为订阅者 (subscribers)。
工厂:通过工厂类(工具类)去生产产品类。有分3种模式,简单工厂、工厂方法、抽象工厂。
简单工厂模式(Simple Factory Pattern): 是指定义一个工厂类,工厂类中实现一个方法,此方法根据不同的参数返回不同的类。当要创建的实例过多时,会存在过多的if语句,当要创建新的实例时要修改工厂方法,这样做违背了开-闭原则
工厂方法模式(Factory Method Pattern): 是在简单工厂模式的基础上将工厂类修改为抽象类,具体的类实例创建交给抽象工厂的子类。工厂方法模式很好的避免了过多的if语句,同时也保证了开-闭原则,但是当类过多时会产生类"爆炸"的情况
抽象工厂与工厂方法相比,抽象工厂允许生成不同的产品(即一个工厂存在多个产品)
动态规划算法
基本思想也是将待求解问题分解成若干个子问题,经分解得到的子问题往往不是互相独立的,有些子问题被重复计算多次 ,如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算
快速排序
快速排序算法是对冒泡排序算法的一种改进算法,在当前所有内部排序算法中,快速排序算法被认为是最好的排序算法之一。
快速排序的基本思想: 通过一趟排序将待排序的序列分割为左右两个子序列,左边的子序列中所有数据都比右边子序列中的数据小,然后对左右两个子序列继续进行排序,直到整个序列有序。
因为会有指针指向的数据置空的时候,所以容易被其他数据插进去,不稳定的。