UE3中Object和Actor的创建与销毁
创建Object
① 在uc脚本中使用new运算符来创建
/**********************************************************************************
outer : The value for the new object's Outer variable.
The default value is None, which means the object is created within the "transient package", a virtual package for runtime objects.
InName : The name for the new object.
flags : Specifies object flags for the new object.
class : The class to create an object of. No abstract object & No Actor.
**********************************************************************************/ new ( optional Object outer=none , optional String ObjName="" , optional int flags=0 ) class(template);
注1:outer记录当前object的创建者是谁
注2:new的实现在c++的UObject::execNew函数中
一些示例:
local TObject1 O1, O2, O3, O4; O1 = new class'TObject1';
O2 = new(self) class'TObject1'; // O2.Outer=self
O3 = new(none, "TObject1_xxx") class'TObject1'; // O3.Name="TObject1_xxx"
O4 = new(self, "", 0) class'TObject1';
② 在c++中使用StaticConstructObject函数来创建
/**
* Create a new instance of an object. The returned object will be fully initialized. If InFlags contains RF_NeedsLoad (indicating that the object still needs to load its object data from disk), components
* are not instanced (this will instead occur in PostLoad()). The different between StaticConstructObject and StaticAllocateObject is that StaticConstructObject will also call the class constructor on the object
* and instance any components.
*
* @param Class the class of the object to create
* @param InOuter the object to create this object within (the Outer property for the new object will be set to the value specified here).
* @param Name the name to give the new object. If no value (NAME_None) is specified, the object will be given a unique name in the form of ClassName_#.
* @param SetFlags the ObjectFlags to assign to the new object. some flags can affect the behavior of constructing the object.
* @param Template if specified, the property values from this object will be copied to the new object, and the new object's ObjectArchetype value will be set to this object.
* If NULL, the class default object is used instead.
* @param Error the output device to use for logging errors
* @param SubobjectRoot
* Only used to when duplicating or instancing objects; in a nested subobject chain, corresponds to the first object that is not a subobject.
* A value of INVALID_OBJECT for this parameter indicates that we are calling StaticConstructObject to duplicate or instance a non-subobject (which will be the subobject root for any subobjects of the new object)
* A value of NULL indicates that we are not instancing or duplicating an object.
* @param InstanceGraph
* contains the mappings of instanced objects and components to their templates
*
* @return a pointer to a fully initialized object of the specified class.
*/
UObject* UObject::StaticConstructObject
(
UClass* InClass,
UObject* InOuter /*=GetTransientPackage()*/,
FName InName /*=NAME_None*/,
EObjectFlags InFlags /*=0*/,
UObject* InTemplate /*=NULL*/,
FOutputDevice* Error /*=GError*/,
UObject* SubobjectRoot /*=NULL*/,
FObjectInstancingGraph* InInstanceGraph /*=NULL*/
)
{
// ... ... // Allocate the object.
UObject* Result = StaticAllocateObject( InClass, InOuter, InName, InFlags, InTemplate, Error, NULL, SubobjectRoot, InstanceGraph ); if( Result )
{
{
// call the base UObject class constructor if the class is misaligned (i.e. a native class that is currently being recompiled)
// 调用UObject::InternalConstructor,里面会使用placement new来构造UObject,使得其能调用UObject()无参构造函数来初始化
if ( !InClass->IsMisaligned() )
{
(*InClass->ClassConstructor)( Result );
}
else
{
(*UObject::StaticClass()->ClassConstructor)( Result );
}
} // ... ...
} // ... ... return Result;
}
销毁Object
GC系统检查当前Object对象是否被Root类型Object对象直接或间接引用,如果没有则会销毁该Object
当某个Root类型Object不再使用某个Object对象时,应及时将其设置成null,来防止因为被引用无法及时被GC回收
注1:在UWorld::Tick中GC系统会按照一定的时间间隔调用UWorld::PerformGarbageCollection()来开始查找并标记那些对象是垃圾(GCMark),被标记的的object对象会触发BeginDestroy()调用
时间间隔变量TimeBetweenPurgingPendingKillObjects可以在*Engine.ini的[Engine.Engine]标签中配置,缺省配置为60秒
注2:在Tick中调用UObject::IncrementalPurgeGarbage(TRUE)分帧来回收垃圾(GCSweep),在delete Object前还会触发FinishDestroy()调用
由于Object是个对象,delete Object等价于:
Object->~Object(); // ~Object是个虚析构函数,不同Object类型对象会先调用自己的析构函数,然后依次调父类的
operator delete(Object);
由于UObject实现了void operator delete( void* Object, size_t Size )成员函数,最后会调用UObject中的delete操作符重载函数
为了减少内存碎片和减少分配和回收内存开销,UE自己对UObject进行了内存管理,delete实际上不会真正地释放内存
注3:也可以通过执行obj gc来触发UObject::CollectGarbage( GARBAGE_COLLECTION_KEEPFLAGS )调用,来GCMark并GCSweep垃圾
注4:编辑器的GC引用分析逻辑在void FArchiveTagUsedNonRecursive::PerformReachabilityAnalysis( EObjectFlags KeepFlags )
游戏的在void FArchiveRealtimeGC::PerformReachabilityAnalysis( EObjectFlags KeepFlags )中
创建Actor
① 在uc脚本中使用Spawn函数来创建
' Spawn an actor. Returns an actor of the specified class, not of class Actor (this is hardcoded in the compiler).
' Returns None if the actor could not be spawned (if that happens, there will be a log warning indicating why) Defaults to spawning at the spawner's location.
'
' @note: ActorTemplate is sent for replicated actors and therefore its properties will also be applied at initial creation on the client.
' However, because of this, ActorTemplate must be a static resource (an actor archetype, default object, or a bStatic/bNoDelete actor in a level package) or the spawned Actor cannot be replicated native noexport final function coerce actor Spawn
(
class<actor> SpawnClass,
optional actor SpawnOwner,
optional name SpawnTag,
optional vector SpawnLocation,
optional rotator SpawnRotation,
optional Actor ActorTemplate,
optional bool bNoCollisionFail
);
一些示例:
local UTBot NewBot;
local Pawn NewPawn;
local class<HUD> NewHUDType;
local HUD NewHUD; NewBot = Spawn(class'UTBot');
NewPawn = Spawn(class'UTPawn',,,vect(10.0,20.0,0.0),rot(1234, 5678 , 9012)); NewHUDType = class'UTEntryHUD';
NewHUD = Spawn(NewHUDType, self); //self为当前controller对象
注:Spawn的实现在c++的AActor::execSpawn函数中
② 在cpp中使用SpawnActor函数来创建
// Create a new actor. Returns the new actor, or NULL if failure.
AActor* UWorld::SpawnActor
(
UClass* Class,
FName InName=NAME_None,
const FVector& Location=FVector(,,),
const FRotator& Rotation=FRotator(,,),
AActor* Template=NULL,
UBOOL bNoCollisionFail=,
UBOOL bRemoteOwned=,
AActor* Owner=NULL,
APawn* Instigator=NULL,
UBOOL bNoFail=
)
{
// 游戏世界WorldInfo是否创建完毕
const UBOOL bBegunPlay = HasBegunPlay(); FVector NewLocation = Location;
// 根据Actor类型的碰撞信息和碰撞体大小调整Actor的位置
if( (Template->bCollideWorld || (Template->bCollideWhenPlacing && (GetNetMode() != NM_Client))) && !bNoCollisionFail )
{
FindSpot(Template->GetCylinderExtent(), NewLocation, Template->bCollideComplex);
} // 创建Actor
ULevel* LevelToSpawnIn = Owner ? CastChecked<ULevel>(Owner->GetOuter()) : CurrentLevel;
AActor* Actor = ConstructObject<AActor>( Class, LevelToSpawnIn, InName, RF_Transactional, Template );
// 添加Actor到关卡中
LevelToSpawnIn->Actors.AddItem( Actor );
// 添加Actor到关卡的Tick列表中
if (Actor->WantsTick())
{
LevelToSpawnIn->TickableActors.AddItem(Actor);
} Actor->bTicked = !Ticked;
Actor->CreationTime = GetTimeSeconds();
Actor->WorldInfo = GetWorldInfo(); // Set the actor's location and rotation.
Actor->Location = NewLocation;
Actor->Rotation = Rotation; // Initialize the actor's components.
Actor->ConditionalForceUpdateComponents(FALSE,FALSE); // init actor's physics volume
Actor->PhysicsVolume = GetWorldInfo()->PhysicsVolume; // Set owner.
Actor->SetOwner( Owner ); // Set instigator
Actor->Instigator = Instigator; if (bBegunPlay)
{
Actor->InitRBPhys();
} Actor->InitExecution();
Actor->Spawned(); if(bBegunPlay)
{
Actor->PreBeginPlay();
{
eventPreBeginPlay(); // 调用uc脚本的event PreBeginPlay()事件回调函数 // ... ...
} for(INT ComponentIndex = ;ComponentIndex < Actor->Components.Num();ComponentIndex++)
{
if(Actor->Components(ComponentIndex))
{
Actor->Components(ComponentIndex)->ConditionalBeginPlay();
}
}
} // Check for encroachment.
if( !bNoCollisionFail )
{
CheckEncroachment( Actor, Actor->Location, Actor->Rotation, );
}
else if ( Actor->bCollideActors )
{
Actor->FindTouchingActors();
} if(bBegunPlay)
{
Actor->PostBeginPlay();
{
// Send PostBeginPlay.
eventPostBeginPlay();// 调用uc脚本的event PostBeginPlay()事件回调函数 // Init scripting.
eventSetInitialState(); // 调用uc脚本的event SetInitialState()函数 // Find Base
if( !Base && bCollideWorld && bShouldBaseAtStartup && ((Physics == PHYS_None) || (Physics == PHYS_Rotating)) )
{
FindBase();
}
}
} if( InTick )
{
NewlySpawned.AddItem( Actor );
} return Actor;
}
销毁Actor
Actor本质还是一个Object,其回收是通过GC完成的,显示调用uc的Destory和cpp中的DestroyActor只是去除Actor对象的所有引用,让其能被GC视为垃圾
① 在uc脚本中使用Destory函数来销毁
'Destroy this actor. Returns true if destroyed, false if indestructible.
'Destruction is latent. It occurs at the end of the tick.
native() final noexport function k2call bool Destroy();
② 在cpp中使用DestroyActor函数来销毁
/**
* Removes the actor from its level's actor list and generally cleans up the engine's internal state.
* What this function does not do, but is handled via garbage collection instead, is remove references
* to this actor from all other actors, and kill the actor's resources. This function is set up so that
* no problems occur even if the actor is being destroyed inside its recursion stack.
*
* @param ThisActor Actor to remove.
* @param bNetForce [opt] Ignored unless called during play. Default is FALSE.
* @param bShouldModifyLevel [opt] If TRUE, Modify() the level before removing the actor. Default is TRUE.
* @return TRUE if destroy, FALSE if actor couldn't be destroyed.
*/
UBOOL UWorld::DestroyActor(
AActor* ThisActor,
UBOOL bNetForce=FALSE,
UBOOL bShouldModifyLevel=TRUE
)
{
check(ThisActor);
check(ThisActor->IsValid()); ThisActor->bPendingDelete = true; // Terminate any physics engine stuff for this actor right away.
ThisActor->TermRBPhys(NULL);
// Tell this actor it's about to be destroyed.
ThisActor->eventDestroyed();// 调用uc脚本的event Destroyed()事件回调函数
ThisActor->PostScriptDestroyed();
// Remove from base.
if( ThisActor->Base )
{
ThisActor->SetBase( NULL );
} // Make a copy of the array, as calling SetBase might change the contents of the array.
TArray<AActor*> AttachedCopy = ThisActor->Attached;
for( INT AttachmentIndex=; AttachmentIndex < AttachedCopy.Num(); AttachmentIndex++ )
{
AActor* AttachedActor = AttachedCopy(AttachmentIndex);
if( AttachedActor && AttachedActor->Base == ThisActor && !AttachedActor->bDeleteMe )
{
AttachedActor->SetBase( NULL );
}
}
// Then empty the array.
ThisActor->Attached.Empty(); // Clean up all touching actors.
INT iTemp = ;
for ( INT i=; i<ThisActor->Touching.Num(); i++ )
{
if ( ThisActor->Touching(i) && ThisActor->Touching(i)->Touching.FindItem(ThisActor, iTemp) )
{
ThisActor->EndTouch( ThisActor->Touching(i), );
i--;
}
} // If this actor has an owner, notify it that it has lost a child.
if( ThisActor->Owner )
{
ThisActor->SetOwner(NULL);
}
// Notify net players that this guy has been destroyed.
if( NetDriver )
{
NetDriver->NotifyActorDestroyed( ThisActor );
} // Remove the actor from the actor list.
RemoveActor( ThisActor, bShouldModifyLevel ); // Mark the actor and its direct components as pending kill.
ThisActor->bDeleteMe = ;
ThisActor->MarkPackageDirty();
ThisActor->MarkComponentsAsPendingKill( TRUE ); // Clean up the actor's components.
ThisActor->ClearComponents(); // Return success.
return TRUE;
}
UE3中Object和Actor的创建与销毁的更多相关文章
- Android中如何区分界面组件创建和销毁的类型
本文主要描述: 1.分辨系统杀掉退出还是用户主动退出2.分辨全新的创建还是系统恢复性的创建 1.分辨系统杀掉退出还是用户主动退出 当一个组件失去焦点后,系统有可能为了释放资源而杀掉这个组件,这个时候系 ...
- Java中引用类型、对象的创建与销毁
引用类型 在java中,除了基本数据类型之外的,就是引用数据类型了,引用指的是对象的一个引用,通过引用可以操作对象,控制对象,向对象发送消息. 简单来说,引用可以访问对象的属性,并调用对象的方法 创建 ...
- UE3中的时间
为了管理时间,Unreal将游戏运行时间片分隔为"Ticks".一个Tick是关卡中所有Actors更新的最小时间单位.一个tick一般是10ms-100ms(CPU性能越好,游戏 ...
- python 中如何导入一个自己创建的模块
导入模块的语句的三种方法: 1.import module 2.from module import name1,[name2,name3....] 3.from module import * 先看 ...
- JavaScript中Object的总结
基于原型继承,动态对象扩展,闭包,JavaScript已经成为当今世界上最灵活和富有表现力的编程语言之一. 这里有一个很重要的概念需要特别指出:在JavaScript中,包括所有的函数,数组,键值对和 ...
- (转)es6中object.create()和object.assign()
今天学习javascript面向对象,在学习Obejct方法时了解到create方法,偶像想起之前使用的assign方法,顺带查找一番,感觉这篇博客讲解详细,遂转载. 先简单提一下装饰器函数,许多面向 ...
- Javascript中Object常用方法学习
1.Object.assign 函数(对象)(JavaScript) 将来自一个或多个源对象中的值复制到一个目标对象.语法: Object.assign(target, ...sources ); 此 ...
- js 中object对象的操作
n = object对象 for(var p in n){ console.log(p);// 取得是key值 console.log(n[p]);//取得是value值 } 继之前js中数组的常用方 ...
- Java中Object的方法
构造方法摘要Object() 方法摘要protected Object clone() 创建并返回此对象的一个副本.boolean equals(Object ...
随机推荐
- 锁开销优化以及 CAS 简单说明
锁开销优化以及 CAS 简单说明 锁 互斥锁是用来保护一个临界区,即保护一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性.当有线程进入临界区段时,其他线程或是进程必须等待. 在 ...
- vscode restclient 插件
使用步骤: 1.vscode 安装restclient 扩展 2.创建 .http 或 .rest 文件 ,编写相应内容 同一个文件内 可以通过 ### 分割多个请求 可以通过 @hostname ...
- 系统的讲解 - PHP 缓存技术
目录 概述 浏览器缓存 文件缓存 NoSQL缓存 WEB服务器缓存 Opcode缓存 小结 关于缓存的常见问题 概述 缓存已经成了项目中是必不可少的一部分,它是提高性能最好的方式,例如减少网络I/O. ...
- Hystix熔断解决雪崩问题
1.线程隔离,服务降级(服务的消费方做降级处理) 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果. 这就好比去买鱼,平常超市买鱼会 ...
- 关于ios的光标和键盘回弹问题
最近再做项目的时候(移动端),遇到了两个小问题,一个是ios端键盘不回弹的问题(微信浏览器),另一个是ios输入光标位置问题.首先看第二个问题: 就是点击一个按钮,要把输入框里面原来的内容加上一些固定 ...
- 虹软人脸识别ArcFace2.0 Android SDK使用教程
一.获取SDK 1.进入ArcFace2.0的申请地址 https://ai.arcsoft.com.cn/product/arcface.html 2.填写信息申请并提交 申请通过后即可下载SDK, ...
- Windows Server 2016-DNS 新增或改进功能
本章节补充介绍在 Windows Server 2016 中域名系统 (DNS) 服务器新增或已更改的功能相关信息,具体内容如下: 功能 新增或改进 描述 DNS 策略 新增 您可以配置 DNS 策略 ...
- pyquery 学习
pyquery 是python仿照jQuery的严格实现,语法与jQuery几乎完全相同,所以对于学过前端的朋友们可以立马上手,没学过的小朋友也别灰心,我们马上就能了解到pyquery的强大. 1 安 ...
- SUSE12SP3-Mycat(4)rule.xml配置详解
简介 rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义.我们可以灵活的对表使用不同的分片算法, 或者对表使用相同的算法但具体的参数不同.这个文件里面主要有 tableRule 和 fu ...
- 开发人员的必备工具Git(初级)
Git是什么 Git是目前世界上最先进的分布式版本控制系统. 这个软件用起来就应该像这个样子,能记录每次文件的改动: 举个栗子 : 版本 用户 说明 日期 1 张三 删除了软件服务条款5 ...