0%

UE编辑器偏好设置-源码中没有rider选项

环境 window,引擎版本4.27

解决方法:

将 Rider 启动文件的绝对路径写入到 RiderLocations.txt ,该文件在 /UE4安装目录/Engine/Plugins/Developer/RiderSourceCodeAccess/Resources/RiderLocations.txt

1
2
3
4
5
6
7
8
9
# Add absolute path to the Rider's binary file. Example:
# Windows:
# C:\\Program Files\\Toolbox\\Tools\\apps\\Rider For Unreal Engine\\ch-0\\211.7442.67\\bin\rider64.exe
# MacOS:
# /Users/alexander.pirogov/Library/Application Support/JetBrains/Toolbox/apps/Rider For Unreal Engine/ch-0/212.4488.6/Rider.app
# Linux:
# /home/user/.local/share/JetBrains/Toolbox/apps/Rider/ch-0/211.7442.29/bin/rider.sh

F:\JetBrains Rider 2022.2.4\bin\rider64.exe

重启项目

FString ,FName,FText转换

FString ,FName,FText转换

From to
FName FString TestHUDString = TestHUDName.ToString();
FName FText TestHUDText = FText::FromName(TestHUDName);
FName -> FText 在一些情况下有效,但需注意 — FNames 内容不会从 FText 的”自动本地化”中受益。
FString FName TestHUDName = FName(*TestHUDString);
FString -> FName 不可靠。因为 FName 不区分大小写,所以转换存在损耗。
FString FText TestHUDText = FText::FromString(TestHUDString);
FString -> FText 在一些情况下有效,但需注意 — FString 内容不会从 FText 的”自动本地化”中受益。
FText FString TestHUDString = TestHUDText.ToString();
FText -> FString 不可靠。它在一些语言的转换中存在潜在损耗
FText FName FText 到 FName 的转换不存在。但可先转换到 FString,再转换到 FName。
FText -> FString -> FName 不可靠。因为 FName 不区分大小写,所以转换存在损耗。
FString int32 int32 TestInt = FCString::Atoi(*MyFString);
FString float float TestFloat = FCString::Atof(*MyFString);
int32 FString FString TestString = FString::FromInt(MyInt);
float FString FString TestString = FString::SanitizeFloat(MyFloat);
1
2
3
4
5
6
7
8
9
10
11
FName name = FName("this is a name");
FText::FromName(name);
name.ToString();

FString str = FString("this is a string");
FName name2 = FName(*str);
FText::FromString(str);

FText text = FText::FromString("this is a text");
text.ToString();
FName(*text.ToString());

总体而言,设置字符串变量文字时应使用 TEXT() 宏。如未指定 TEXT() 宏,将使用 ANSI 对文字进行编码,会导致支持字符高度受限。 传入 FString 的 ANSI 文字需要完成到 TCHAR 的转换(本地万国码编码),以便更高效地使用 TEXT()。

虚幻引擎中的字符串处理 | 虚幻引擎 5.4 文档 | Epic Developer Community

帧同步和网络同步

定义

  • 帧同步:通过同步每一帧的操作指令,确保所有客户端在每一帧上执行相同的操作,从而保持游戏画面和逻辑的一致性。
  • 状态同步:通过服务器周期性地将游戏或系统的状态信息发送给所有客户端,以确保每个客户端上的游戏或系统状态保持一致。

工作原理

  • 帧同步
    1. 客户端在每一帧收集玩家操作并发送给服务器。
    2. 服务器汇总所有客户端的操作并广播给所有客户端。
    3. 客户端在同一帧上执行相同的输入操作。
  • 状态同步
    1. 客户端将操作发送到服务器。
    2. 服务器计算游戏行为的结果,并将结果广播给所有客户端。
    3. 客户端根据服务器发送的状态信息更新本地状态。

优缺点

  • 帧同步
    • 优点:延迟低,适合对实时性要求高的游戏;数据传输量小,服务器压力小;容易实现回放和观战功能。
    • 缺点:实现复杂,对网络延迟敏感;任何客户端的延迟或掉线都会影响整个游戏的同步。
  • 状态同步
    • 优点:安全性高,反外挂能力强;对网络延迟的适应性较高;适合复杂逻辑和物理交互的游戏。
    • 缺点:数据传输量大,可能导致带宽消耗高;延迟较大,响应速度慢。

区别

  1. 核心逻辑位置
    • 帧同步的战斗逻辑在客户端,状态同步的战斗逻辑在服务器。
  2. 数据传输量
    • 帧同步传输的是操作指令,数据量小;状态同步传输的是游戏状态,数据量大。
  3. 延迟适应性
    • 帧同步要求低延迟,状态同步对延迟的适应性更强。
  4. 安全性
    • 状态同步的安全性更高,因为所有逻辑都在服务器处理,帧同步更容易被篡改。
  5. 适用场景
    • 帧同步适用于动作快速、精确度要求高的游戏(如格斗游戏、MOBA游戏);状态同步适用于对复杂逻辑和物理交互要求高的游戏(如RPG、回合制游戏)

题目:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

1
2
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

1
2
输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

1
2
输入:nums = [1]
输出:[[1]]

代码:

1
2
3
4
5
6
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {

}
};

题目:

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 abc 使得 a + b + c = 0 ?请找出所有和为 0不重复 的三元组。

示例 1:

1
2
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

1
2
输入:nums = []
输出:[]

示例 3:

1
2
输入:nums = [0]
输出:[]

代码:

1
2
3
4
5
6
7
//退化为排序后的双数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {

}
};

题目:

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

1
2
3
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

1
2
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

示例 3:

1
2
输入:nums = [1,0,1,2]
输出:3

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> num_set;
//去重,set集合元素唯一
for (const int& num : nums) {
num_set.insert(num);
}

int maxLength = 0;
int curNum = 0;
int curLength = 0;
for(const int& num:num_set)
{
//判断是否是开头的数字
// 100 99 5 7 6 2 1 (这里只有在遍历到99,5,1的时候才会进来)
if(!num_set.count(num-1))
{
curNum = num;
curLength = 1;
//找到最长的连续集合
while(num_set.count(++curNum))
{
curLength++;
}
maxLength = max(maxLength,curLength);
}
}
return maxLength;
}
};

考察的是对set集合的运用

题目:

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> mp;
for (string& str: strs) {
string key = str;
sort(key.begin(), key.end());
mp[key].emplace_back(str);
}
vector<vector<string>> resultArr;
for (auto it = mp.begin(); it != mp.end(); ++it) {
resultArr.emplace_back(it->second);
}
return resultArr;
}
};

主要考察对哈希表的引用和排序

题目:

给定一个二叉树 root ,返回其最大深度。

二叉树的最大深度

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
//方法一:递归,返回子节点的最大深度+1
class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root){return 0;}
return max(maxDepth(root->left),maxDepth(root->right))+1;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//方法二:递归,维护一个全局变量,递归到子节点+1,返回最大值
class Solution {
public:
int maxDepth(TreeNode* root) {
int result = 0;
function<void(TreeNode* ,int )> def = [&result,&def](TreeNode* root,int count){
if(!root){
return;
}
count +=1;
result = max(result,count);
def(root->left,count);
def(root->right,count);
};
def(root,0);
return result;
}
};
1
2
3
4
5
6
7
8
//方法三,BFS
class Solution {
public:
int maxDepth(TreeNode* root) {

return = 0;
}
};