unreal中actor的property replicate简单小节

news2024/9/27 9:26:32

首先参考的网址是官网中的:
https://docs.unrealengine.com/5.1/en-US/multiplayer-programming-quick-start-for-unreal-engine/

unreal引擎的版本是5.1

还原的过程相对比较简单,主要的精力花在了编译报错和调试的过程。
属性复制的流程如下:
在这里插入图片描述
ClientA和CleintB的的通信,由Server转发。
ClientA开枪打了ClientB,造成伤害后,由Server,将伤害同步给两个客户端。

完成这个需求使用属性同步的方式。
1、书写客户端回调函数

声明一个属性,添加必要的复制标签。

UPROPERTY(ReplicatedUsing = xxxOnRep_CurrentHealth)
float CurrentHealth;

这里的ReplicatedUsing作为关键字和Replicated的都可以,但是ReplicatedUsing 后面可以配置一个回调函数。这里xxxOnRep_CurrentHealth为ClientA或者B收到服务器的通知之后,执行的函数,函数名字任意。

回调函数xxxOnRep_CurrentHealth的实现:

void ADedicatedServerDemoCharacter::xxxOnRep_CurrentHealth()
{
	UE_LOG(LogTemp, Error, TEXT("yyyyyyyyyyyyyyyyyy"));
	OnHealthUpdate();
}

void ADedicatedServerDemoCharacter::OnHealthUpdate()
{
	//Client-specific functionality
	if (IsLocallyControlled())
	{
		FString healthMessage = FString::Printf(TEXT("You now have %f health remaining."), CurrentHealth);
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, healthMessage);

		if (CurrentHealth <= 0)
		{
			FString deathMessage = FString::Printf(TEXT("You have been killed."));
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, deathMessage);
		}
		UE_LOG(LogTemp, Error, TEXT("xxxxxxxxxxxxxxxxxxxxxx"));
	}

	//Server-specific functionality
	if (GetLocalRole() == ROLE_Authority)
	{
		FString healthMessage = FString::Printf(TEXT("%s now has %f health remaining."), *GetFName().ToString(), CurrentHealth);
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, healthMessage);
		UE_LOG(LogTemp, Error, TEXT("%s now has %f health remaining."), *GetFName().ToString(), CurrentHealth);
	}

	//Functions that occur on all machines. 
	/*  
		Any special functionality that should occur as a result of damage or death should be placed here. 
	*/
}

这里可以让客户端做展示使用。这里IsLocallyControlled,是用来判断是否是客户端。
参考:https://zhuanlan.zhihu.com/p/548761791

而:if (GetLocalRole() == ROLE_Authority)用来判断是否是服务器。

这里要注意,此函数OnHealthUpdate是跑在所有端,仅仅通过IsLocallyControlled和GetLocalRole() == ROLE_Authority)来区分是客户端还是服务器。
在这里插入图片描述
2、如何造成伤害
unreal中,造成伤害是很容易。由于我们的class ADedicatedServerDemoCharacter : public ACharacter具有这种继承关系:

//直接声明TakeDamage函数
UFUNCTION(BlueprintCallable, Category = "Health")
	float TakeDamage( float DamageTaken, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser ) override;

//TakeDamage函数具体实现
float ADedicatedServerDemoCharacter::TakeDamage(float DamageTaken, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	float damageApplied = CurrentHealth - DamageTaken;
	SetCurrentHealth(damageApplied);
	return damageApplied;
}

//这段函数跑在服务器
void ADedicatedServerDemoCharacter::SetCurrentHealth(float healthValue)
{
	if (GetLocalRole() == ROLE_Authority)
	{
		CurrentHealth = FMath::Clamp(healthValue, 0.f, MaxHealth);
		OnHealthUpdate();
	}
}

当收到伤害之后,会调用SetCurrentHealth函数设置当前血量。注意此函数要判断是否是服务器,只有服务器才能修改这个值。

那我什么时候被伤害呢?即TakeDamage函数,是谁调用的呢?
是子弹击中人的时候,造成伤害,这个调用伤害的地方,应该在子弹类中实现:

void ABullet::OnBulletHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	if (OtherActor)
	{
		UGameplayStatics::ApplyPointDamage(OtherActor, Damage, NormalImpulse, Hit, GetInstigator()->Controller, this, DamageType);
	}

	Destroy();
}

当子弹发生碰撞的时候,要调用伤害函数。
在这里插入图片描述
有我们的ADedicatedServerDemoCharacter重写了TakeDamage函数,所以逻辑是通了。

那这个子弹的啥时候调用OnBulletHit呢?

ABullet::ABullet()
{
 	PrimaryActorTick.bCanEverTick = true;
	bReplicates = true;
	
	SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
	SphereComponent->InitSphereRadius(37.5f);
	SphereComponent->SetCollisionProfileName(TEXT("BlockAllDynamic"));
	RootComponent = SphereComponent;

	//Registering the Projectile Impact function on a Hit event.
	if (GetLocalRole() == ROLE_Authority)
	{
		SphereComponent->OnComponentHit.AddDynamic(this, &ABullet::OnBulletHit);
	}

要使用SphereComponent 进行注册:OnComponentHit.AddDynamic
同时判断只有在服务器上的if (GetLocalRole() == ROLE_Authority) 才能进行注册这个回调函数。

到目前位置,我们在不用rpc的方式,而是为属性添加标签ReplicatedUsing的方式,实现了属性的同步。他的唯一的缺点是,要时刻区分初,当前这段代码是在客户端还是在服务器。

理解的逻辑过程为:子弹攻攻击人、人受击后,服务器计算伤害,然后同步给客户端。
这里存疑的地方是,子弹的碰撞是在服务器上的?还是在客户端上的。TakeDamage函数是谁调用的?这个在调试的时候,可以看看堆栈。

3、另外补充下,调试的方式:
在这里插入图片描述
在编辑器下,选择Net Mode为Play As Listen Server,然后Number of Players为2,运行之后,然后使用Attach to Process即可调试,也可以打log方式,在控制台看log。

另外如果是打包成服务器和客户端的exe的方式,还是看log吧。还要注意,改一行代码,也要打包server,否则连不上服务器。

如何构建服务器,参考:https://blog.csdn.net/wodownload2/article/details/128452317?spm=1001.2014.3001.5501

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

尚医通-MongDB简介-安装-概念-操作(十六)

目录 &#xff08;1&#xff09;MongDB-简介和安装 &#xff08;2&#xff09;MongDB-概念和操作 &#xff08;1&#xff09;MongDB-简介和安装 1、NoSQL简介 MongDB为什么要用呢&#xff1f;之前我们用MySQL数据库&#xff0c;如果数据达到一定的量级&#xff0c;或者有高…

QT 之SQLite数据库

文章目录一、windows下使用命令行方法操作db文件1、 安装sqlite2、 使用sqlite二、QT操作sqlite1、 建立数据库2、 打开数据库3 、关闭数据库4、 创建数据表5 、插入数据6、 删除表数据7、 修改表数据8、 查询数据——遍历查询、条件查询一、windows下使用命令行方法操作db文件…

计算机网络期中考试部分题目

1. &#xff08;1&#xff09;以太网帧的数据部分是IP数据报&#xff0c;只要数出相应字段所在的字节即可。由图可知以太网帧头部有6&#xff0b;6214字节&#xff0c;IP数据报首部的目的P地址字段前有4x4 16字节&#xff0c;从帧的第1字节开始数141630字节&#xff0c;得目的P…

java怎么完成输出语句

我们在前面的文章和案例中&#xff0c;其实早就知道Java是如何实现输出功能的了。没错&#xff0c;就是利用System.out.println()语句来实现的&#xff01;接下来壹哥就给大家详细解读一下这个语句的作用及其含义。 1. System 我们先来看看System是个什么东东。 System是Jav…

不推荐别的了,IDEA 自带的数据库工具就很牛逼!

MySQL 等数据库客户端软件市面上非常多了&#xff0c;别的栈长就不介绍了&#xff0c; 其实 IntelliJ IDEA 自带的数据库工具就很牛逼&#xff0c;不信你继续往下看。 本文以 IntelliJ IDEA/ Mac 版本作为演示&#xff0c;其他版本的应该也差距不大&#xff01; 1、打开数据库…

JPE驱动器维修印刷机驱动器维修JV4-380-1410

印刷机水辘/墨辘/墨斗辊电机马达驱动器维修、墨控电机驱动器维修、JPE驱动器维修。 三菱印刷机电路板维修范围&#xff1a;东洋变频器维修&#xff0c;油墨电机维修&#xff0c;水辊变频器维修&#xff0c;电眼控制板维修&#xff0c;接口板维修&#xff0c;电源维修等。 小森…

【结构型】外观模式(Facade)

目录外观模式(Facade)适用场景外观模式实例代码&#xff08;Java&#xff09;外观模式(Facade) 为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式 (Facade) 定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。 适用场景 要为一个复杂子系统提…

【C++】初级面试整理

C基础 四种类型转换 static_cast&#xff1a;用于良性转换&#xff0c;一般不会导致意外发生&#xff0c;风险很低。常用于基本类型转换到 void&#xff0c;转换父类指针到子类不安全&#xff1b; const_cast&#xff1a;一般用于去掉const属性以及volatile&#xff0c;但是…

如何进行深度数据恢复?分享详细的恢复方法

有时我们会发现保存已久的照片&#xff0c;因为某些误操作导致它们消失了。通过多种方法都没有办法找回&#xff0c;这时该怎么办&#xff1f;不妨尝试下深度数据恢复的方法。它可以帮助我们找到更深层次的数据&#xff01; 一、恢复数据前的一些问题 很多人都会遇到数据丢失的…

windows环境下安装RocketMQ

文章目录前言一、下载二、环境变量配置三、启动RocketMq1.启动nameserver2.启动broker四、RocketMq控制台安装1.下载2.修改配置文件3.打包4.启动前言 环境要求&#xff1a;JDK1.8Maven 3.2x;64为操作系统 一、下载 官网下载地址&#xff1a;https://rocketmq.apache.org/zh/…

xxljob 的路由策略如何理解,他的选择逻辑是什么(小白阅读)

目录 1 需求2 路由策略2.1 第一个 FIRST2.2 最后一个 LAST2.3 ROUND 轮询2.4 RANDOM :随机2.5 CONSISTENT_HASH:一致性HASH2.6 LEAST_FREQUENTLY_USED:最不经常使用2.7 LEAST_RECENTLY_USED :最近最久未使用2.8 FAILOVER :故障转移2.9 BUSYOVER :忙碌转移1 需求 xxljob …

Ansible变量定义和使用

剧本中使用变量 在playbook中,可以直接定义变量,如下所示: vars&#xff1a;变量名变量值&#xff0c;也可以写在下一级将改成冒号空格值的形式 debug&#xff1a;debug模块&#xff0c;msg消息 引用变量&#xff1a;使用两对{{ }} vim juben.yml - hosts: allvars:bianliang…

extern关键字以及加了头文件引用的作用

0.前言 xdm&#xff0c;今天是阳了的第一天&#xff0c;昨天是高烧&#xff0c;浑身酸痛&#xff0c;今天好多了。。。祝大家健康。 推荐一首歌《不是因为寂寞才想你》。看了《阿凡达2》&#xff0c;感觉没第一部好看哎。 1.extern 之前写过一篇博客extern关键字。今天讲一下和…

fpga实操训练(ip ram和ip fifo)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 所有的fpga ip当中&#xff0c;用的最多的ip一般有pll、rom、ram和fifo。前面&#xff0c;我们讨论过了rom&#xff0c;rom相比较ram和fifo而言&am…

弹性盒子(flex)

一、什么是弹性盒子 弹性盒子是一种用于按行或按列布局元素的一维布局方法。元素可以膨胀以填充额外的空间&#xff0c;收缩以适应更小的空间。 二、flex 模型说明 主轴&#xff08;main axis&#xff09;&#xff1a; 是沿着 flex 元素放置的方向延伸的轴&#xff08;比如页…

【vue】关于vuex的一点补充

1.vuex的基本和下载 1.vuex是一种集中管理模式&#xff0c;举个详细一点的例子就是公共的数据&#xff0c;函数和计算属性&#xff0c;允许任何组件来使用&#xff0c;修改这里面的数据&#xff0c;vuex也可以成为store处理模式&#xff0c;其中一个store示例有state&#xff…

hadoop大数据入门HDFS、MapReduce、YARN的个人通俗理解

大数据时代,在数据量,计算量,计算时间上都是单机无法胜任的&#xff0c;通过简单的增强单机已经无法解决。普遍的解决方案为将多个单机组合起来进行存储和计算的分布式集群来处理。 Hadoop支持使用普通机器组成可拓展的分布式主从集群实现了对大数据的分布式存储&#xff08;HD…

SpringCloud之Hystrix服务熔断

Hystrix服务熔断1. 服务雪崩2. Hystrix 的概念3. Hystrix 的作用4. 服务熔断4.1 概念4.2 服务熔断解决哪些问题&#xff1f;4.3 案例5. 服务降级5.1 概念5.2 案例6. 服务熔断和降级的区别7. Dashboard 流监控分布式系统面临的问题复杂分布式体系结构中的应用程序有数十个依赖关…

At and Cron and Scheduling task

1.at 一次性任务 一次性使用&#xff0c;执行某条命令或者脚本&#xff0c;守护进程atd,默认安装以及开机启动。在输入完命令的时候&#xff0c;按CtrlD结束 now 5min 现在过后5分钟 teatime tomorrow 明天的下午茶时间-4点 noon 中午 5pm august 3 2016 2016年八月3号的下午5点…

linux平台下node cnpm的安装方法

linux node cnpm的安装方法&#xff1a;1、下载linux版的node&#xff0c;并放在“/home/node/”目录下 &#xff1b;2、打开linux解压缩下gz&#xff1b;3、回到根目录&#xff0c;建立软连接&#xff1b;4、通过“npm install -g cnpm --registryhttps://registry.npm.taobao…