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 ...
随机推荐
- 玩转Spring Cloud之服务注册发现(eureka)及负载均衡消费(ribbon、feign)
如果说用Spring Boot+Spring MVC是开发单体应用(或单体服务)的利器,那么Spring Boot+Spring MVC+Spring Cloud将是开发分布式应用(快速构建微服务)的 ...
- iOS----------学习路线思维导图
UI相关 Runtime OC特性 内存管理 Block 多线程 Runloop 网络相关 设计模式 架构 算法 第三方库
- Android之Realm详解
文章大纲 一.Realm介绍二.Realm实战三.Realm官方文档四.项目源码下载五.参考文章 一.Realm介绍 1. 什么是Realm Realm 是一个手机数据库,是用来替代 SQli ...
- Flutter 即学即用系列博客——01 环境搭建
前言 工欲善其事,必先利其器 所以第一篇我们来说说 Flutter 环境的搭建. 笔者这边使用的是 MAC 电脑,因此以 MAC 电脑的环境搭建为例. Windows 或者 Linux 也是类似的操作 ...
- git使用笔记1:结合Github远程仓库管理项目
git是一个十分好用的版本控制工具,我们经常在本地使用git进行项目开发,Git 并不像 SVN 那样有个中心服务器,如果想要通过 Git 分享你的代码或者与其他开发人员合作,就需要将数据放到一台其他 ...
- MongDB集群容灾方案步骤
MongoDB复制集优/特点支持大数据量.高扩展性.高性能.灵活数据模型.高可用性.同步机制数据复制的目的是使数据得到最大的可用性,避免单点故障引起的整站不能访问的情况的发生,Mongodb的副本集在 ...
- (一)初识Redis
1.redis简介 Redis是一个速度非常快的key-value非关系型存储数据库,可以存储5种形态的键值对,可以将存储在内存中的键值对持久化到硬盘,可以使用复制特性扩展读性能,还可以使用客户端分片 ...
- win10彻底禁用自动更新,win10怎样彻底关闭自动更新,永久关闭win10自动更新,win10更新助手
首先,请广大win10受害者原谅小菜用一个如此长的标题来吸引你们,为了尽最大努力帮助那些饱受win10自动更新折磨的朋友们,小菜不得已出此下策,望见谅! windows 10是一个神奇的操作系统,当你 ...
- Storm入门(十)Twitter Storm: Transactional Topolgoy简介
作者: xumingming | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://xumingming.sinaapp.com/736/twitter-stor ...
- kafka的设计
1.动机 设计 kafka 初衷,作为统一平台处理大公司的实时数据.所以 必须具有如下特性: 支持海量数据 高吞吐量 低延迟(实时性) 支持分区,分布式 容错 2.持久化 kafka 高度依赖 文件系 ...