解密ControlRotation与ActorRotation

在实现角色移动时,我们是通过获取当前角色向前或者向后移动的向量来计算具体的移动步长,进而增量设置角色位置以达到使角色移动的目的。但是获取向前或者向后的向量得先知道当前角色在世界坐标系中旋转的角度,于是我们就在ControlRotation和ActorRotation之间犹豫不定,对二者异同不甚了解,分别表达的意图也懵懵懂懂,似乎对于初学者总隔着一层面纱,今天我就帮大家揭开它。

有个大前提:只讨论第一人称

首先概念上讲,ControlRotation作为控制器的成员变量,在这里是表示人眼睛朝向,ActorRotation表示人身躯的朝向。

如下示意图,会更明确:


rotation示意图

我们可以从常识上理解,人的眼睛在脑袋上,脑袋是可以左右摆头(Yaw角度变化),可以上下点头(Pitch角度变化),而人的身躯只能左右转动(Yaw角度变化),身躯不能僵直地俯仰,这在第一人称射击游戏里面不会出现。(反正我没有见过,你如果见过请告知我)

我们可以通过代码进一步佐证:


获取眼睛位置和朝向

朝向获取

ControlRotation和ActorRotation的关系

它们两者的关系,其实主要是理清楚它们分别是怎样更新的或者其中一个值的更新怎样影响到另一个值的变化。

1、ControlRotation的更新

我们在开发第一人称射击游戏时,通过鼠标的上下左右移动以控制枪的瞄准方向也就是眼睛的朝向,会利用到如下代理绑定:



ControlRotation的更新代理

随着鼠标移动会使眼睛也保持移动,那么具体ControlRotation怎样被更新的呢?那么我们通过UE4底层代码进一步探究,如下图:


ControlRotation更新算法

我们先看到我标注的关注1,在此ViewRotation就是ControlRotation,它会在PlayerCameraManager的ProcessViewRotation函数里面被更新,更新的变换值是DeltaRot,这个值是角度的增量变化值。更新好了后,通过SetControlRotation更新ControlRotation值,那么再看ProcessViewRotation函数具体的实现,如下图:


ControlRotation增量角度更新

如上图的注释说明,最终值是通过引用做返回,而值的增量更新就是加上了DeltaRot。不过,我们前面就说了ControlRotation实际上就是眼睛的朝向,眼睛朝向按实际情况角度是有限制的,比如向上仰头肯定不能超过90度,否则头就断了(很恐怖的情景)。具体限制的值如下图:


眼睛各角度限制值

由此我们终于弄明白了ControlRotation具体更新的过程,实际上就是把增量变化的角度值增加到其上即可,增量变化的角度值与鼠标的位置变化成线性关系。

2、ActorRotation的更新

那ActorRotation是怎样被更新的,我们回过头来看《ControlRotation更新算法》图中的关注2,当更新完了ControlRotation后,会利用它作为参数传递到了FaceRotation函数中,那就看一下FaceRotation函数做了什么,如下图:


ActorRotation更新

我们看到它其实会根据bUseControllerRotaionPictch,bUseControllerRotaionYaw和bUseControllerRotaionRoll开关,分别判断是否使用ControlRotation的分量角度,最后会通过SetActorRotation函数设置ActorRotation的值,这里也恰好解释了我们经常在编辑器里面设置的几个开关,如下图:


开关设置

对于射击游戏,我们设置让ControlRotation的Yaw值去更新ActorRotation的Yaw值,也就是说眼睛的左右转向控制角色身躯的左右转向。

至此,所有谜底我们都已经解开,我们给出一个结论:

在第一人称射击游戏中,ControlRotation表示的是角色眼睛的朝向,为了符合现实中的效果,分别对眼睛在Pitch、Yaw、Roll三个转向上做了限制,ActorRotation表示的是角色身躯的朝向,根据用户配置,它的Yaw是更新自ControlRotatioin的Yaw值。

不知道大家有没有一种包公破案的感觉,当然这里要简单很多,实际在工作中我们碰到的问题也比这要复杂,但是其实解决问题的思路方法一致。

好,大家如果有兴趣结合案例去综合实践,可以跟着UE4-VR高级课程 虚幻引擎多人在线射击游戏C++开发实战(第一季)第六节课《人物前后移动》来做。

欢迎大家加入我们的qq群,跟业内人士共同探讨交流。

qm.qq.com/cgi-bin/qm/qr? (二维码自动识别)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432481.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

llinux下kvm虚拟化

原理就是本来可能要10台物理机完成的事现在只要5台,分别在每台物理机上虚拟一台,这5太虚拟机共享一个stronge,比如有一台物理机down掉后或是要做维护,我们可以把它上面的虚拟机牵走,从而减少损失或防止终端业务&#x…

系统会自带java吗_使用eclipse自带制作帮助系统

①help的api的生成1:项目中的生成javadoc或右击项目的导出,成javadoc格式。2:找打jdk中的Javadoc位置。如果忘记可以同cmd窗口通过指令寻找jdk位置,还可以直接再我的电脑中搜索javadoc。查找Javadoc.exe路径位置,填入j…

UE4 左右立体参数

在编辑器的editor preferences里设置下面参数

java arraylist范围_Java常见集合之ArrayList深入分析

1 /*2 继承自AbstractList,实现了List、RandomAccess、Cloneable、Serializable接口3 1)RandomAccess接口:用来快速随机存取,在实现了该接口后,用普通for来遍历,性能更高4 2)Cloneable接口:实现了该接口&am…

UE4 多个static mesh合并成一个static mesh

第一种方法: 1. 把需要合并的所有的static mesh导入到一个level中,static mesh导入到level中后,会自动变成static mesh actor 2. 在level的world outliner面板把选中需要合并的所有的static mesh actor 3. 鼠标右键,在弹出的快…

在UE中自由绘制基本图元的几种方法

1. 在UMG中可以使用UWidgetBlueprintLibrary类来绘制,UWidgetBlueprintLibrary类提供了一系列的静态函数可以使用。但只提供了DrawLine,DrawLines,DrawBox,DrawText,DrawTextFormatted函数,如果要自己绘制的…

java work set没有显示出来_eclipse里新建work set,将项目分组放在不同文件夹

想必大家的Eclipse里也会有这么多得工程......每次工作使用到的项目肯定不会太多......每次从这么大数量的工程当中找到自己要使用的,必须大规模的滚动滚动条......有点不和谐了.无意当中看到了working set自己创建了一个 workingset 并将相应的 projects 添加到 working set 当…

指针的一些问题

1、c/c语言中不少地方,数组和指针可以相互替换使用,容易让人产生一种错觉,指针和数组是等价的。 数组要么在静态存储区域创建,如全局数组;要么在栈上创建如函数内的数组。数组的名称对应着(而不是指向&…

java连接imserver_java后端IM消息推送服务开发——协议

最近在一家saas企业使用Mqtt开发IM消息推送服务,把开发中的一些问题记录下来,项目仍在商用中,完整的消息服务包括4个模块---协议protocol,信令Signal,规则Rule,状态Status,这个主题主要是协议pr…

好多邮箱的SMTP设置

http://731771490.diandian.com/post/2011-04-20/19576550转载于:https://www.cnblogs.com/mantian/p/3828837.html

新手向:如何理解OpenGL中着色器,渲染管线,光栅化等概念

首先,光栅化(Rasterize/rasteriztion)。 这个词儿Adobe官方翻译成栅格化或者像素化。没错,就是把矢量图形转化成像素点儿的过程。我们屏幕上显示的画面都是由像素组成,而三维物体都是点线面构成的。要让点线面&#xf…

tankwar的java坦克子弹撞墙_tankwar

tankwar 是使用java开发的一个单机版的小游戏 (未使用任何游戏引擎).和90经典版的坦克大战有些不同, 这里是纯坦克之间的战争, 英雄坦克并不用保护它的家.特色:1. 游戏共设6个关卡. (支持无限关卡)关卡设置中包括敌人坦克数量, 移动速度, 子弹速度, 以及子弹的杀伤力, 炸弹数量…

材质加载

UMaterial* Material LoadObject<UMaterial>(NULL, TEXT("/Game/VertexColorMaterial"), NULL, LOAD_None, NULL);

java如何添加进程_如何创建一个进程,如何进程调用进程

java一般用线程就够了&#xff0c;多进程优势在于每个进程互不干扰&#xff0c;劣势在于太耗费内存&#xff0c;任何事情都不是绝对的&#xff0c;在编写Java程序时&#xff0c;有时候需要在Java程序中执行另外一个程序。1、启动程序Java提供了两种方法用来启动其它程序&#x…

输入学生成绩,并按升序排列 Ascending.java

import java.util.Arrays;import java.util.Scanner;public class Ascending{ public static void main(String[] args){ Scanner innew Scanner(System.in); int[] arrnew int[10]; for(int i0;i<arr.length;i){ System.out.println("请输入第"(i1)"个学生的…

java判断ftp创建目录是否成功_Java判断Ftp服务器目录是否存在,若不存在创建目录 ....

解决方法1&#xff1a;package com.soft4j.log4j;import java.io.IOException;import sun.net.ftp.FtpClient;public class FtpTest{static String middle_ftpServer "10.103.2.250";static String middle_user "ora9iftp";static String middle_passwor…

第三方静态库的使用

1. 工程根目录下创建文件夹“ThirdParty”&#xff0c;然后在此文件夹下创建“includes”和“libs”文件夹 2. 拷贝静态库的头文件和库文件到上面的文件夹下 3. 修改工程的build.cs文件&#xff0c;增加下面代码1&#xff09;在类中private string ThirdPartyPath { …

UITableView:改变 TableHeaderView 的高度

参考&#xff1a;http://stackoverflow.com/a/526825 有这么一种需求&#xff0c;在列表顶端显示一些别样的数据&#xff0c;而这个别样的数据则需要通过一个别样的 View 来展现&#xff0c;它便是 UITableView 的 tableHeaderView。 倘若 tableHeaderView 里的内容很固定&…

perl 远程 mysql_写的一个perl脚本,用于发送远程MySQL命令 -电脑资料

想写一些简化管理操作的脚本&#xff0c;下面是基础脚本之一&#xff0c;对于一个从来没使用过perl脚本的我来说还是有些难度的&#xff0c;直接上代码。此脚本用于发送远程MySQL命令并且接收结果&#xff0c;功能比较简单&#xff0c;后面会渐渐完善。#!/usr/bin/perl use Get…