UE4 - C++:如何设计角色具有不同输入方案的本地合作游戏?
UE4 - C++: How to design a local coop game where characters have different input schemes?
这是我的第一个 post,在 post 来到这里之前我确实对这个主题做了很多研究。但现在我找到了几种可能的解决方案,但我不确定哪种方法才是正确的。
问题
我们目前正在开发一款本地合作游戏,该游戏混合了一个玩家的动作游戏和第二个玩家的益智游戏。我们的实际问题是当前由播放器控制器处理的输入,播放器控制器在接收到的每个动作映射委托上进行投射,以确定拥有的 Pawn 是来自类型 PlayerA 还是 PlayerB,然后调用正确的函数。
举个具体的例子:
我们有两个按钮 B(XBox 控制器)的动作绑定,当前称为 "B"
当委托被调用时,我们施放 possessedPlayer 来检查它是否应该调用 PlayerA->Jump 或 PlayerB->Blink
每次我们收到输入只是为了检查我是否拥有 action/puzzle char
时我必须施放的情况我完全不满意
解决方案
1) 创建 2 个 PlayerControllers 并使用 GameMode::SwapPlayerController(Old, New)
交换它们
我在研究过程中发现了这个功能,但我不喜欢用 PlayerControllerA 创建一个 Player 以立即将其切换为使用 PlayerControllerB,
2) 将责任转移给角色class
另一种想法是通过将 E_BUTTON_B 这样的枚举值从 PlayerController 传递给角色,从而将决策权委托给角色 class。我们可以编写一个宏来根据我们的输入映射创建此枚举,然后将决定委托给通用的 Character->ProcessInput(EnumValue) 函数。我也不太高兴,因为那时 PC 对我来说意义不大。
3)缓存拥有的Pawn以避免施法
另一个想法是在 PC 拥有 Pawn 时缓存拥有的角色的类型。这将消除每次输入委托调用的强制转换。
如果您能提供建议和任何提示,我将非常高兴你们如何解决游戏中的此类问题。我们的主要目标是关注点分离、良好的可维护性和输入重新绑定。
干杯,祝你有美好的一天,
帕齐瓦尔
您可以像这样创建结构(用 C++ 编写,但这种方法也可以在蓝图中轻松实现):
class MyGameBasePlayerController : public PlayerController
{
// TODO methods common for both controllers (for example Escape key handling)
}
现在特定控制器:
class PuzzlePlayerControler : public MyGameBasePlayerController
{
UPROPERTY(BlueprintReadWrite, Transient, Category = "MyCat"
PuzzleCharacter* puzzleChar;
// TODO handle specific actions for Puzzle chararacter and control handling.
// TODO override base methods / input bindings if necesary
virtual void Possess(APawn* pawn) override;
}
ActionPlayerCharacter
也是如此。
你需要决定,你的角色会有怎样的不同。如果它们相同,您可以使用 MyGameCharacter : public PlayerCharacter
之类的东西(或者您可以使用更广泛的 class PlayerPawn
)并且您的 PlayerControllers
将调用适当的方法。那么你存储的对 MyGameCharacter
的引用可以存储在 MyGameBasePlayerController
.
中
或者您也可以使用继承,因此您将拥有 PuzzleCharacter : public MyGameCharacter
和 ActionCharacter : MyGameCharacter
以及一些通用的基本实现和扩展方法或使用虚方法覆盖。
根据您的最终结构,您可以使用覆盖的 Possess
方法 (UE Docs) 获取实际的 pawn 实例,将其转换为适当的 class(例如 PuzzleCharacter
或 PuzlePawn
in PuzzlePlayerController
) 并存储参考供以后使用。 请注意,在这种情况下,您还应该实施 Unpossess
,这样您就可以清除存储的引用并在任何给定情况下都能正确运行。
这是我的第一个 post,在 post 来到这里之前我确实对这个主题做了很多研究。但现在我找到了几种可能的解决方案,但我不确定哪种方法才是正确的。
问题
我们目前正在开发一款本地合作游戏,该游戏混合了一个玩家的动作游戏和第二个玩家的益智游戏。我们的实际问题是当前由播放器控制器处理的输入,播放器控制器在接收到的每个动作映射委托上进行投射,以确定拥有的 Pawn 是来自类型 PlayerA 还是 PlayerB,然后调用正确的函数。
举个具体的例子:
我们有两个按钮 B(XBox 控制器)的动作绑定,当前称为 "B"
当委托被调用时,我们施放 possessedPlayer 来检查它是否应该调用 PlayerA->Jump 或 PlayerB->Blink
每次我们收到输入只是为了检查我是否拥有 action/puzzle char
时我必须施放的情况我完全不满意解决方案
1) 创建 2 个 PlayerControllers 并使用 GameMode::SwapPlayerController(Old, New)
交换它们我在研究过程中发现了这个功能,但我不喜欢用 PlayerControllerA 创建一个 Player 以立即将其切换为使用 PlayerControllerB,
2) 将责任转移给角色class
另一种想法是通过将 E_BUTTON_B 这样的枚举值从 PlayerController 传递给角色,从而将决策权委托给角色 class。我们可以编写一个宏来根据我们的输入映射创建此枚举,然后将决定委托给通用的 Character->ProcessInput(EnumValue) 函数。我也不太高兴,因为那时 PC 对我来说意义不大。
3)缓存拥有的Pawn以避免施法
另一个想法是在 PC 拥有 Pawn 时缓存拥有的角色的类型。这将消除每次输入委托调用的强制转换。
如果您能提供建议和任何提示,我将非常高兴你们如何解决游戏中的此类问题。我们的主要目标是关注点分离、良好的可维护性和输入重新绑定。
干杯,祝你有美好的一天,
帕齐瓦尔
您可以像这样创建结构(用 C++ 编写,但这种方法也可以在蓝图中轻松实现):
class MyGameBasePlayerController : public PlayerController
{
// TODO methods common for both controllers (for example Escape key handling)
}
现在特定控制器:
class PuzzlePlayerControler : public MyGameBasePlayerController
{
UPROPERTY(BlueprintReadWrite, Transient, Category = "MyCat"
PuzzleCharacter* puzzleChar;
// TODO handle specific actions for Puzzle chararacter and control handling.
// TODO override base methods / input bindings if necesary
virtual void Possess(APawn* pawn) override;
}
ActionPlayerCharacter
也是如此。
你需要决定,你的角色会有怎样的不同。如果它们相同,您可以使用 MyGameCharacter : public PlayerCharacter
之类的东西(或者您可以使用更广泛的 class PlayerPawn
)并且您的 PlayerControllers
将调用适当的方法。那么你存储的对 MyGameCharacter
的引用可以存储在 MyGameBasePlayerController
.
或者您也可以使用继承,因此您将拥有 PuzzleCharacter : public MyGameCharacter
和 ActionCharacter : MyGameCharacter
以及一些通用的基本实现和扩展方法或使用虚方法覆盖。
根据您的最终结构,您可以使用覆盖的 Possess
方法 (UE Docs) 获取实际的 pawn 实例,将其转换为适当的 class(例如 PuzzleCharacter
或 PuzlePawn
in PuzzlePlayerController
) 并存储参考供以后使用。 请注意,在这种情况下,您还应该实施 Unpossess
,这样您就可以清除存储的引用并在任何给定情况下都能正确运行。