Actor的生成和GetDefaultObject

原文链接:http://orfeasel.com/actor-spawning/

Actor的生成和GetDefaultObject

有些时候我们需要在游戏运行时生成基于C++类的actor。另外,我们还需要了解函数GetDefaultObject的作用以及我们为什么应该了解它!让我们开始吧!

Actor的生成

在本文中我们将创建两个Actor。一个包含一些基础的逻辑(我们将这个Actor命名为UsefulActor),而另一个会在一段时间后生成UsefulActor。我们第一步先添加一个新的C++类(基于actor类),命名为UsefulActor然后在它的头文件中加入以下逻辑:

1.	void DoSomething()
2.	{
3.	    GLog->Log("UsefulActor does something...");
4.	}

切换到你的编辑器,创建一个基于此类的蓝图,命名为BP_UsefulActor。记得要在你的蓝图中添加一个静态网格物体,这样当你的actor生成的时候你可以看见它。

设置完UsefulActor后,添加另一个名为ActorSpawner的C++类(它也继承自actor类)。在它的头文件中,包含UsefulActor.h然后加入以下代码:

1.	/*Blueprint Reference of UsefulActor class*/
2.	UPROPERTY(EditDefaultsOnly,Category="ActorSpawning")
3.	TSubclassOf<AUsefulActor> UsefulActorBP;
4.	 
5.	/*Delay after the Blueprint of the UsefulActor will get spawned*/
6.	UPROPERTY(EditDefaultsOnly, Category = "ActorSpawning")
7.	float TimeToSpawn = 2.f;
8.	 
9.	/*Spawns the UsefulActor Blueprint*/
10.	UFUNCTION()
11.	void SpawnUsefulActor();

TSubclassOf意味着该性质可以接受任何AUsefulActor类型的对象。由于我们制作了一个基于此类的蓝图,我们可以将蓝图作为该性质中的一个参数。

记得要在ActorSpawner.generated.h之前包含“UsefulActor.h”。否则你的项目不会成功编译。
切换到ActorSpawner.cpp文件然后添加以下功能:

1.	void AActorSpawner::BeginPlay()
2.	{
3.	    Super::BeginPlay();
4.	 
5.	    FTimerHandle OutHandle;
6.	 
7.	    //Will call SpawnUsefulActor after the specified time
8.	    GetWorld()->GetTimerManager().SetTimer(OutHandle, this, &AActorSpawner::SpawnUsefulActor, TimeToSpawn);
9.	   
10.	}
11.	void AActorSpawner::SpawnUsefulActor()
12.	{
13.	    //If the usefulactorbp is valid
14.	    if(UsefulActorBP)
15.	    {
16.	        //Spawn parameters for the current spawn.
17.	        //We can use this for a number of options like disable collision or adjust the spawn position
18.	        //if a collision is happening in the spawn point etc..
19.	        FActorSpawnParameters SpawnParams;
20.	 
21.	        //Actual Spawn. The following function returns a reference to the spawned actor
22.	        AUsefulActor* ActorRef = GetWorld()->SpawnActor<AUsefulActor>(UsefulActorBP, GetTransform(), SpawnParams);
23.	 
24.	        GLog->Log("Spawned the UsefulActor.");
25.	    }
26.	}

编译你的代码然后创建一个基于ActorSpawner类的蓝图。然后打开它,在UsefulActorBP性质中选择BP_UsefulActor,不要选择UsefulActor类,如下图所示:

设置完成后,将ActorSpawner蓝图放置在你的关卡的某处然后点击播放/模拟按钮。BP_UsefulActor应该在蓝图中设置的 “Time To Spawn” 秒后生成。

Epic的API提供了一些有用的SpawnActor函数的重载,你可以在这里找到它们。

我们在UsefulActorBP性质中选择蓝图类而不是C++类的原因是我们想要生成蓝图而不是C++类。尽管我们的蓝图是基于C++类的,但我们将一些特定的数值存储在了蓝图中而不是在C++中,比如我们上文添加的静态网格物体。在实际项目中也有可能遇到这种情况。大部分情况下,你要创建一个基于C++类(其中包含一些自定义的性质)的actor。然后,切换到你的编辑器并为这些性质赋值。这样当你想要生成拥有所有设置好性质的actor时你应该选择蓝图版本的而不是C++类的。

GetDefaultObject

在前面例子中,当我们生成一个新的actor时我们储存了一个指针的引用。假设我们忘记储存该引用,后来我们想要使用AUsefulActor类中的DoSomething函数。也许你认为这很简单。由于我们储存了UsefulActorBP,我们只需使用它调用DoSomething函数。但是当你键入以下代码后:

UsefulActorBP->DoSomething();

你的代码不能正确编译。你会得到以下错误:

在这里插入图片描述
嗯,这就怪了!虽然TSubclassOf接受任何AUsefulActor的派生类,但是我们不能使用任何C++函数。这里就要用到GetDefaultObject了。该函数会得到我们上面使用的子类(其中含有C++函数)的父类。所以以下代码将正确编译和执行:

UsefulActorBP->GetDefaultObject<AUsefulActor>()->DoSomething();

另一种取得AUsefulActor的C++函数的使用权限的方法是将蓝图转换成它的父类。但是类型转换在性能方面通常需要很大的开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值