Can't pick StaticMeshActor from scene when I create variable of that type in blueprint, if the actor is from sub-level in Unreal Engine 5 - unreal-engine4

I have made an blueprint and inside of it, variable of type StaticMeshActor (object reference):
When I create instance of this blueprint in scene, I get the drop-down for my “Test” variable with StaticMeshActor actors in scene (that’s correct).
But once I click on any of them (that are from sub-levels), field resets to “None” again. Same goes for picker icon from scene.
Is it bug, or am I doing something wrong? Is it even possible to select actor from sub-level?

Related

access a variable from level blueprint in unreal engine 4

I Have a variable that updates every time i move my cube in the level blueprint , now i want to access this variable from multiple class blueprints , what do I do , I tried casting to gamestate but didn't succeed , I am really new to ue4 if you could explain in details please
edit: sorry for not adding details ,
The var I want to access is an integer named cube_side that tells me what side the cube is on every time I move , all of this happens in the level bp , I want to access this variable to see what side the cube is on from other class blueprints ->
here are some details in a picture
I know it's not good to code everything in the level blueprint , but it's too late now , I only need to transfer the var cube_side to other class blueprints so the other object can change depending what side the cube is on.
Create an Actor Class for your logic/functionality. Then use Get all actors of class (choose your class) -> Get a copy -> get variable
Communication with the level blueprint is rather tricky in UE4, since they are not as persistent as e.g. the GameMode, and therefore shouldn't be accessed directly (Imagine older games like Final Fantasy where a new level was loaded every time you stepped outside a boundary, so relying on it could potentially break your actors or crash the game due to nullptrs).
It's a little hacky, but works:
Move the variable inside the cube-blueprint. Add an event dispatcher to the cube, if it is moved, call it and pass the variable in.
Select the cube in the editor, open the level blueprint, right-click, "add reference to selected actor" (the cube must be part of a blueprintclass, not only a static mesh dragged in, though), and bind the event dispatcher inside the Level BP.
Create a function inside every blueprint that needs access to the variable, which does whatever it should do, depending on the variable.
The custom event of the Level Bp (that was bound to the Event Dispatcher of the cube), needs references to all actors that have to work, when the variable changes and call each Actors function (you can get the references like you got the one from the cube)
Then, every time the variable changes, the Level BP is notified, the custom Event is executed and this custom event calls all the actor's functions.
Event Dispatchers explained
This is a huge wastage of functions/code, since you only need it for this one level and may never use it again. Avoid this in the future, by not relying on the level BP so much.
You can use GameStateBP to create and store all variables that you need in game, in GameModeBP create functions to get and set this variables via Get Game State function and then function Cast To GameState and then logic. After that from any blueprint access it using Get Game Mode -> Cast to you GameMode -> use your function to set or get data from GameState.

Unity3d, add component to prefab in resource

One time I was playing around with Resouce system in Unity I discovered this:
Say if you only load but do not Instantiate the prefab:
GameObject testObj = Resource.Load("testPrefab");
And you have a script called "TestScript", and you add this script to testObj
testObj.AddComponent<TestScript>();
You run it, and close it, this TestScript will still be inside testPrefab inside Resource folder, and if you run it again, the testPrefab in Resource folder will have two TestScript component.
I understand that Resouce.Load() is just point to that prefab in Resource folder, no copy has occured.
But would it be a good idea says, put a CleanPrefab() function in this prefab to make sure it restore to the original configuration first and then add other conponents as needed?
Do not modify a prefab. Prefabs are made to be used as re-usable Objects. There are many reasons you shouldn't try to modify it. One of them is that it will affect instantiated objects references that prefab. With modifications done to your prefab, there is no guarantee your levels will start the way they are supposed to start. This will mess up your game.
You run it, and close it, this TestScript will still be inside
testPrefab inside Resource folder, and if you run it again, the
testPrefab in Resource folder will have two TestScript component.
The behavior you described is only true in the Editor. One you build it, the behavior is totally different. In a standalone version, once you restart the program, the prefabs will automatically reset itself. What you are really modifying is the loaded prefab in the memory not the one stored on the disk. Also note that everything in the Resources folder is read-only. They can't be modified.
If you modify a prefab directly, it stays in the memory even when you reload the scene. The only time that modification will be gone is when you restart the application. Do not modify a prefab.
As mentioned here, Resources.Load doesn't create a new instance of an object because it does not create an Object in the scene; that's what Instantiate does.
To avoid this problem of linking to the original prefab and avoid overriding, use Instantiate() and then add all your components with respect to that variable.
It is important to use Instantiate before apply new components to the object or modify the existing ones.
For instance you have this snippet of code:
void Start()
{
SelectCharacter();
InstantiateObj();
ControllerAssignment();
AddColliderComponent();
AddScriptComponent();
}
private void InstantiateObj()
{
obj = Instantiate(obj_original_prefab); //apply changes to this variable
}
This code is a correct implementation, where you call the Instantiate method before applying all the changes to the object obj, which is a 'deep copy' of your original prefab and not a reference!

Unity, Spawn a prefab from another prefab

I'm new to Unity. I have an invisible GameObject , call it A, with only a script, that instantiates a prefab B multiple times. I need spawned clones of B to have reference back to A, I have learned that in order for this to work, A has to be a prefab itself (correct me if I'm wrong) Spawned B objects react to mouse clicks and call a method of A. The problem is that inside this called method of A, the variables of A itself have values that I don't expect, for example a certain variable that was initialized to 0 in Start() and never used has a value of 12. It seems like every spawned object B has a reference to its "own" A, and variables of A have random values. What am I missing?
in order for this to work, A has to be a prefab itself (correct me if I'm wrong)
I assume that you are setting the relevant field in the script on prefab B to the prefab of A, which is not what you want. A doesn't have to be a prefab at all.
A prefab is a serialized GameObject that contains specific shared default values for easy GameObject management through the Editor and Editor/in-game scripts. A prefab is used when dealing with a large number of similar objects; each prefab instance will be similar to another with the exception of a few modified properties. This allows for large scale instantiation modification of prefab instances in a single click. For example, storing a gun projectile object as a prefab allows you to modify the default size of all gun projectiles with a single click, while allowing for property customization on a per-instance basis. You can think of prefabs as templates you can use to instantiate a GameObject.
When spawning an instance of prefab B through the script on A (henceforth referred to as ScriptA), simply set the required field on the script on the spawned instance of B (hereafter referred to as ScriptB) to the gameObject (or some other) field of ScriptA, like the following:
// ScriptA's method which spawns instances of prefab B
GameObject bInstance = Instantiate(prefabB);
ScriptB scriptOnBInstance = bInstance.GetComponent<ScriptB>();
scriptOnBInstance.referenceToAGameObject = this.gameObject;

Dynamically add Components to an Entity

In my game, I have an entity which is an empty robot, and some components which are parts for building that robot(arm, head, weapon, tool, etc) and each part consists of different types. What I want is for the player to starting building the robot by dynamically adding parts to it.
My entity class has properties like this:
var arm: Component!
var head: Component!
var legs: Component!
var weapon: Component!
Basically, the robot entity has a property for every possible component in the game, and when I get new ideas for components I have to create properties for them in the robot class, and I have a function that assigns each property to the component that the player adds. The reason I'm doing that is to be able to access them from an outside class like this:
robot.weapon.shoot()
robot.legs.move()
But what I want is for the robot entity to not have any component reference in it at the start, I want them to be added dynamically depending on the player's choices and still be able to access them as I have shown above, meaning that the class would be empty and when the player adds a component (for example a pistol) a property like that would appear, or some sort of a way that makes that component a part of that entity:
var weapon: Component = Pistol()
I'm not sure if it's even possible to do that.
PS: I'm not using the component-entity system that is built in GamePlayKit and I don't want to.
I guess what you need is a Null Object pattern. You have to make classes for your robot components, that represent an absence of a special action. For example, you may create AbsentWeapon class and it's shoot() must do nothing in your game. Or it could sent a message to event control class about an attempt to shoot without a weapon (that depends on your design).
You could make those classes singleton-like objects to ease your checks (if myWeapon == EmptyComponents.getEmptyWeapon() {...})

How to keep references to UI elements in a prefab, instantiated at runtime

I have a prefab, which has a script component as MonoBehaviour. This script has 3 public fields as text; which are assigned in the inspector, before saving the gameobject and remove it from the scene.
Now, this works fine if I have a UI element, like a panel. Every text field on the panel, defined in the prefab, is still assigned when the prefab is instantiated at runtime.
This sadly does not work on another prefab that I have made; which is not a UI element. In my case it is a meshgameobject with various components on it (navmesh agent, capsule collider, rigidbody, animator and so on)
I believe this is due the fact that with the UI panel, the elements are already in the gameobject hierarchy, while when the reference is on a different gameobject; Unity does not keep track of them.
This means that I have to always add at runtime via code, the elements that I want to reference on each prefab, if they are not part of the game object itself? In this case I would just avoid to have my references public then, since I won't be using the inspector in this case (every gameobject of this type is instantiated at runtime).
Just checking if there is any other solution to work around this.
Use List to save reference for each generated object.
Lets assume that the object you want to add to store the reference is called meshgameobject.
Example:
List<meshgameobject> meshGOB;
initiaize inside Start function
void Start(){
meshGOB = new List <meshgameobject>();
}
Then create and use list.add() to add reference during runtime like
meshGOB.Add((meshgameobject)Instantiate(prefab, Pos, Quaternion.Identity);
OR
meshgameobject tempGOB= (meshgameobject)Instantiate(prefab, Pos, Quaternion.Identity);
//Do something with meshgameobject
tempGOB.someAction......
then add the reference to the List
meshGOB.Add(tempGOB);
Do not make a perfab which references to other gameobjects in the scene but are not in the hierarchy of the perfabI itself. AFAIK, Unity can not track this kind of references.
Even if Unity supported this kind of prefab, you could not use this kind of prefab in other scenes because the specific references, so it is not make much sense to make a perfab like that. If you have to make it a pefab just because the scene and the game object are maintained by different person, you may use Find() to populate the references at runtime.