第18章 UE5创建命令

第18章 UE5创建命令

在现代游戏中,命令系统是玩家与游戏交互的重要方式,特别是在RPG和MMO游戏中。本章将探讨如何在UE5.2中创建一个灵活、安全且用户友好的命令系统,让玩家能够通过文本输入执行各种游戏功能。

18.1 检测基本的命令

命令系统的核心是能够解析用户输入并将其转换为游戏动作。让我们从创建一个基本的命令解析器开始:

cpp

// CommandSystem.h
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "CommandSystem.generated.h"

// 命令执行委托
DECLARE_DYNAMIC_DELEGATE_RetVal_TwoParams(bool, FCommandExecuteDelegate, const TArray<FString>&, Arguments, FString&, ErrorMessage);

// 命令定义结构
USTRUCT(BlueprintType)
struct FCommandDefinition
{
    GENERATED_BODY()
    
    // 命令名称
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    FString Name;
    
    // 命令描述
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    FString Description;
    
    // 使用示例
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    FString Usage;
    
    // 所需权限级别
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    int32 RequiredPermissionLevel;
    
    // 是否需要目标
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    bool bRequiresTarget;
    
    // 是否在战斗中可用
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    bool bAvailableInCombat;
    
    // 命令别名
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    TArray<FString> Aliases;
    
    // 执行委托
    FCommandExecuteDelegate ExecuteDelegate;
    
    // 构造函数
    FCommandDefinition()
        : Name("")
        , Description("")
        , Usage("")
        , RequiredPermissionLevel(0)
        , bRequiresTarget(false)
        , bAvailableInCombat(true)
    {
    }
};

// 命令执行结果
USTRUCT(BlueprintType)
struct FCommandResult
{
    GENERATED_BODY()
    
    // 是否成功执行
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    bool bSuccess;
    
    // 结果消息
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Command")
    FString Message;
    
    // 构造函数
    FCommandResult()
        : bSuccess(false)
        , Message("")
    {
    }
    
    // 带参数构造函数
    FCommandResult(bool InSuccess, const FString& InMessage)
        : bSuccess(InSuccess)
        , Message(InMessage)
    {
    }
};

// 命令事件委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCommandExecuted, const FCommandResult&, Result);

/**
 * 命令系统 - 处理游戏命令的解析和执行
 */
UCLASS()
class MYGAME_API UCommandSystem : public UGameInstanceSubsystem
{
    GENERATED_BODY()
    
public:
    // 初始化
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;
    
    // 注册命令
    UFUNCTION(BlueprintCallable, Category = "Command System")
    bool RegisterCommand(const FCommandDefinition& CommandDef);
    
    // 注销命令
    UFUNCTION(BlueprintCallable, Category = "Command System")
    bool UnregisterCommand(const FString& CommandName);
    
    // 执行命令
    UFUNCTION(BlueprintCallable, Category = "Command System")
    FCommandResult ExecuteCommand(const FString& CommandString, int32 UserPermissionLevel = 0, AActor* TargetActor = nullptr);
    
    // 获取命令帮助
    UFUNCTION(BlueprintCallable, Category = "Command System")
    FString GetCommandHelp(const FString& CommandName);
    
    // 获取所有命令列表
    UFUNCTION(BlueprintCallable, Category = "Command System")
    TArray<FString> GetAllCommands();
    
    // 获取带有指定前缀的命令列表(用于自动完成)
    UFUNCTION(BlueprintCallable, Category = "Command System")
    TArray<FString> GetCommandsWithPrefix(const FString& Prefix);
    
    // 检查命令是否存在
    UFUNCTION(BlueprintCallable, Category = "Command System")
    bool CommandExists(const FString& CommandName);
    
    // 解析命令字符串
    UFUNCTION(BlueprintCallable, Category = "Command System")
    void ParseCommandString(const FString& CommandString, FString& OutCommandName, TArray<FString>& OutArguments);
    
    // 命令执行事件
    UPROPERTY(BlueprintAssignable, Category = "Command System")
    FOnCommandExecuted OnCommandExecuted;
    
    // 注册内置命令
    UFUNCTION(BlueprintCallable, Category = "Command System")
    void RegisterBuiltInCommands();
    
private:
    // 命令映射
    TMap<FString, FCommandDefinition> Commands;
    
    // 命令前缀字符(例如:/,!等)
    UPROPERTY()
    FString CommandPrefix;
    
    // 检查命令前缀
    bool CheckCommandPrefix(FString& CommandString);
    
    // 查找命令定义
    bool FindCommandDefinition(const FString& CommandName, FCommandDefinition& OutCommandDef);
    
    // 输出帮助信息
    FCommandResult OutputHelpInfo(const TArray<FString>& Arguments);
    
    // 输出系统信息
    FCommandResult OutputSystemInfo(const TArray<FString>& Arguments);
};

// CommandSystem.cpp
#include "CommandSystem.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"

void UCommandSystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);
    
    // 设置命令前缀
    CommandPrefix = TEXT("/");
    
    // 注册内置命令
    RegisterBuiltInCommands();
    
    UE_LOG(LogTemp, Log, TEXT("Command System initialized"));
}

void UCommandSystem::Deinitialize()
{
    // 清除所有命令
    Commands.Empty();
    
    Super::Deinitialize();
}

bool UCommandSystem::RegisterCommand(const FCommandDefinition& CommandDef)
{
    // 检查命令名是否为空
    if (CommandDef.Name.IsEmpty())
    {
        UE_LOG(LogTemp, Warning, TEXT("Cannot register command with empty name"));
        return false;
    }
    
    // 检查命令名是否已存在
    if (Commands.Contains(CommandDef.Name.ToLower()))
    {
        UE_LOG(LogTemp, Warning, TEXT("Command '%s' already registered"), *CommandDef.Name);
        return false;
    }
    
    // 检查委托是否绑定
    if (!CommandDef.ExecuteDelegate.IsBound())
    {
        UE_LOG(LogTemp, Warning, TEXT("Command '%s' has no execute delegate bound"), *CommandDef.Name);
        return false;
    }
    
    // 添加命令
    Commands.Add(CommandDef.Name.ToLower(), CommandDef);
    
    // 添加别名
    for (const FString& Alias : CommandDef.Aliases)
    {
        if (!Alias.IsEmpty() && !Commands.Contains(Alias.ToLower()))
        {
            FCommandDefinition AliasDef = CommandDef;
            AliasDef.Name = Alias;
            Commands.Add(Alias.ToLower(), AliasDef);
        }
    }
    
    UE_LOG(LogTemp, Log, TEXT("Registered command: %s"), *CommandDef.Name);
    return true;
}

bool UCommandSystem::UnregisterCommand(const FString& CommandName)
{
    // 检查命令名是否为空
    if (CommandName.IsEmpty())
    {
        return false;
    }
    
    // 尝试移除命令
    bool bRemoved = false;
    
    // 移除主命令
    FCommandDefinition CommandDef;
    if (FindCommandDefinition(CommandName, CommandDef))
    {
        Commands.Remove(CommandName.ToLower());
        bRemoved = true;
        
        // 移除别名
        for (const FString& Alias : CommandDef.Aliases)
        {
            Commands.Remove(Alias.ToLower());
        }
    }
    
    if (bRemoved)
    {
        UE_LOG(LogTemp, Log, TEXT("Unregistered command: %s"), *CommandName);
    }
    
    return bRemoved;
}

FCommandResult UCommandSystem::ExecuteCommand(const FString& CommandString, int32 UserPermissionLevel, AActor* TargetActor)
{
    FString CommandName;
    TArray<FString> Arguments;
    
    // 检查命令前缀
    FString ProcessedCommand = CommandString;
    CheckCommandPrefix(ProcessedCommand);
    
    // 解析命令字符串
    ParseCommandString(ProcessedCommand, CommandName, Arguments);
    
    // 检查命令是否为空
    if (CommandName.IsEmpty())
    {
        return FCommandResult(false, TEXT("No command specified"));
    }
    
    // 查找命令定义
    FCommandDefinition CommandDef;
    if (!FindCommandDefinition(CommandName, CommandDef))
    {
        return FCommandResult(false, FString::Printf(TEXT("Unknown command: %s"), *CommandName));
    }
    
    // 检查权限
    if (UserPermissionLevel < CommandDef.RequiredPermissionLevel)
    {
        return FCommandResult(false, TEXT("You don't have permission to use this command"));
    }
    
    // 检查是否需要目标
    if (CommandDef.bRequiresTarget && !TargetActor)
    {
        return FCommandResult(false, TEXT("This command requires a target"));
    }
    
    // 检查是否在战斗中可用
    // 在实际游戏中,您需要添加检查玩家是否在战斗中的逻辑
    bool bInCombat = false; // 示例,假设玩家不在战斗中
    if (bInCombat && !CommandDef.bAvailableInCombat)
    {
        return FCommandResult(false, TEXT("This command cannot be used in combat"));
    }
    
    // 执行命令
    FString ErrorMessage;
    bool bSuccess = CommandDef.ExecuteDelegate.Execute(Arguments, ErrorMessage);
    
    // 创建结果
    FCommandResult Result;
    Result.bSuccess = bSuccess;
    
    if (bSuccess)
    {
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝哥Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值