创建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的创建与销毁的更多相关文章

  1. Android中如何区分界面组件创建和销毁的类型

    本文主要描述: 1.分辨系统杀掉退出还是用户主动退出2.分辨全新的创建还是系统恢复性的创建 1.分辨系统杀掉退出还是用户主动退出 当一个组件失去焦点后,系统有可能为了释放资源而杀掉这个组件,这个时候系 ...

  2. Java中引用类型、对象的创建与销毁

    引用类型 在java中,除了基本数据类型之外的,就是引用数据类型了,引用指的是对象的一个引用,通过引用可以操作对象,控制对象,向对象发送消息. 简单来说,引用可以访问对象的属性,并调用对象的方法 创建 ...

  3. UE3中的时间

    为了管理时间,Unreal将游戏运行时间片分隔为"Ticks".一个Tick是关卡中所有Actors更新的最小时间单位.一个tick一般是10ms-100ms(CPU性能越好,游戏 ...

  4. python 中如何导入一个自己创建的模块

    导入模块的语句的三种方法: 1.import module 2.from module import name1,[name2,name3....] 3.from module import * 先看 ...

  5. JavaScript中Object的总结

    基于原型继承,动态对象扩展,闭包,JavaScript已经成为当今世界上最灵活和富有表现力的编程语言之一. 这里有一个很重要的概念需要特别指出:在JavaScript中,包括所有的函数,数组,键值对和 ...

  6. (转)es6中object.create()和object.assign()

    今天学习javascript面向对象,在学习Obejct方法时了解到create方法,偶像想起之前使用的assign方法,顺带查找一番,感觉这篇博客讲解详细,遂转载. 先简单提一下装饰器函数,许多面向 ...

  7. Javascript中Object常用方法学习

    1.Object.assign 函数(对象)(JavaScript) 将来自一个或多个源对象中的值复制到一个目标对象.语法: Object.assign(target, ...sources ); 此 ...

  8. js 中object对象的操作

    n = object对象 for(var p in n){ console.log(p);// 取得是key值 console.log(n[p]);//取得是value值 } 继之前js中数组的常用方 ...

  9. Java中Object的方法

    构造方法摘要Object()           方法摘要protected Object clone()           创建并返回此对象的一个副本.boolean equals(Object ...

随机推荐

  1. 玩转Spring Cloud之服务注册发现(eureka)及负载均衡消费(ribbon、feign)

    如果说用Spring Boot+Spring MVC是开发单体应用(或单体服务)的利器,那么Spring Boot+Spring MVC+Spring Cloud将是开发分布式应用(快速构建微服务)的 ...

  2. iOS----------学习路线思维导图

    UI相关 Runtime OC特性 内存管理 Block 多线程 Runloop 网络相关 设计模式 架构 算法 第三方库

  3. Android之Realm详解

    文章大纲 一.Realm介绍二.Realm实战三.Realm官方文档四.项目源码下载五.参考文章   一.Realm介绍 1. 什么是Realm   Realm 是一个手机数据库,是用来替代 SQli ...

  4. Flutter 即学即用系列博客——01 环境搭建

    前言 工欲善其事,必先利其器 所以第一篇我们来说说 Flutter 环境的搭建. 笔者这边使用的是 MAC 电脑,因此以 MAC 电脑的环境搭建为例. Windows 或者 Linux 也是类似的操作 ...

  5. git使用笔记1:结合Github远程仓库管理项目

    git是一个十分好用的版本控制工具,我们经常在本地使用git进行项目开发,Git 并不像 SVN 那样有个中心服务器,如果想要通过 Git 分享你的代码或者与其他开发人员合作,就需要将数据放到一台其他 ...

  6. MongDB集群容灾方案步骤

    MongoDB复制集优/特点支持大数据量.高扩展性.高性能.灵活数据模型.高可用性.同步机制数据复制的目的是使数据得到最大的可用性,避免单点故障引起的整站不能访问的情况的发生,Mongodb的副本集在 ...

  7. (一)初识Redis

    1.redis简介 Redis是一个速度非常快的key-value非关系型存储数据库,可以存储5种形态的键值对,可以将存储在内存中的键值对持久化到硬盘,可以使用复制特性扩展读性能,还可以使用客户端分片 ...

  8. win10彻底禁用自动更新,win10怎样彻底关闭自动更新,永久关闭win10自动更新,win10更新助手

    首先,请广大win10受害者原谅小菜用一个如此长的标题来吸引你们,为了尽最大努力帮助那些饱受win10自动更新折磨的朋友们,小菜不得已出此下策,望见谅! windows 10是一个神奇的操作系统,当你 ...

  9. Storm入门(十)Twitter Storm: Transactional Topolgoy简介

    作者: xumingming | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://xumingming.sinaapp.com/736/twitter-stor ...

  10. kafka的设计

    1.动机 设计 kafka 初衷,作为统一平台处理大公司的实时数据.所以 必须具有如下特性: 支持海量数据 高吞吐量 低延迟(实时性) 支持分区,分布式 容错 2.持久化 kafka 高度依赖 文件系 ...