受击反馈HitReact、死亡效果Death Dissolve、Floating伤害值Text(末尾附 客户端RPC )

受击反馈HitReact

设置角色受击标签 

(GameplayTag基本了解待补充)

角色监听标签并设置移动速度

创建一个受击技能,并应用GE

实现设置角色的受击蒙太奇动画

        实现角色受击时播放蒙太奇动画,为了保证通用性,将其设置为一个函数,并设置到战斗接口中,这样只需要在战斗接口中获取对应角色的蒙太奇即可。(每个角色的受击动画不一定一样)

UCLASS()
class AURA_API AAuraCharacterBase : public ACharacter, public IAbilitySystemInterface, public ICombatInterface
{
	GENERATED_BODY()

public:

	//HitReact
	virtual UAnimMontage* GetHitReactMontage_Implementation() override;

private:

	UPROPERTY(EditAnywhere, Category = "Combat")
	TObjectPtr<UAnimMontage> HitReactMontage;
};


UAnimMontage* AAuraCharacterBase::GetHitReactMontage_Implementation()
{
	return HitReactMontage;
}

别忘了设置对应的HitReact_AM

激活受击技能

在CharacterClassInfo.h里增加一个参数,用于设置创建敌人时所拥有的初始技能

在函数技能库里新增一个函数用于初始化角色技能

UCLASS()
class AURA_API UMyASBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:

	//初始化角色的技能
	UFUNCTION(BlueprintCallable, Category="MyBlueprintFunctionLibrary|CharacterClassDefaults")
	static void GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC);
	
};


void UMyASBlueprintFunctionLibrary::GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC)
{
	//获取到当前关卡的GameMode实例
	const AAuraGameModeBase* GameMode = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(WorldContextObject));
	if(GameMode == nullptr) return;

	//从实例获取到关卡角色的配置
	UCharacterClassInfo* CharacterClassInfo = GameMode->CharacterClassInfo;

	//遍历角色拥有的技能数组
	for(const TSubclassOf<UGameplayAbility> AbilityClass : CharacterClassInfo->CommonAbilities)
	{
		FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(AbilityClass, 1); //创建技能实例
		ASC->GiveAbility(AbilitySpec); //只应用不激活
	}
}

在敌人基类里,开始事件时,我们调用函数库的初始化技能函数,将技能应用到角色身上

void AAuraEnemy::BeginPlay()
{
	Super::BeginPlay();
	
	InitAbilityActorInfo();
	
	//初始化角色的技能
	UMyASBlueprintFunctionLibrary::GiveStartupAbilities(this, AbilitySystemComponent);
    
    ...
}

在PostGameplayEffectExecute函数里,之前设置血量下面有判断,我们在角色没有被击杀时,让其触发受击技能。 

void UAuraAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
    ...
	//查看IncomingDamage修改的是否为元属性
	if(Data.EvaluatedData.Attribute == GetIncomingDamageAttribute())
	{
		//获取到元属性的值备用,并将属性集上的值设置为0,等待下一次设置。
		const float LocalIncomingDamage = GetIncomingDamage();
		SetIncomingDamage(0.f);

		if(LocalIncomingDamage > 0.f)//伤害传入的时机
		{
			const float NewHealth = GetHealth() - LocalIncomingDamage; //受到伤害后的新生命值
			SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth())); //设置新的生命值

			const bool bFatal = NewHealth <= 0.f; //血量小于等于0时,角色将会死亡 致命的(Fatal)
			if(!bFatal) //在角色没有被击杀时,让其触发受击技能。
			{
				FGameplayTagContainer TagContainer;
				TagContainer.AddTag(FMyGameplayTags::Get().Effects_HitReact); //添个眼 这里原本是Effects.HitReact 对应GA一样  我是修改了
				Props.TargetASC->TryActivateAbilitiesByTag(TagContainer); //根据tag标签激活技能
			}
		}
	}

 接下来是蓝图中的设置(已做修改)

我们将使用标签激活技能,所以还需要将受击标签设置给技能

我们不需要在每次激活时创建一个新的实例,只需要一个角色生成一个实例重复利用即可。

        由于它一个角色对应一个单例,每次触发都是相同的实例,所以,我们需要在其播放完成后,将其结束,才可以重新触发,然后,在敌人的受击动画播放完成后,我们需要将敌人身上的受击标签清楚(如果GE添加的,只需要将对应的GE清除,标签也会随着清除)并结束技能。 

死亡效果Death/Dissolve

        我们实现了敌人受到攻击后会播放受击动画,并且还给角色设置了受击标签。并在角色受击时,在角色身上挂上受击标签,在c++里,如果挂载了此标签,速度将降为0 。
受击有了,接下来我们将实现角色的死亡逻辑,角色血量为0或者小于0时,我们将触发它的死亡功能

实现死亡

在战斗接口类里增加一个纯虚函数无法创建函数的实现,必须在子类里面去覆写它。

	virtual void Die() = 0;

在角色基类里面覆写

virtual void Die() override;

接着我们增加一个在每个客户端上执行的函数,被Die函数调用。
NetMulticast设置后,这个函数被调用时,将在服务器执行,然后复制到每个客户端。和它对应的还有(Server:只在服务器运行,Client:只在调用此函数的客户端运行)这种情况的函数实现需要在后面加上_Implementation
Reliable: 这是一个传输属性,表示该函数的数据应该以可靠的方式发送。

	UFUNCTION(NetMulticast, Reliable)
	virtual void MulticastHandleDeath();
void AAuraCharacterBase::Die()
{
	//将武器从角色身上分离(Detach)
	Weapon->DetachFromComponent(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));
	MulticastHandleDeath(); //NetMulticast在服务器执行,然后复制到每个客户端()
}

void AAuraCharacterBase::MulticastHandleDeath_Implementation()
{
	//开启武器物理效果
	Weapon->SetSimulatePhysics(true); //开启模拟物理效果
	Weapon->SetEnableGravity(true); //开启重力效果
	Weapon->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道

	//开启角色物理效果
	GetMesh()->SetSimulatePhysics(true); //开启模拟物理效果
	GetMesh()->SetEnableGravity(true); //开启重力效果
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道
	GetMesh()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); //开启角色与静态物体产生碰撞

	//关闭角色碰撞体碰撞通道,避免其对武器和角色模拟物理效果产生影响
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

在敌人基类里面也覆盖Die函数,并在死亡时设置它的清除时间

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat")
	float LifeSpan = 5.f; //设置死亡后的存在时间

void AAuraEnemy::Die()
{
	SetLifeSpan(LifeSpan); //在Enemy死亡后尸体会存在五秒 对象不再需要时会自动销毁
	Super::Die();
}

接下来在AttributeSet的PostGameplayEffectExecute函数里,增加Die函数调用的逻辑处理,我们在死亡时调用即可 

void UAuraAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
	。。。
	//查看IncomingDamage修改的是否为元属性
	if(Data.EvaluatedData.Attribute == GetIncomingDamageAttribute())
	{
		//获取到元属性的值备用,并将属性集上的值设置为0,等待下一次设置。
		const float LocalIncomingDamage = GetIncomingDamage();
		SetIncomingDamage(0.f);

		if(LocalIncomingDamage > 0.f)//伤害传入的时机
		{
			const float NewHealth = GetHealth() - LocalIncomingDamage; //受到伤害后的新生命值
			SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth())); //设置新的生命值

			const bool bFatal = NewHealth <= 0.f; //血量小于等于0时,角色将会死亡 致命的(Fatal)
			if(bFatal)
			{
				//调用死亡函数
				ICombatInterface* CombatInterface = Cast<ICombatInterface>(Props.TargetAvatarActor);
				if(CombatInterface)
				{
					CombatInterface->Die();
				}
			}
			else
			{
				在角色没有被击杀时,让其触发受击技能。
				FGameplayTagContainer TagContainer;
				TagContainer.AddTag(FMyGameplayTags::Get().Abilities_HitReact);  //添个眼 这里原本是Effects.HitReact 对应GA一样  我是修改了
				Props.TargetASC->TryActivateAbilitiesByTag(TagContainer); //根据tag标签激活技能
			}
		}
	}

测试效果

溶解材质(目前渲染方面不做了解)

小怪死亡定时直接清除掉,显得太突兀,大部分游戏中的做法就是使用溶解效果来实现它的缓慢消失的效果。

实现溶解效果

        实现从普通材质切换MI到溶解材质,并实现通过程序修改Dissolve溶解的标量Scalar Parameter参数数值。(步骤

        增加两个变量,用于设置角色和武器的溶解材质

        增加一个溶解函数,在角色死亡时调用

        溶解是需要一个时间过程,所以可以在蓝图里面实现时间轴,所以增加一个蓝图可实现函数,这个函数在代码里调用,在蓝图实现。

// YanWei.


UCLASS()
class AURA_API AAuraCharacterBase : public ACharacter, public IAbilitySystemInterface, public ICombatInterface
{
	GENERATED_BODY()

public:

	//--ICombatInterface
	virtual UAnimMontage* GetHitReactMontage_Implementation() override;//HitReact
	
	virtual void Die() override; //Death  OnServer 服务器端 
	UFUNCTION(NetMulticast, Reliable) //NetMulticast:在服务器执行,然后复制到每个客户端
	virtual void MulticastHandleDeath();

protected:

	//--Dissolve Effect 实现思路:是将avatar和weapon的材质叫换成下面的
    //溶解函数
	void Dissolve(); 
	//蓝图可实现事件
	UFUNCTION(BlueprintImplementableEvent)
	void StartDissolveTimeline(const TArray<UMaterialInstanceDynamic*>& DynamicMaterialInstance); 
    //接受材质实例dyn 数组用于存储材质s
	
	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	TObjectPtr<UMaterialInstance> DissolveMaterialInstance; 
	//对应的材质实例
	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	TObjectPtr<UMaterialInstance> WeaponDissolveMaterialInstance;

	//
	
};

//cpp


void AAuraCharacterBase::Dissolve()
{
	TArray<UMaterialInstanceDynamic*> DynMatArray;
	
	if (DissolveMaterialInstance)
	{
		UMaterialInstanceDynamic* DynamicMatInst = UMaterialInstanceDynamic::Create(DissolveMaterialInstance, this);
		GetMesh()->SetMaterial(0, DynamicMatInst);
		DynMatArray.Add(DynamicMatInst);
	}
	if (WeaponDissolveMaterialInstance)
	{
		UMaterialInstanceDynamic* DynamicMatInst = UMaterialInstanceDynamic::Create(WeaponDissolveMaterialInstance, this);
		Weapon->SetMaterial(0, DynamicMatInst);
		DynMatArray.Add(DynamicMatInst);
	}
	
	StartDissolveTimeline(DynMatArray);
}

void AAuraCharacterBase::Die()
{
	//将武器从角色身上分离(Detach)
	Weapon->DetachFromComponent(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));
	MulticastHandleDeath(); //NetMulticast在服务器执行,然后复制到每个客户端()
}

void AAuraCharacterBase::MulticastHandleDeath_Implementation()
{
	...

	//设置角色溶解
	Dissolve();
}

打开UE,在敌人基类里面覆写StartDissolveTimeline   (增加线结点<Add Reroute>)


创建一个时间轴 Timeline 并点击它 

 

 Set Scalar Parameter Value

效果图

伤害值浮动FloatingText

        实现技能或者攻击对敌人造成的伤害数值,并直观的显示出来。接下来,还要实现一个用户控件,来设置伤害数值的UI表现。并且还需要一个用户控件的组件来修改伤害UI显示的数值。在创建完成这些以后,我们还需要实现从AttributeSet里面实现在目标位置(也就是受到伤害的角色位置)创建组件,并实现在每个客户端上面显示数值。

创建Damage用户控件

新建一个控件蓝图,这里不需要其它脚本直接基于UserWidget创建即可。我们将其命名为WBP_DamageText

在控件里面增加一个覆层,覆层下面添加一个文本显示文字

在控件尺寸这里,我们使用自定义,来设置一个固定的尺寸,这样它的尺寸不会乱动,不会在更新时频繁修改尺寸影响性能。

然后设置文本的样式,并将其设置为变量,方便后期修改其显示的内容

创建伤害文字动画 (视觉反馈很重要!)

动画创建完成后,在事件构造时调用动画播放

创建用户控件组件

用户控件创建完成,我们还需要创建用户控件组件,用于实现用户控件的实例化并播放动画。
所以,我们接下来要创建一个用户组件的控件,创建基于最基本的组件即可,我们不需要从控制器获取内容,只需要一个设置显示数字的方法即可。命名为DamageTextComponent

增加一个函数,设置伤害的数值,可以在蓝图内实现此函数,并且可以在蓝图内调用

基于此类创建一个蓝图类,命名为BP_DamageTextComponent

现在这个蓝图相当于一个未挂载在对象上面的组件类,但是我们可以设置它的默认参数。我们将空间修改为屏幕空间,并将创建的用户控件设置上去

在蓝图内,我们实现SetDamageText,将设置的类型转换为我们创建的用户组件类型,调用它的更新数字方法,然后在延迟一秒钟(动画播放一秒钟)后,将自身销毁,组件也会跟随销毁。

其中 UpdateDamageText   鼠标处设0是为了只显示整数部分

调用实现伤害显示

现在,我们有了显示伤害数值的用户控件和组件,接下来就要考虑实现如何调用并显示对应的内容。
现在有个问题,就是我们是通过在AttributeSet里面通过元属性获取到当前的伤害的,它是在服务器上运行的,因此,我们要实现在AttributeSet里面去调用函数生成,并且,还需要获取到玩家控制器,因为你需要将数值显示给玩家查看得,所以,我们将数值在玩家控制器里面实现在每个客户端上面调用是一个很好的选择。
所以,我们打开玩家控制器的基类,在里面增加一个函数,用于复制到每个客户端并且只会在客户端执行所以我们设置了Client (只在客户端执行)
函数内部实现在目标角色身上显示伤害数字

(制作一个客户端RPC函数,如果在服务端调用它,它将在服务端执行,如果玩家控制器是本地Local的话;但是如果玩家控制器是Remote远程的话,这个函数将被执行在remote远程的客户端)

// YanWei.

class UDamageTextComponent;

/**
 *  
 */
UCLASS()
class AURA_API AAuraPlayerController : public APlayerController
{
	GENERATED_BODY()
public:
	AAuraPlayerController();
	virtual void PlayerTick(float DeltaTime) override;

	//客户端RPC函数
	UFUNCTION(Client, Reliable)
	void ShowDamageNumber(float DamageAmount, ACharacter* TargetCharacter); //在每个客户端显示伤害数值

	
private:
    。。。	
	//DamageText  创建一个用于设置显示伤害数值的组件类,后续可以使用它去实例化多个实例,显示多个伤害数值
	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<UDamageTextComponent> DamageTextComponentClass;

};



// 客户端的具体实现
void AAuraPlayerController::ShowDamageNumber_Implementation(float DamageAmount,ACharacter* TargetCharacter)
{
	if(IsValid(TargetCharacter) && DamageTextComponentClass)
	{
        //在内部实例化组件,并注册,在实例化时,第一个参数相当于作为此组件的父类,当PlayerController被销毁时,它也会被销毁。
		UDamageTextComponent* DamageText = NewObject<UDamageTextComponent>(TargetCharacter, DamageTextComponentClass);
		DamageText->RegisterComponent(); //动态创建的组件需要调用注册
		
		DamageText->AttachToComponent(TargetCharacter->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform); //先附加到角色身上,使用角色位置
		DamageText->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); //然后从角色身上分离,保证在一个位置播放完成动画
		DamageText->SetDamageText(DamageAmount); //设置显示的伤害数字
	}
}



// YanWei.

/**
 *  
 */
UCLASS()
class AURA_API UAuraAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
protected:
	//用于服务器端调用客户端RPC函数,在客户端执行
	static void ShowFloatingText(const FEffectProperties& Props, const float Damage);
};



// 服务器调用客户端函数的实现
void UAuraAttributeSet::ShowFloatingText(const FEffectProperties& Props, const float Damage)
{
	//调用显示伤害数字
	if(Props.SourceCharacter != Props.TargetCharacter)
	{
		if(AAuraPlayerController* PC = Cast<AAuraPlayerController>(UGameplayStatics::GetPlayerController(Props.SourceCharacter, 0)))
		{
            //调用客户端RPC函数
			PC->ShowDamageNumber(Damage, Props.TargetCharacter); //调用显示伤害数字
		}
	}
}

void UAuraAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
	。。。
		if(LocalIncomingDamage > 0.f)//伤害传入的时机
		{
			。。。
			//TODO::设置显示float伤害值的区域
			ShowFloatingText(Props, LocalIncomingDamage);// 服务端请求客户端执行
		}
	}

 在BP_Controller控制器中设置bpCompDamageText

测试结果

每个客户端只能看到自己所造成的浮动伤害值,其他客户端看不到别的客户端(也包括监听服务器端)造成浮动伤害值,而(监听)服务端可以看到所有的浮动伤害值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962395.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++,STL 命名空间:理解 std 的作用、规范与陷阱

文章目录 引言一、为什么需要 std 命名空间&#xff1f;二、std 命名空间的组成三、使用 std 命名空间的正确姿势1. 显式作用域限定2. 谨慎使用 using 声明3. 头文件中禁止 using namespace std 四、常见陷阱与解决方案陷阱 1&#xff1a;与第三方库命名冲突陷阱 2&#xff1a;…

第11章:根据 ShuffleNet V2 迁移学习医学图像分类任务:甲状腺结节检测

目录 1. Shufflenet V2 2. 甲状腺结节检测 2.1 数据集 2.2 训练参数 2.3 训练结果 2.4 可视化网页推理 3. 下载 1. Shufflenet V2 shufflenet v2 论文中提出衡量轻量级网络的性能不能仅仅依靠FLOPs计算量&#xff0c;还应该多方面的考虑&#xff0c;例如MAC(memory acc…

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。 相关阅读:【ArcGIS微课1000例】0141:提取多波段影像中的单个波段 文章目录 一、数据准备二、效果比对二、python批处理1. 编写python代码2. 运行代码一、数据准备 实验数据及完整的python位…

HTB:Administrator[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用nmap对靶机…

vscode+WSL2(ubuntu22.04)+pytorch+conda+cuda+cudnn安装系列

最近在家过年闲的没事&#xff0c;于是研究起深度学习开发工具链的配置和安装&#xff0c;之前欲与天公试比高&#xff0c;尝试在win上用vscodecuda11.6vs2019的cl编译器搭建cuda c编程环境&#xff0c;最后惨败&#xff0c;沦为笑柄&#xff0c;痛定思痛&#xff0c;这次直接和…

亚博microros小车-原生ubuntu支持系列:17 gmapping

前置依赖 先看下亚博官网的介绍 Gmapping简介 gmapping只适用于单帧二维激光点数小于1440的点&#xff0c;如果单帧激光点数大于1440&#xff0c;那么就会出【[mapping-4] process has died】 这样的问题。 Gmapping是基于滤波SLAM框架的常用开源SLAM算法。 Gmapping基于RBp…

FreeRTOS从入门到精通 第十六章(任务通知)

参考教程&#xff1a;【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、任务通知简介 1、概述 &#xff08;1&#xff09;任务通知顾名思义是用来通知任务的&#xff0c;任务控制块中的结构体成员变量ulNotifiedValue就是这个通知值。 &#xff08;2&#…

数据结构选讲 (更新中)

参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的&#xff1a; AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MSTP5280 [ZJOI2019] 线段树 AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树&#xff0c;点有点权 w i w_i wi​&am…

【01】共识机制

BTF共识 拜占庭将军问题 拜占庭将军问题是一个共识问题 起源 Leslie Lamport在论文《The Byzantine Generals Problem》提出拜占庭将军问题。 核心描述 军中可能有叛徒&#xff0c;却要保证进攻一致&#xff0c;由此引申到计算领域&#xff0c;发展成了一种容错理论。随着…

春晚舞台上的人形机器人:科技与文化的奇妙融合

文章目录 人形机器人Unitree H1的“硬核”实力传统文化与现代科技的创新融合网友热议与文化共鸣未来展望&#xff1a;科技与文化的更多可能结语 2025 年央视春晚的舞台&#xff0c;无疑是全球华人目光聚焦的焦点。就在这个盛大的舞台上&#xff0c;一场名为《秧BOT》的创意融合…

.NET Core缓存

目录 缓存的概念 客户端响应缓存 cache-control 服务器端响应缓存 内存缓存&#xff08;In-memory cache&#xff09; 用法 GetOrCreateAsync 缓存过期时间策略 缓存的过期时间 解决方法&#xff1a; 两种过期时间策略&#xff1a; 绝对过期时间 滑动过期时间 两…

如何从客观角度批判性阅读分析博客

此文仅以个人博客为例&#xff0c;大量阅读朋友反馈给我的交流让我得知他们所理解我的博客所表达的意思并非我所想表达的&#xff0c;差异或大或小&#xff0c;因人而异。 观点与事实 只有从客观角度反复批判性阅读和分析&#xff0c;才能逐渐清晰观点和事实。 观点不等于事实…

【力扣】49.字母异位词分组

AC截图 题目 思路 由于互为字母异位词的两个字符串包含的字母相同&#xff0c;因此对两个字符串分别进行排序之后得到的字符串一定是相同的&#xff0c;故可以将排序之后的字符串作为哈希表的键。 可以遍历strs&#xff0c;将其中每一个str排序&#xff0c;然后用unodered_ma…

【4Day创客实践入门教程】Day4 迈向高手之路——进一步学习!

Day4 迈向高手之路——进一步学习&#xff01; 目录 Day4 迈向高手之路——进一步学习&#xff01;更多的开发板外壳制作 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟Day4…

什么是线性化PDF?

线性化PDF是一种特殊的PDF文件组织方式。 总体而言&#xff0c;PDF是一种极为优雅且设计精良的格式。PDF由大量PDF对象构成&#xff0c;这些对象用于创建页面。相关信息存储在一棵二叉树中&#xff0c;该二叉树同时记录文件中每个对象的位置。因此&#xff0c;打开文件时只需加…

向下调整算法(详解)c++

算法流程&#xff1a; 与⽗结点的权值作⽐较&#xff0c;如果⽐它⼤&#xff0c;就与⽗亲交换&#xff1b; 交换完之后&#xff0c;重复 1 操作&#xff0c;直到⽐⽗亲⼩&#xff0c;或者换到根节点的位置 大家可能会有点疑惑&#xff0c;这个是大根堆&#xff0c;22是怎么跑到…

unity学习25:用 transform 进行旋转和移动,简单的太阳地球月亮模型,以及父子级关系

目录 备注内容 1游戏物体的父子级关系 1.1 父子物体 1.2 坐标关系 1.3 父子物体实际是用 每个gameobject的tranform来关联的 2 获取gameObject的静态数据 2.1 具体命令 2.2 具体代码 2.3 输出结果 3 获取gameObject 的方向 3.1 游戏里默认的3个方向 3.2 获取方向代…

C基础算法与实现

前言 通过业务侧输入需求,使用代码完成。 1.偶数立方和 编写函数求1~100中奇数的平方与偶数的立方的和 1.1代码实现结果 1.2源码示例 #include <stdio.h>// 计算1到100中奇数的平方与偶数的立方的和 int calculateSum() {int sum 0;// 遍历1到100之间的所有数字for (…

基于SSM实现的乡村振兴文化平台系统功能实现十八

一、前言介绍&#xff1a; 1.1 项目摘要 农耕文明是广大群众在几千年的农业生产生活中智慧的结晶&#xff0c;不仅是乡土文化的核心和精髓&#xff0c;还是中华文明的起源和基因。因此&#xff0c;传承和发扬优秀乡村文化&#xff0c;是传承农耕文明的必然要求。 文化振兴是乡…

如何让一个用户具备创建审批流程的权限

最近碰到一个问题&#xff0c;两个sandbox&#xff0c;照理用户的权限应该是一样的&#xff0c;结果开发环境里面我可以左右的做各种管理工作&#xff0c;但是使用change set上传后&#xff0c;另一个环境的同一个用户&#xff0c;没有相对于的权限&#xff0c;权限不足。 当时…