这是我的第一篇文章,在发布之前我真的做了很多关于这个主题的研究。但现在我找到了几种可能的解决方案,我只是不确定什么是正确的方法。
问题
我们目前正在开发一种本地合作游戏,它是一个玩家的动作游戏和第二个游戏的益智游戏的混合。我们的实际问题是当前由玩家控制器处理的输入,该控制器对每个接收到的动作映射委托进行强制转换,以确定所拥有的Pawn是否来自PlayerA或PlayerB类型,然后调用正确的函数。
让我举个具体的例子:
我们有两个动作绑定,用于当前称为“B”的按钮B(XBox控制器)
当委托被召唤时,我们施放possessedPlayer以检查它是否应该调用PlayerA-> Jump或PlayerB-> Blink
我非常不满意我每次收到输入时必须投射的情况只是为了检查我是否已经拥有动作/拼图字符
解决方案
1)创建2个PlayerControllers并使用 GameMode :: SwapPlayerController(Old,New)交换它们
我在研究过程中发现了这个功能但是我不满意用PlayerControllerA创建一个播放器以立即将其切换为使用PlayerControllerB,
2)将责任转移到Charatcer类
另一个想法是通过将一个枚举值(如E_BUTTON_B)从PlayerController传递给Character来将决策委托给Character类。我们可以根据输入映射编写一个创建此枚举的宏,然后将决策委托给一般的Character-> ProcessInput(EnumValue)函数。我也不太高兴,因为那时PC对我来说没那么有意义。
3)缓存拥有的Pawn以避免施放
另一个想法是当PC拥有Pawn时缓存所拥有的角色的类型。这将消除每个输入委托调用的强制转换。
我很高兴为您提供建议以及任何提示您如何在游戏中解决此类问题的提示。我们的主要目标是分离关注点,良好的可维护性和输入重新绑定。
干杯,祝你有个愉快的一天,
Parzival
答案 0 :(得分:0)
您可以创建这样的结构(用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
之类的内容(或者您可以使用更广泛的类PlayerPawn
),而PlayerControllers
会调用适当的方法。然后,您存储的MyGameCharacter
引用可以存储在MyGameBasePlayerController
。
或者您也可以使用继承,因此您将拥有PuzzleCharacter : public MyGameCharacter
和ActionCharacter : MyGameCharacter
一些常见的基本实现和扩展方法,或使用虚方法覆盖。
根据您的最终结构,您可以使用覆盖Possess
方法(UE Docs)来获取实际的pawn实例,将其强制转换为适当的类(例如PuzzleCharacter
或{{1} } {in PuzlePawn
)并存储引用以供以后使用。 请注意,在这种情况下,您也应该实施PuzzlePlayerController
,这样您就可以清除存储的引用,并在任何特定情况下都能正常运行。