void UChildActorComponent::CreateChildActor() { // Kill spawned actor if we have one DestroyChildActor(); // This is no longer needed if (CachedInstanceData) { delete CachedInstanceData; CachedInstanceData = nullptr; } // If we have a class to spawn. if(ChildActorClass != nullptr) { UWorld* World = GetWorld(); if(World != nullptr) { // Before we spawn let's try and prevent cyclic disaster bool bSpawn = true; AActor* Actor = GetOwner(); while (Actor && bSpawn) { if (Actor->GetClass() == ChildActorClass) { bSpawn = false; UE_LOG(LogChildActorComponent, Error, TEXT("Found cycle in child actor component '%s'. Not spawning Actor of class '%s' to break."), *GetPathName(), *ChildActorClass->GetName()); } Actor = Actor->ParentComponentActor.Get(); } if (bSpawn) { FActorSpawnParameters Params; Params.bNoCollisionFail = true; Params.bDeferConstruction = true; // We defer construction so that we set ParentComponentActor prior to component registration so they appear selected Params.bAllowDuringConstructionScript = true; Params.OverrideLevel = GetOwner()->GetLevel(); Params.Name = ChildActorName; if (!HasAllFlags(RF_Transactional)) { Params.ObjectFlags &= ~RF_Transactional; } // Spawn actor of desired class FVector Location = GetComponentLocation(); FRotator Rotation = GetComponentRotation(); ChildActor = World->SpawnActor(ChildActorClass, &Location, &Rotation, Params); // If spawn was successful, if(ChildActor != nullptr) { ChildActorName = ChildActor->GetFName(); // Remember which actor spawned it (for selection in editor etc) ChildActor->ParentComponentActor = GetOwner(); ChildActor->AttachRootComponentTo(this); // Parts that we deferred from SpawnActor ChildActor->FinishSpawning(ComponentToWorld); } } } } }
void FBlueprintCompileReinstancer::ReplaceInstancesOfClass(UClass* OldClass, UClass* NewClass, UObject* OriginalCDO, TSet<UObject*>* ObjectsThatShouldUseOldStuff) { USelection* SelectedActors; bool bSelectionChanged = false; TArray<UObject*> ObjectsToReplace; const bool bLogConversions = false; // for debugging // Map of old objects to new objects TMap<UObject*, UObject*> OldToNewInstanceMap; TMap<UClass*, UClass*> OldToNewClassMap; OldToNewClassMap.Add(OldClass, NewClass); TMap<FStringAssetReference, UObject*> ReinstancedObjectsWeakReferenceMap; // actors being replace TArray<FActorReplacementHelper> ReplacementActors; // A list of objects (e.g. Blueprints) that potentially have editors open that we need to refresh TArray<UObject*> PotentialEditorsForRefreshing; // A list of component owners that need their construction scripts re-ran (because a component of theirs has been reinstanced) TSet<AActor*> OwnersToReconstruct; // Set global flag to let system know we are reconstructing blueprint instances TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true); struct FObjectRemappingHelper { void OnObjectsReplaced(const TMap<UObject*, UObject*>& InReplacedObjects) { ReplacedObjects.Append(InReplacedObjects); } TMap<UObject*, UObject*> ReplacedObjects; } ObjectRemappingHelper; FDelegateHandle OnObjectsReplacedHandle = GEditor->OnObjectsReplaced().AddRaw(&ObjectRemappingHelper,&FObjectRemappingHelper::OnObjectsReplaced); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplaceInstancesOfClass); const bool bIncludeDerivedClasses = false; GetObjectsOfClass(OldClass, ObjectsToReplace, bIncludeDerivedClasses); SelectedActors = GEditor->GetSelectedActors(); SelectedActors->BeginBatchSelectOperation(); SelectedActors->Modify(); // Then fix 'real' (non archetype) instances of the class for (UObject* OldObject : ObjectsToReplace) { // Skip non-archetype instances, EXCEPT for component templates const bool bIsComponent = NewClass->IsChildOf(UActorComponent::StaticClass()); if ((!bIsComponent && OldObject->IsTemplate()) || OldObject->IsPendingKill()) { continue; } UBlueprint* CorrespondingBlueprint = Cast<UBlueprint>(OldObject->GetClass()->ClassGeneratedBy); UObject* OldBlueprintDebugObject = nullptr; // If this object is being debugged, cache it off so we can preserve the 'object being debugged' association if ((CorrespondingBlueprint != nullptr) && (CorrespondingBlueprint->GetObjectBeingDebugged() == OldObject)) { OldBlueprintDebugObject = OldObject; } AActor* OldActor = Cast<AActor>(OldObject); UObject* NewUObject = nullptr; // if the object to replace is an actor... if (OldActor != nullptr) { FVector Location = FVector::ZeroVector; FRotator Rotation = FRotator::ZeroRotator; if (USceneComponent* OldRootComponent = OldActor->GetRootComponent()) { Location = OldActor->GetActorLocation(); Rotation = OldActor->GetActorRotation(); } // If this actor was spawned from an Archetype, we spawn the new actor from the new version of that archetype UObject* OldArchetype = OldActor->GetArchetype(); UWorld* World = OldActor->GetWorld(); AActor* NewArchetype = Cast<AActor>(OldToNewInstanceMap.FindRef(OldArchetype)); // Check that either this was an instance of the class directly, or we found a new archetype for it check(OldArchetype == OldClass->GetDefaultObject() || NewArchetype); // Spawn the new actor instance, in the same level as the original, but deferring running the construction script until we have transferred modified properties ULevel* ActorLevel = OldActor->GetLevel(); UClass** MappedClass = OldToNewClassMap.Find(OldActor->GetClass()); UClass* SpawnClass = MappedClass ? *MappedClass : NewClass; FActorSpawnParameters SpawnInfo; SpawnInfo.OverrideLevel = ActorLevel; SpawnInfo.Template = NewArchetype; SpawnInfo.bNoCollisionFail = true; SpawnInfo.bDeferConstruction = true; // Temporarily remove the deprecated flag so we can respawn the Blueprint in the level const bool bIsClassDeprecated = SpawnClass->HasAnyClassFlags(CLASS_Deprecated); SpawnClass->ClassFlags &= ~CLASS_Deprecated; AActor* NewActor = World->SpawnActor(SpawnClass, &Location, &Rotation, SpawnInfo); // Reassign the deprecated flag if it was previously assigned if (bIsClassDeprecated) { SpawnClass->ClassFlags |= CLASS_Deprecated; } check(NewActor != nullptr); NewUObject = NewActor; // store the new actor for the second pass (NOTE: this detaches // OldActor from all child/parent attachments) // // running the NewActor's construction-script is saved for that // second pass (because the construction-script may reference // another instance that hasn't been replaced yet). ReplacementActors.Add(FActorReplacementHelper(NewActor, OldActor)); ReinstancedObjectsWeakReferenceMap.Add(OldObject, NewUObject); OldActor->DestroyConstructedComponents(); // don't want to serialize components from the old actor // Unregister native components so we don't copy any sub-components they generate for themselves (like UCameraComponent does) OldActor->UnregisterAllComponents(); // Unregister any native components, might have cached state based on properties we are going to overwrite NewActor->UnregisterAllComponents(); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldActor, NewActor); // reset properties/streams NewActor->ResetPropertiesForConstruction(); // register native components NewActor->RegisterAllComponents(); // // clean up the old actor (unselect it, remove it from the world, etc.)... if (OldActor->IsSelected()) { GEditor->SelectActor(OldActor, /*bInSelected =*/false, /*bNotify =*/false); bSelectionChanged = true; } if (GEditor->Layers.IsValid()) // ensure(NULL != GEditor->Layers) ?? While cooking the Layers is NULL. { GEditor->Layers->DisassociateActorFromLayers(OldActor); } World->EditorDestroyActor(OldActor, /*bShouldModifyLevel =*/true); OldToNewInstanceMap.Add(OldActor, NewActor); } else { FName OldName(OldObject->GetFName()); OldObject->Rename(NULL, OldObject->GetOuter(), REN_DoNotDirty | REN_DontCreateRedirectors); NewUObject = NewObject<UObject>(OldObject->GetOuter(), NewClass, OldName); check(NewUObject != nullptr); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldObject, NewUObject); if (UAnimInstance* AnimTree = Cast<UAnimInstance>(NewUObject)) { // Initialising the anim instance isn't enough to correctly set up the skeletal mesh again in a // paused world, need to initialise the skeletal mesh component that contains the anim instance. if (USkeletalMeshComponent* SkelComponent = Cast<USkeletalMeshComponent>(AnimTree->GetOuter())) { SkelComponent->InitAnim(true); } } OldObject->RemoveFromRoot(); OldObject->MarkPendingKill(); OldToNewInstanceMap.Add(OldObject, NewUObject); if (bIsComponent) { UActorComponent* Component = Cast<UActorComponent>(NewUObject); AActor* OwningActor = Component->GetOwner(); if (OwningActor) { OwningActor->ResetOwnedComponents(); // Check to see if they have an editor that potentially needs to be refreshed if (OwningActor->GetClass()->ClassGeneratedBy) { PotentialEditorsForRefreshing.AddUnique(OwningActor->GetClass()->ClassGeneratedBy); } // we need to keep track of actor instances that need // their construction scripts re-ran (since we've just // replaced a component they own) OwnersToReconstruct.Add(OwningActor); } } } // If this original object came from a blueprint and it was in the selected debug set, change the debugging to the new object. if ((CorrespondingBlueprint) && (OldBlueprintDebugObject) && (NewUObject)) { CorrespondingBlueprint->SetObjectBeingDebugged(NewUObject); } if (bLogConversions) { UE_LOG(LogBlueprint, Log, TEXT("Converted instance '%s' to '%s'"), *OldObject->GetPathName(), *NewUObject->GetPathName()); } } } GEditor->OnObjectsReplaced().Remove(OnObjectsReplacedHandle); // Now replace any pointers to the old archetypes/instances with pointers to the new one TArray<UObject*> SourceObjects; TArray<UObject*> DstObjects; OldToNewInstanceMap.GenerateKeyArray(SourceObjects); OldToNewInstanceMap.GenerateValueArray(DstObjects); // Also look for references in new spawned objects. SourceObjects.Append(DstObjects); FReplaceReferenceHelper::IncludeCDO(OldClass, NewClass, OldToNewInstanceMap, SourceObjects, OriginalCDO); FReplaceReferenceHelper::FindAndReplaceReferences(SourceObjects, ObjectsThatShouldUseOldStuff, ObjectsToReplace, OldToNewInstanceMap, ReinstancedObjectsWeakReferenceMap); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplacementConstruction); // the process of setting up new replacement actors is split into two // steps (this here, is the second)... // // the "finalization" here runs the replacement actor's construction- // script and is left until late to account for a scenario where the // construction-script attempts to modify another instance of the // same class... if this were to happen above, in the ObjectsToReplace // loop, then accessing that other instance would cause an assert in // UProperty::ContainerPtrToValuePtrInternal() (which appropriatly // complains that the other instance's type doesn't match because it // hasn't been replaced yet... that's why we wait until after // FArchiveReplaceObjectRef to run construction-scripts). for (FActorReplacementHelper& ReplacementActor : ReplacementActors) { ReplacementActor.Finalize(ObjectRemappingHelper.ReplacedObjects); } } SelectedActors->EndBatchSelectOperation(); if (bSelectionChanged) { GEditor->NoteSelectionChange(); } if (GEditor) { // Refresh any editors for objects that we've updated components for for (auto BlueprintAsset : PotentialEditorsForRefreshing) { FBlueprintEditor* BlueprintEditor = static_cast<FBlueprintEditor*>(FAssetEditorManager::Get().FindEditorForAsset(BlueprintAsset, /*bFocusIfOpen =*/false)); if (BlueprintEditor) { BlueprintEditor->RefreshEditors(); } } } // in the case where we're replacing component instances, we need to make // sure to re-run their owner's construction scripts for (AActor* ActorInstance : OwnersToReconstruct) { ActorInstance->RerunConstructionScripts(); } }
PyObject *py_ue_actor_spawn(ue_PyUObject * self, PyObject * args, PyObject *kwargs) { ue_py_check(self); PyObject *py_class; PyObject *py_obj_location = nullptr; PyObject *py_obj_rotation = nullptr; if (!PyArg_ParseTuple(args, "O|OO:actor_spawn", &py_class, &py_obj_location, &py_obj_rotation)) { return nullptr; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); UClass *u_class = ue_py_check_type<UClass>(py_class); if (!u_class) return PyErr_Format(PyExc_Exception, "argument is not a UClass"); if (!u_class->IsChildOf<AActor>()) { return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from AActor"); } FVector location = FVector(0, 0, 0); FRotator rotation = FRotator(0, 0, 0); if (py_obj_location) { ue_PyFVector *py_location = py_ue_is_fvector(py_obj_location); if (!py_location) return PyErr_Format(PyExc_Exception, "location must be an FVector"); location = py_location->vec; } if (py_obj_rotation) { ue_PyFRotator *py_rotation = py_ue_is_frotator(py_obj_rotation); if (!py_rotation) return PyErr_Format(PyExc_Exception, "location must be an FRotator"); rotation = py_rotation->rot; } if (kwargs && PyDict_Size(kwargs) > 0) { FTransform transform; transform.SetTranslation(location); transform.SetRotation(rotation.Quaternion()); AActor *actor = world->SpawnActorDeferred<AActor>(u_class, transform); if (!actor) return PyErr_Format(PyExc_Exception, "unable to spawn a new Actor"); ue_PyUObject *py_actor = ue_get_python_uobject_inc(actor); if (!py_actor) return PyErr_Format(PyExc_Exception, "uobject is in invalid state"); PyObject *py_iter = PyObject_GetIter(kwargs); while (PyObject *py_key = PyIter_Next(py_iter)) { PyObject *void_ret = py_ue_set_property(py_actor, Py_BuildValue("OO", py_key, PyDict_GetItem(kwargs, py_key))); if (!void_ret) { Py_DECREF(py_iter); return PyErr_Format(PyExc_Exception, "unable to set property for new Actor"); } } Py_DECREF(py_iter); UGameplayStatics::FinishSpawningActor(actor, transform); return (PyObject *)py_actor; } AActor *actor = world->SpawnActor(u_class, &location, &rotation); if (!actor) return PyErr_Format(PyExc_Exception, "unable to spawn a new Actor"); Py_RETURN_UOBJECT(actor); }
void UChildActorComponent::CreateChildActor() { // Kill spawned actor if we have one DestroyChildActor(); // If we have a class to spawn. if(ChildActorClass != nullptr) { UWorld* World = GetWorld(); if(World != nullptr) { // Before we spawn let's try and prevent cyclic disaster bool bSpawn = true; AActor* MyOwner = GetOwner(); AActor* Actor = MyOwner; while (Actor && bSpawn) { if (Actor->GetClass() == ChildActorClass) { bSpawn = false; UE_LOG(LogChildActorComponent, Error, TEXT("Found cycle in child actor component '%s'. Not spawning Actor of class '%s' to break."), *GetPathName(), *ChildActorClass->GetName()); } if (UChildActorComponent* ParentComponent = Actor->GetParentComponent()) { Actor = ParentComponent->GetOwner(); } else { Actor = nullptr; } } if (bSpawn) { FActorSpawnParameters Params; Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; Params.bDeferConstruction = true; // We defer construction so that we set ParentComponent prior to component registration so they appear selected Params.bAllowDuringConstructionScript = true; Params.OverrideLevel = (MyOwner ? MyOwner->GetLevel() : nullptr); Params.Name = ChildActorName; if (!HasAllFlags(RF_Transactional)) { Params.ObjectFlags &= ~RF_Transactional; } // Spawn actor of desired class FVector Location = GetComponentLocation(); FRotator Rotation = GetComponentRotation(); ChildActor = World->SpawnActor(ChildActorClass, &Location, &Rotation, Params); // If spawn was successful, if(ChildActor != nullptr) { ChildActorName = ChildActor->GetFName(); // Remember which component spawned it (for selection in editor etc) FActorParentComponentSetter::Set(ChildActor, this); // Parts that we deferred from SpawnActor const FComponentInstanceDataCache* ComponentInstanceData = (CachedInstanceData ? CachedInstanceData->ComponentInstanceData : nullptr); ChildActor->FinishSpawning(ComponentToWorld, false, ComponentInstanceData); ChildActor->AttachRootComponentTo(this, NAME_None, EAttachLocation::SnapToTarget); } } } } // This is no longer needed if (CachedInstanceData) { delete CachedInstanceData; CachedInstanceData = nullptr; } }
void UActorAnimationPlayer::SpawnActorsForMovie(TSharedRef<FMovieSceneSequenceInstance> MovieSceneInstance) { UWorld* WorldPtr = World.Get(); if (WorldPtr == nullptr) { return; } UMovieScene* MovieScene = MovieSceneInstance->GetSequence()->GetMovieScene(); if (MovieScene == nullptr) { return; } TArray<FSpawnedActorInfo>* FoundSpawnedActors = InstanceToSpawnedActorMap.Find(MovieSceneInstance); if (FoundSpawnedActors != nullptr) { // Remove existing spawned actors for this movie DestroyActorsForMovie( MovieSceneInstance ); } TArray<FSpawnedActorInfo>& SpawnedActorList = InstanceToSpawnedActorMap.Add(MovieSceneInstance, TArray<FSpawnedActorInfo>()); for (auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex) { auto& Spawnable = MovieScene->GetSpawnable(SpawnableIndex); UClass* GeneratedClass = Spawnable.GetClass(); if ((GeneratedClass == nullptr) || !GeneratedClass->IsChildOf(AActor::StaticClass())) { continue; } AActor* ActorCDO = CastChecked<AActor>(GeneratedClass->ClassDefaultObject); const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation; const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation; FActorSpawnParameters SpawnInfo; { SpawnInfo.ObjectFlags = RF_NoFlags; } AActor* NewActor = WorldPtr->SpawnActor(GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo); if (NewActor) { // Actor was spawned OK! FSpawnedActorInfo NewInfo; { NewInfo.RuntimeGuid = Spawnable.GetGuid(); NewInfo.SpawnedActor = NewActor; } SpawnedActorList.Add(NewInfo); } } }
PyObject *py_ue_actor_spawn(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_obj_location = nullptr; PyObject *py_obj_rotation = nullptr; UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); PyObject *obj; if (!PyArg_ParseTuple(args, "O|OO:actor_spawn", &obj, &py_obj_location, &py_obj_rotation)) { return NULL; } if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<UClass>()) { return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from AActor"); } UClass *u_class = (UClass *)py_obj->ue_object; if (!u_class->IsChildOf<AActor>()) { return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from AActor"); } FVector location = FVector(0, 0, 0); FRotator rotation = FRotator(0, 0, 0); if (py_obj_location) { ue_PyFVector *py_location = py_ue_is_fvector(py_obj_location); if (!py_location) return PyErr_Format(PyExc_Exception, "location must be an FVector"); location = py_location->vec; } if (py_obj_rotation) { ue_PyFRotator *py_rotation = py_ue_is_frotator(py_obj_rotation); if (!py_rotation) return PyErr_Format(PyExc_Exception, "location must be an FRotator"); rotation = py_rotation->rot; } AActor *actor = world->SpawnActor((UClass *)py_obj->ue_object, &location, &rotation); PyObject *ret = (PyObject *)ue_get_python_wrapper(actor); if (!ret) return PyErr_Format(PyExc_Exception, "uobject is in invalid state"); Py_INCREF(ret); return ret; }
ATile* ATileManager::SpawnTileAtLocation(FVector Location) { UWorld* World = GetWorld(); ATile* NewTile = (ATile*)World->SpawnActor(TileClass, &Location); NewTile->SetWidthAndHeight(TileWidth, TileHeight); Tiles.Add(NewTile); return NewTile; }
ATown* ATileManager::SpawnTownAtTile(ATile* Tile) { UWorld* World = GetWorld(); FVector Loc = Tile->GetActorLocation(); ATown* NewTown = (ATown*)World->SpawnActor(TownClass, &Loc); TilesWithTowns.Add(Tile); return NewTown; }
void URuntimeMovieScenePlayer::SpawnActorsForMovie( TSharedRef<FMovieSceneInstance> MovieSceneInstance ) { UWorld* WorldPtr = World.Get(); if( WorldPtr != NULL && MovieSceneBindings != NULL ) { UMovieScene* MovieScene = MovieSceneInstance->GetMovieScene(); if( MovieScene != NULL ) { TArray<FSpawnedActorInfo>* FoundSpawnedActors = InstanceToSpawnedActorMap.Find( MovieSceneInstance ); if( FoundSpawnedActors ) { // Remove existing spawned actors for this movie DestroyActorsForMovie( MovieSceneInstance ); } TArray<FSpawnedActorInfo>& SpawnedActorList = InstanceToSpawnedActorMap.Add( MovieSceneInstance, TArray<FSpawnedActorInfo>() ); for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex ) { auto& Spawnable = MovieScene->GetSpawnable( SpawnableIndex ); UClass* GeneratedClass = Spawnable.GetClass(); if ( GeneratedClass != NULL ) { const bool bIsActorBlueprint = GeneratedClass->IsChildOf( AActor::StaticClass() ); if ( bIsActorBlueprint ) { AActor* ActorCDO = CastChecked< AActor >( GeneratedClass->ClassDefaultObject ); const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation; const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation; FActorSpawnParameters SpawnInfo; SpawnInfo.ObjectFlags = RF_NoFlags; AActor* NewActor = WorldPtr->SpawnActor( GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo ); if( NewActor ) { // Actor was spawned OK! FSpawnedActorInfo NewInfo; NewInfo.RuntimeGuid = Spawnable.GetGuid(); NewInfo.SpawnedActor = NewActor; SpawnedActorList.Add( NewInfo ); } } } } } } }
AMeshWallText* AMeshWallText::Spawn(AMeshWallPlane* Plane) { FVector Location = Plane->GetActorLocation(); FRotator Rotator = Plane->GetActorRotation(); UStaticMesh* Mesh = MeshPool.Pop(); UWorld* World = Plane->GetWorld(); AMeshWallText* Instance = (AMeshWallText*)World->SpawnActor(AMeshWallText::StaticClass(), &Location, &Rotator); check(Instance != nullptr && Instance->IsValidLowLevel()); Instance->SetMesh(Mesh); Instance->SetHostPlane(Plane); Plane->SetUsed(true); ++AMeshWallText::SpawnedCount; return Instance; }
void AWeapon::FireFunction(){ if (firedObject){ UWorld* world = GetWorld(); if (world){ FActorSpawnParameters parameters = FActorSpawnParameters(); parameters.bNoCollisionFail = true; parameters.Instigator = Owner; parameters.Name = GetProjectileName(); FVector spawnLocation = GetActorLocation(); FRotator spawnRotation = GetActorRotation(); AActor* Spawned = world->SpawnActor(*firedObject, &spawnLocation, &spawnRotation,parameters); AFirable* firable = Cast<AFirable>(Spawned); firable->SetColor(ProjectileColor); firable->Instigator = Owner->GetController(); firable->Damage = damage; firable->OwnerID = OwnerShipNumber; } } }
void UChildActorComponent::CreateChildActor() { AActor* MyOwner = GetOwner(); if (MyOwner && !MyOwner->HasAuthority()) { AActor* ChildClassCDO = (ChildActorClass ? ChildActorClass->GetDefaultObject<AActor>() : nullptr); if (ChildClassCDO && ChildClassCDO->GetIsReplicated()) { // If we belong to an actor that is not authoritative and the child class is replicated then we expect that Actor will be replicated across so don't spawn one return; } } // Kill spawned actor if we have one DestroyChildActor(); // If we have a class to spawn. if(ChildActorClass != nullptr) { UWorld* World = GetWorld(); if(World != nullptr) { // Before we spawn let's try and prevent cyclic disaster bool bSpawn = true; AActor* Actor = MyOwner; while (Actor && bSpawn) { if (Actor->GetClass() == ChildActorClass) { bSpawn = false; UE_LOG(LogChildActorComponent, Error, TEXT("Found cycle in child actor component '%s'. Not spawning Actor of class '%s' to break."), *GetPathName(), *ChildActorClass->GetName()); } Actor = Actor->GetParentActor(); } if (bSpawn) { FActorSpawnParameters Params; Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; Params.bDeferConstruction = true; // We defer construction so that we set ParentComponent prior to component registration so they appear selected Params.bAllowDuringConstructionScript = true; Params.OverrideLevel = (MyOwner ? MyOwner->GetLevel() : nullptr); Params.Name = ChildActorName; Params.Template = ChildActorTemplate; if (!HasAllFlags(RF_Transactional)) { Params.ObjectFlags &= ~RF_Transactional; } // Spawn actor of desired class ConditionalUpdateComponentToWorld(); FVector Location = GetComponentLocation(); FRotator Rotation = GetComponentRotation(); ChildActor = World->SpawnActor(ChildActorClass, &Location, &Rotation, Params); // If spawn was successful, if(ChildActor != nullptr) { ChildActorName = ChildActor->GetFName(); // Remember which component spawned it (for selection in editor etc) FActorParentComponentSetter::Set(ChildActor, this); // Parts that we deferred from SpawnActor const FComponentInstanceDataCache* ComponentInstanceData = (CachedInstanceData ? CachedInstanceData->ComponentInstanceData : nullptr); ChildActor->FinishSpawning(ComponentToWorld, false, ComponentInstanceData); ChildActor->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); SetIsReplicated(ChildActor->GetIsReplicated()); } } } } // This is no longer needed if (CachedInstanceData) { delete CachedInstanceData; CachedInstanceData = nullptr; } }