Dynamically add Components to an Entity - swift

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() {...})

Related

Is there a way to have a script reference an object as a field?

I've had trouble searching around and may be critically misunderstanding how Unity wants you to structure your project, but here is my situation:
I have characters in my game and would like to configure them in the editor. I have made classes that represent different behavior types and actions that can be performed. Is there a way for me to make a field on a script typed for these classes so that I can drag and drop using the inspector to configure different prefabs?
Here is some code demonstrating the situation:
Unit.cs
// A unit on the board.
public class Unit : MonoBehaviour
{
public UnitAction action;
}
UnitAction.cs
// A unit on the board.
public class UnitAction : MonoBehaviour
{
// Does things
}
These fields show up in the inspector once this script is applied to a prefab, but there are no options to populate the default field value. If I make the field type UnityEngine.Object, I can put the scripts there, but that seems like something I do not want.
It sounds like you are trying to serialize references to scripts themselves instead of instances of those scripts. There are a couple of ways that you may want to do this:
You could attach your UnitAction scripts as components of a GameObject that is in a context accessible to your "Unit" object (in the same scene, a child of the "Unit" object, or - probably the most common case - the "Unit" object itself). Then you will be able to serialize those instantiated components into the fields in your Unit class. This is the most common use case.
You could create a prefab for each of your UnitAction components and then serialize those prefabs into your Unit class fields. You would then instantiate a UnitAction at runtime. This doesn't really seem appropriate for your case based on what you described because a UnitAction probably isn't something that needs to be dynamically instantiated, but it is important to be aware of. This article has an example of using this method for giving a unit a list of spells (and also provides some good context on how to think about using unity components that would probably be valuable to you):
Unity: Now You're Thinking With Components
I would guess and say you do not want these scripts exposed except in editor, so you can use an attribute called SerializeField. It will expose the field to the editor so you are able to drag in references, but other scripts will not be able to access the fields you drop in.
If you want a specific script to appear in the editor, simply write
[SerializeField] private YourScriptName scriptReference = null;
As lists are generic structures, if you want, you can also make a list of scripts in a similar way
[SerializeField] private List<YourScriptName> scriptListReference = new List<YourScriptName>();
As I do not think you will be assigning these references again, if you want to grab the reference at any point, you can make a getter method.
public YourScriptName GetYourScript(){ return scriptReference;}
There are very few fields that Unity can not serialize, so generally, if you want to drag in a reference to a component, script, object, etc. all you need to do is make it either SerializeField or public followed by the type of whatever you want to drag in.
From the docs, the serialization system
CANNOT serialize static fields.
CANNOT serialize properties.
CAN serialize public non-static fields (of serializable types)
CAN serialize nonpublic non-static fields marked with the SerializeField attribute.
The fields that it can serialize are as follows
All classes inheriting from UnityEngine.Object, for example
GameObject, Component, MonoBehaviour, Texture2D, AnimationClip.
All basic data types, such as int, string, float, bool.
Some built-in types, such as Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Color, Rect, LayerMask.
Arrays of a serializable type Lists of a
serializable type
Enums
Structs

MRTK Add ManipulationHandler in C#

I'm attempting to dynamically add Manipulation Events to a ManipulationHandler that is being added to child objects of a parent. The parent object will be what the user is inspecting, but the user will be able to grab parts off of the parent and inspect them more closely. (i.e. you can look at an engine (parent object), but if you want to inspect the pistons (child objects) you can grab them and look at them)
Instead of having to go into every child object and manually add it in Unity I'd like to be able to add the parent object and just procedurally add the ManipulationHandler and ManipulationEvents on start or awake.
So far I have the following code for adding the ManipulationHandler script, but to add the ManipulationEvent I'm not sure how to set up the pointers so I can use the script and function I want from the source:
gameObject.AddComponent<ManipulationHandler>();
ManipulationHandler handler = gameObject.GetComponent<ManipulationHandler>();
ManipulationEvent newevent = new ManipulationEvent();
ManipulationEventData eventdata = new ManipulationEventData();
eventdata.ManipulationSource = gameObject;
The program works when I grab the objects, but I'd like to add manipulation events when I grab them so I can display additional data.
I see there's a getter and setter for Pointer in ManipulationEventData, but I'm not sure how to instantiate IMixedRealityPointer and how to get it to work. I'm also not sure if that's the object I actually need to accomplish what I'd like to accomplish.
I apologize in advance if I've missed something obvious. I'm new to MRTK.
Thanks!
The ManipulationHandler has four callback events among them OnManipulationStarted and OnManipulationEnded you can simply add listeners to. (see UnityEvent.AddListener)
Unless I understood your question wrong you don't have to instantiate any IMixedRealityPointer. You don't create the event data yourself but rather the ManipulationHandler feeds these events with the current event data including the interacting pointer information. The ManipulationHandler uses OnPointerDown and OnPointerDragged and OnPointerUp via the IMixedRealityPointerHandler interface in order to manage the interacting pointers and invokes the according events where needed.
Instead of using AddComponent followed by GetComponent directly store and use the return value of AddComponent which will be the reference of the newly added Component. MRTK also has an extension method
T EnsureComponent<T>(this Component component) where T : Component
so that you can simply use e.g.
var handler = this.EnsureComponent<ManipulationHandler>();
which internally first checks whether the component already exists, and if not it adds it.
Note that in order to enable near interactions you will also need a NearInteractionGrabbable so you should add this one too.
You also will have to make sure that your objects have some sort of Collider attached to the same GameObject as the NearInteractionGrabbable.
...
gameObject.transform.EnsureComponnet<NearInteractionGrabbable>();
var handler = gameObject.transform.EnsureComponnet<ManipulationHandler>();
handler.OnManipulationStarted.AddListener(HandleOnManipulationStarted);
handler.OnManipulationEnded.AddListener(HandleOnManipulationEnded);
...
/// <summary>
/// If you need it later you need to store the pointer since unfortunately in
/// OnManipulationEnded the <see cref="ManipulationEventData.Pointer"/> is null
/// (no idea why they do it this way :D )
/// </summary>
private IMixedRealityPointer _pointer;
private void HandleOnManipulationStarted(ManipulationEventData eventData)
{
_pointer = eventData.Pointer;
// whatever shall happen when manipulation started
}
private void HandleOnManipulationEnded(ManipulationEventData eventData)
{
// whatever shall happen when manipulation ended
}
Note: I am not sure if this thing you are trying to achieve is possible with this architecture ... it is very possible that nesting various ManipulationHanlder leads to strange behavior here and there. Especially very small parts will be almost impossible to grab ...

Why aren't Image and SpriteRenderer components inherited from one common base class?

I'm righting a script that loads some sprites and want to use it on both UI and in the game.
But there are two types of renderers for each and without any common base class, although they both have Sprite in common!
I want to use both Image and SpriteRenderer, so i want to write sth like this:
class SpriteLoader<T> where T: SomeRendererBaseClass {
T renderer;
void Load(){
renderer.sprite = GetSprite();
}
}
but to use "renderer.sprite" i have to specify T, for which i found no common base class.
If i'm gonna show game characters in UI i should load sprites on Image component, but in the game, i have to do the same behaviour but on SpriteRenderer, and as programmers we don't like duplicate codes.
Just because they both have a sprite doesn't mean anything.
You're going to just have to deal with the fact that the two classes aren't related to each other in the way that you'd like. This is no different than having a Player class that has a name property and trying to find a common parent class with GameObject ("it has a name too!")
The two classes have nothing else in common and should not inherit from some common ancestor (beyond whatever ancestor they do share).
At least they should have a common interface. I've seen that Unity API doesn't use interface at there best like .Net Does

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.

Are UE4 Blueprints the same with a C++ class? If so, how will I implement a class design?

Good day! I am new to using Unreal Engine 4 and I have a few questions about how exactly blueprints work. From my understanding of it, every blueprint works like a class. By that I mean one blueprint is much like one class in an OOP programming language.
Please educate me as to - if my assumption is correct or wrong. If wrong, then maybe you could help me achieve what I want in a different method/perspective. I am willing to learn and accept suggestions.
If at some point my understanding is correct - that blueprints are actually individual classes - I would really appreciate it if you could (please) guide as to where to go and how to implement a design that I want to create. This is from a programmers perspective (PHP OOP Programming). Forgive the approach, I'm just using PHP to logically express how I want the class to work. Plus, it is the only OOP programming I know atm.
I want to create a class named: Items. class Item {}
This class is going to handle everything item related, thus we will have to give it a lot of properties/variable. (Below is just an example; Again I'm using PHP as an example.)
class Item {
var $id;
var $name;
var $description;
var $type;
var $subType;
var $mesh;
var $materials;
}
3.) I would like to initiate this class by having two variables as its construct arguments. (We will require itemID and itemType). This is because I will use these two variables to retrieve the item's data which is already available in a data table. I will use those data in the table to populate the class properties/variables. (I'm not sure if I said that right. I hope you understood my point anyway.)
class Item {
var $id;
var $name;
var $description;
var $type;
var $subType;
var $mesh;
var $materials;
function _construct($cons_itemID, $cons_itemType) {
/*-- Start getting the item Data here based on what item and type provided. Then, push that data into the class properties/variables. We will use individual methods/functions to fill other properties/variables later. --*/
}
}
4.) Basically with that design I could easily pass on an item ID to the class and then get the item's name, description, mesh, materials and etc using pointers.
Example:
$weapon = new Item('10001','Weapon');
$weaponMesh = $weapon->getMesh();
$armor = new Item('12345','Armor');
$armorName = $armor->getName();
I'm just having a lot of trouble working with blueprint and achieve this method or even something similar to it. I'm not trying to avoid C++, I would love to learn it but I just don't have the time freedom right now.
Few things I have tried to make it work:
Casting / Casting to class (But I couldn't figure out what the target object will be and how was I going to add input arguments into the class that way? There isn't any input there that I could use.)
Spawn Actor (This one is very promising, I need to dig in deeper into this)
Blueprint Macros? Blueprint Interfaces? (I'm just lost.)
For all those who will help or answer. Thank you!
~ Chris
So far as I know, yes, we can assume that each blueprint can be viewed as class. (Moreover, since UE 4.12 (in UE 4.11 that functionality is marked as experimental I think) you can check Compile blueprints under Project settings -> Packaging. That will create native class for each blueprint.)
You can create either Blueprint or C++ class based on Object (UObject in C++). Then you can specify all properties (or variables in UE editor terminology). In BP you have small advantage: you can mark some properties as Visible at spawn (they must be Public and Visible). So when you are creating new instance of that class, you can explicitly pass values to that properties.
And in BP Construct event, that properties are correctly filled, thus you can set another properties values based on given ID and Type.
In C++ class having different arguments than FObjectInitializer is not possible, thus you don't have that values in time when constructor is executed. But it is not so hard to achieve same functionality, you can find example here: https://answers.unrealengine.com/questions/156055/passing-arguments-to-constructors-in-ue4.html.
Something about list of what you had tried:
Spawn actor - derive from actor only if you intend to have that BP in scene. Actors are subjects to game updates and rendering, so having actor only as data container is very wrong.
BP Macro is same as BP Function except function will be called just like function (so executing necesary actions by function call conventions) and macro will replace it's implementation in place, where you are calling that macro. More exhausting explanation here.
If I would implement your code, I'd do it like I said and then I'll have that class as property in some component and that component would be attached to some actor, which would be placed in scene.