| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 斯坦福UE4 + C++课程学习记录 18:十字准星 -> 正文阅读 |
|
[游戏开发]斯坦福UE4 + C++课程学习记录 18:十字准星 |
目录 1. 创建准星UI????????结合之前文章关于UMG的内容,我们可以十分快速地创建一个之子准星的UI,这一部分视频对应课程P20开始。 ? ? ? ? 首先,我们需要调整一下摄像机的位置。如果我们现在运行关卡,会发现游戏角色位于镜头的正中间,这无疑会在操作中遮挡玩家的实现。回忆一下各种第三人称视角的游戏,人物通常位于画面的偏左或偏右的位置。 ????????进入Player的蓝图编辑器,选择弹簧臂组件(SpringArmComp),调整其中的“摄像机”属性。通过设置“长度”可以变化摄像机与角色的距离,设置“插槽偏移”从而在改变相机位置时保持弹簧地碰撞检测的功能。这里大家可以根据自己的喜好自行调节视角,我在这个地方的设置如图18-1: ? ? ? ? 接下来,在UI文件夹下创建Crosshair_Widget控件蓝图,并添加一个图像控件。通常,十字准星固定在屏幕的正中央。因此,我们设置图像的锚点为屏幕中间点,设置位置X、Y为0,并把X与Y的对齐均设置为0.5。适当调节尺寸X、Y属性,使准星的大小合适。 ????????回到Player蓝图中,在之前添加血量条的位置再把准星加上,同样添加到视口。然后运行关卡,就可以看到屏幕正中间有一个简单的准星了。 ?2. 调整发射代码????????在此前第5节的文章中,我在SurCharacter中的PrimaryAttack使用了GetActorRotation函数来获取角色的旋转,从而使粒子以角色的正前方发射,如图18-5: ????????在添加十字准星后,我们肯定需要粒子沿着准星发射,即沿着玩家的视角发射。所以,我们只用把PrimaryAttack_TimeElapsed函数中的GetActorRotation()换成GetControlRotation()即可。此外,在当前项目下,我使用UE_LOG发现GetControlRotation()和GetViewRotation()的值相等,所以后面就统一用前者。 ????????但这样的更改可能会带来两个问题:一是反方向(正脸面向摄像头)发射时可能会打中角色自己,这取决于魔法粒子蓝图的设置;二是击中的位置与准星还是存在偏差,尤其在角色朝向左边的时候(角色右手发射): ????????第一个问题很容易理解,反方向发射的魔法粒子检测到了自己角色的actor,就触发了OnActorOverlap事件。在此前第11节的内容中,我们已经使用了Instigator判断是不是玩家自己,所以第一个问题我并没有遇到。 ????????但此处还要注意,粒子虽然可以穿过角色,但仍会对角色自己造成伤害。我们控制粒子销毁的功能是在蓝图中实现的,而控制伤害的功能是在代码中实现的(有点混乱,但这是课程出于教学目的的设计),所以我们还需要再C++中添加忽略对玩家造成伤害的代码。代码如下所示,其实就是在之前的基础上在第一个if处添加了对Instigator的判断,和蓝图中的逻辑是一样的。
????????第二个问题就稍微复杂一些,我个人是这样理解的:粒子发射的方向是角色的相机方向,而粒子发射的位置是角色右手。也就是说,只要发射位置不在屏幕正中心(也就是相机的位置),最后粒子的落点一定存在偏移,且距离屏幕中间越远偏移越大。 ? ? ? ? 一种最简单的解决办法是,直接设置魔法粒子的发射点在屏幕正中间,也就是相机位置。这个方法只修改需要一行代码,也就是把相机的Rotation和Location都赋给SpawnTM:
????????这种方法的效果如图18-9,毫无疑问实现了指哪打哪。如果要使用这个方法,也许在每次攻击时把角色旋转到朝前,然后要精调角色在镜头中的位置,以及魔法粒子沿着GetControlRotation这个方向的具体生成位置,使其攻击时手部刚好和发射粒子的位置重合,感觉第一人称射击游戏可以更方便地使用这种方法(以上都是个人猜想)。 ? ? ? ? 另一种很巧妙的方法,是先检测再发射。在发射魔法粒子前,先用射线检测的方法,检测一个从相机位置沿着其朝向的较大的射程范围内,有没有命中对象。如果检测到命中,返回命中的位置,并利用向量加法得到这次攻击的方向向量,然后再发射魔法粒子;如果不命中,最后就会落到沿着相机,距离为射程的那个点上。这种方法每次攻击的方向向量是不相同的,是判定完位置后再计算的。 ????????实现方法和之前第7节打开箱子的射线检测很类似,这里使用形状检测来增加检测的空间,核心代码如下:
????????原理已经十分清晰明了,但我使用如上代码在运行时并没有达到预期的效果。在我添加了DrawDebugLine和DrawDebugPoint进行调试后,终于发现问题的原因:预先检测时直接略过了预期对象,根据UE_LOG打印的内容显示,最后传回的Actor是地板Floor,如图18-10中黄球所示: ? ? ? ? 于是我顺着这个问题,对碰撞和物理属性的各种设置折腾了许久,最后终于发现把对象的碰撞预设设置为“BlockAll”后,代码就可以正常运行了。但这样的缺点在于,这些物体即使设置了“模拟物理”也不会和场景内的火药桶产生交互,火药桶爆炸后它们还死死地钉在原地。 ????????接下来我只能从函数上入手,我看到UE对SweepSingleByObjectType的解释是发射一个形状,会返回第一个碰撞的对象。一看到碰撞这个字眼,我就突然意识到ObjParams里面传入了需要检测的对象,兴许是我场景中的对象不属于代码中的三种。我在UE中检查这面墙的对象类型,发现是PhysicsBody,于是我尝试性地在代码中加入了ECC_PhysicsBody。最后,终于在物体能模拟物理的基础上,被SweepSingleByObjectType检测到。最终效果如图18-11所示,其中黄色是形状检测的点,紫色是粒子触发命中事件的点。 ????????看来根本的问题还是在UE的碰撞设置上,目前有关各种碰撞预设设置、命中事件、重叠事件等一些列问题理解还十分粗浅。所以暂且留个坑,待日后对UE有一定概念后再回头来系统研究这个问题。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/17 6:07:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |