企业网站管理系统用户,上海网站建设一般多少钱,现在的网站推广是怎么做的,微商城网站建设咨询在正常的游戏中#xff0c;我们应该考虑如何去初始化角色属性#xff0c;并且要给角色分好类型。比如#xff0c;在我们游戏中#xff0c;我们如何去初始化小兵的属性#xff0c;并且还要实现小兵随着等级的增长而增加属性。而且就是小兵也有类型的区分#xff0c;比如我…在正常的游戏中我们应该考虑如何去初始化角色属性并且要给角色分好类型。比如在我们游戏中我们如何去初始化小兵的属性并且还要实现小兵随着等级的增长而增加属性。而且就是小兵也有类型的区分比如我们将在后面设置小兵分为三种战士游侠法师。而小兵的属性实现一般需要策划进行配表实现将小兵的属性统一性的存入到表格导入项目。 我们将使用枚举去定义敌人的类型并创建一个ECharacterClass并创建一个DataAsset命名为UCharacterClassInfo用来设置每种类型使用的属性初始化的GE。对于随着等级变动的基础属性我们将使用曲线表格去生成所有等级的数据。并且在数据中我们去设置敌人需要附带的技能。 所以接下来我们实现的步骤是
创建一个枚举ECharacterClass来定义角色的种类创建一个DataAsset类 UCharacterClassInfo用来设置角色所使用得数据创建曲线表格用来定义角色属性跟随等级变化的值创建设置角色属性的GE通过函数实现角色应用设置的数据。
创建DataAsset
首先我们创建角色使用的DataAsset打开UE创建一个新类继承DataAsset并将其命名为CharacterClassInfo 在项目中首先创建我们第一步需要的枚举这里创建的三个职业的枚举
//角色职业类型的枚举
UENUM(BlueprintType)
enum class ECharacterClass : uint8
{Elementalist, //法师Warrior, //战士Ranger //游侠
};接着创建一个结构体用于根据不同的职业选择不同的结构体这是只添加了第一项就是基础的属性设置后面我们会增加更多的内容。
USTRUCT()
struct FCharacterClassDefaultInfo
{GENERATED_BODY()UPROPERTY(EditDefaultsOnly, CategoryClass Defaults)TSubclassOfUGameplayEffect PrimaryAttributes;
};有了枚举和角色初始化的结构体以后我们就可以创建DataAsset类了在数据类里我们首先创建一个Map类型用于创建不同职业对应的基础属性GE然后对于SecondaryAttributes和VitalAttributes我们共用一套。最后增加一个函数用于通过职业类型去获取基础的属性GE。
/*** 根据职业选择初始化角色的数据*/
UCLASS()
class AURA_API UCharacterClassInfo : public UDataAsset
{GENERATED_BODY()public:UPROPERTY(EditDefaultsOnly, CategoryClass Defaults)TMapECharacterClass, FCharacterClassDefaultInfo CharacterClassInformation;UPROPERTY(EditDefaultsOnly, CategoryCommon Class Defaults)TSubclassOfUGameplayEffect SecondaryAttributes;UPROPERTY(EditDefaultsOnly, CategoryCommon Class Defaults)TSubclassOfUGameplayEffect VitalAttributes;//通过枚举获取对应的初始化类FCharacterClassDefaultInfo GetClassDefaultInfo(ECharacterClass CharacterClass);
};函数的视线就是通过Map返回对应的类型的GE。
FCharacterClassDefaultInfo UCharacterClassInfo::GetClassDefaultInfo(ECharacterClass CharacterClass)
{return CharacterClassInformation.FindChecked(CharacterClass);
}创建完成后我们编译打开UE在里面创建一个可配置的DataAsset 选择我们前面创建的类 打开以后就是需要我们填充的值这里有个细节就是如果你得枚举第一项就选择枚举默认值那么后面将无法添加因为Map类型的Key不允许相同所以你可以先增加后面的枚举类型然后再最后设置默认枚举值。
创建对应的GE
创建了数据以后我们需要创建对应的GE文件去填充但是GE里面的数据需要根据等级去变动所以我们需要通过数据表格去实现这个功能。 首先我们创建对应的GE之前我们创建了一套主角使用的GE主要属性是设置的固定值虽然后续我们不会这么使用刚好直接使用它复制三个对应三个职业使用然后创建数据图表让GE根据等级去数据图表中获取数据。 然后是它的SecondaryAttributes和VitalAttribues我们在主角上使用的次级属性设置的GE是Infinite类型的复制一个修改成Instant类型的。因为敌人在我们的游戏设计中它们是不会升级也不会变动的所以不需要实时监听数值变化。而VitalAttributes则直接共用一套就行毕竟就是最后在生成将血量和蓝量填充到最满不需要额外制作。
创建GE使用的数据表格
为了能实现敌人的初始属性我们将创建曲线表格来实现角色等级增长带来的属性数值的变化。我们在实现时只要给敌人设置不同的等级它就会生成不同的属性的敌人。 在这里我们选择使用曲线表格曲线表格的好处是可以自动填充中间的数据并且可以过渡的更好。 创建曲线表格时它会提示我们创建什么类型的曲线 Constant就是没有过渡到了位置显示固定值一般不会使用 Linear就是线性过渡 Cubic就是贝塞尔曲线它会圆滑的过渡这里我们选择Cubic 曲线表格推荐使用CT开头比如我们创建的法师的类型的就叫做CT_PrimaryAttributes_Elementalist 打开曲线表格我们将四个属性都添加进去然后选择曲线编辑
选中一项属性然后鼠标右键添加关键帧 可以在上面添加关键帧的等级和数值然后点击缩放匹配 添加完成数值后我们可以右键点击自动 它就可以自动平滑处理 在这种情况下你没必要每个等级都设置并且可以看到对应等级的值 填充完数据之后我们将对应职业的属性设置上在选择使用表格后前面的数值将是得到的值的倍率然后选择表格中的曲线即可实现对应的效果。 后面我们将使用另外两种格式创建另外两个职业的数值我们不知道它的格式是怎么样的可以通过将当前创建的曲线表格导出CSV或者JSON格式 CSV文件打开就是表格的形式我们可以以此为模版进行修改但是CSV格式导入到UE无法进行平滑处理 CSV格式也可以通过文本打开
JSON格式就是标准的JSON字符串显示我们可以通过修改KEY和Value实现值的配置。
从外部文件导入表格数据
上面我们查看了对应的格式我们可以以此为模版修改数据并且直接导回到UE内。 导入到UE分为两种形式第一种是直接将文件导入我们可以在内容浏览器选择导入直接将所需的文件导入到UE内 选择文件后需要选择数据表格式和数据表插值类型。 导入后如果选的是Cubic那可以实现光滑取消的效果 如果你是先创建的文件然后重新导入 曲线就会变成线性插值
使用数据表格设置GE
上面我们实现了使用外部数据创建GE使用的数据表格这里再仔细讲一下如何使用数据表格设置GE。在你设置属性时后面有一个使用曲线表格 选择我们所使用的表格 表格里面能够存储多个数据所以我们还需要指定使用哪一条曲线 现在的设置的浮点数将是对从数据表格中获取到的结果的缩放比如在等级0时返回5 * 1为最终返回的力量值。 接下来我们将所有的属性都设置上去三个职业对应三个GE。
实现通过设置的通用GE实例化敌人
创建完成对应的GE我们并使用数据表格填充了对应的数据接下来我们将通过代码实现对应的逻辑去初始化角色。 首先我们考虑将创建数据放在哪里这里我们将其放到GameMode上面对于GameMode来说在不同场景可以设置不同的GameMode刚好合适比如你创建了一个关卡可以设置上对应的数据关卡内的敌人初始化时就使用这一套GE去初始化。 在我们的GameMode基类上增加一个变量用于设置数据
public:UPROPERTY(EditDefaultsOnly, CategoryCharacter Class Defaults)TObjectPtrUCharacterClassInfo CharacterClassInfo;接下来就是如何使用这个数据由于它是属于通用的函数我们将应用的函数创建到函数库里面之前刚好有个自定义的函数库我们在其内部增加对应的实现函数 在函数库增加一个函数用于初始角色属性 //初始化角色的属性UFUNCTION(BlueprintCallable, CategoryMyAbilitySystemLibrary|CharacterClassDefaults)static void InitializeDefaultAttributes(const UObject* WorldContextObject, ECharacterClass CharacterClass, float Level, UAbilitySystemComponent* ASC);在函数实现中首先获取到关卡的GameMode如果类型不一致获取到的是空指针将不执行后续操作 //获取到当前关卡的GameMode实例const AMyGameModeBase* GameMode CastAMyGameModeBase(UGameplayStatics::GetGameMode(WorldContextObject));if(GameMode nullptr) return;然后获取到我们配置的DataAsset //从实例获取到关卡角色的配置UCharacterClassInfo* ClassInfo GameMode-CharacterClassInfo;从DataAsset获取到配置的对应职业的数据 //获取到默认的基础角色数据const FCharacterClassDefaultInfo ClassDefaultInfo ClassInfo-GetClassDefaultInfo(CharacterClass);接下来就是三连应用和角色一致先应用主要属性这个会通过等级设置的不同的属性值然后根据基础属性生成次级属性的值最后根据属性填充血量和蓝量的值。 //应用基础属性FGameplayEffectContextHandle PrimaryContextHandle ASC-MakeEffectContext();PrimaryContextHandle.AddSourceObject(WorldContextObject);const FGameplayEffectSpecHandle PrimarySpecHandle ASC-MakeOutgoingSpec(ClassDefaultInfo.PrimaryAttributes, Level, PrimaryContextHandle);ASC-ApplyGameplayEffectSpecToSelf(*PrimarySpecHandle.Data.Get());//设置次级属性FGameplayEffectContextHandle SecondaryContextHandle ASC-MakeEffectContext();SecondaryContextHandle.AddSourceObject(WorldContextObject);const FGameplayEffectSpecHandle SecondarySpecHandle ASC-MakeOutgoingSpec(ClassInfo-SecondaryAttributes, Level, SecondaryContextHandle);ASC-ApplyGameplayEffectSpecToSelf(*SecondarySpecHandle.Data.Get());//填充血量和蓝量FGameplayEffectContextHandle VitalContextHandle ASC-MakeEffectContext();VitalContextHandle.AddSourceObject(WorldContextObject);const FGameplayEffectSpecHandle VitalSpecHandle ASC-MakeOutgoingSpec(ClassInfo-VitalAttributes, Level, VitalContextHandle);ASC-ApplyGameplayEffectSpecToSelf(*VitalSpecHandle.Data.Get());初始化角色属性的函数完成了接下来我们要在敌人的基类里面实现使用此函数。 首先在敌人的基类身上增加一个变量用来设置它的职业 UPROPERTY(EditAnywhere, BlueprintReadOnly, CategoryCharacter Class Defaults)ECharacterClass CharacterClass ECharacterClass::Warrior;在敌人基础的角色基础类里有个函数叫InitializeDefaultAttributes它是通过在角色的蓝图上面设置的三个GE进行初始化角色也是当前的主角在使用的方式。 但是在敌人这里我们不需要在角色身上设置对应的GE而是在GameMode的配置的数据里获取设置所以我们将其设置为虚拟函数 virtual void InitializeDefaultAttributes() const;在实现这里只需要调用函数库实现的InitializeDefaultAttributes函数即可实现对应的效果。
void AEnemyBase::InitAbilityActorInfo()
{AbilitySystemComponent-InitAbilityActorInfo(this, this);CastUAbilitySystemComponentBase(AbilitySystemComponent)-AbilityActorInfoSet();//通过GE初始角色的属性InitializeDefaultAttributes();
}void AEnemyBase::InitializeDefaultAttributes() const
{UMyAbilitySystemBlueprintLibrary::InitializeDefaultAttributes(this, CharacterClass, Level, AbilitySystemComponent);
}编写完成编译代码打开UE首先进入GameMode将我们之前编写的数据设置上去 然后选择场景中的敌人设置它的等级和职业
测试结果
配置完成现在角色的设置是否成功需要我们去测试结果我们有多种方式去测试。 第一种打印数据在应用完GE后打印角色的属性值来查看
void AEnemyBase::InitAbilityActorInfo()
{AbilitySystemComponent-InitAbilityActorInfo(this, this);CastUAbilitySystemComponentBase(AbilitySystemComponent)-AbilityActorInfoSet();//通过GE初始角色的属性InitializeDefaultAttributes();//打印生命值查看属性UE_LOG(LogTemp, Warning, TEXT(%s 的生命值为 %f), *this-GetName(), CastUAttributeSetBase(AttributeSet)-GetHealth());
}在输出日志里可以查看到打印的数值
另一种方法就是打断点我们将断点打在应用完GE后 刚好可以查看它的属性值的值是否正确