UPROPOERTY variables not showing in details - unreal-engine4

I´ve been trying to show some variables that I created in a C++ class and then create a Blueprint class based on it. But when I see the details of the object or try to find this variables in the Blueprints they do not show up.
I´ve basically copy and paste code from UE4 documentation see here: https://docs.unrealengine.com/en-us/Programming/Introduction, but the variables are not showing up for me.
// MyActor.cpp
#include "MyActor.h"
// Sets default values
AMyActor::AMyActor()
{
//PrimaryActorTick.bCanEverTick = true;
TotalDamage = 200.0f;
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// MyActor.h
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYPROJECT3_API AMyActor : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float TotalDamage;
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
I want to modify this variables from the Event Graph. Please help me find what I did wrong, if you need anymore information I will gladly provide it to you.

Use BlueprintReadWrite or BlueprintReadOnly
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float TotalDamage;

This just happened to me and feels like this is what might have happened to Juan Esteban as well, if you think your code is correct (and in my case it was):
"Hot Reloading" of the project was "stuck" in Unreal (i.e. changes made to the project didn't reflect in the editor), despite rebuilding the project and running "Refresh Visual Studio Project" from the file menu.
So... restarting Unreal actually fixed it.

Related

Best practice to to access components using scripts in Unity?

I am new to Unity so go easy on me. :)
I added an game object with a text field component (via TextMeshProUGUI) to my heads up display in my scene. I want to use this to display various statistics on it for debugging purposes during game play.
I then created a script which I added as a component to the same game object that holds my text component. Is this the best practice? Not sure how else I would get the script to execute.
Once I had my script created, I needed to find the text component as well as some other components in my scene so I could display the debug information. Below you can see how I did it... it feels a little dirty to be searching the entire scene to find these things. Would love some insight on how long-time Unity programmers go about this!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerDebugStatistics:MonoBehaviour {
TextMeshProUGUI playerDebugStatisticsText;
PlayerCharacterController playerCharacterController;
Health playerHealth;
private void Start() {
// First find the object in the scene named "PlayerDebugStatisticsText" and then get it's TextMeshProUGUI component
this.playerDebugStatisticsText = GameObject.Find("PlayerDebugStatisticsText").GetComponent<TextMeshProUGUI>();
// Get the player character controller
this.playerCharacterController = GameObject.FindObjectOfType<PlayerCharacterController>();
// Get the player health from the player character controller
this.playerHealth = playerCharacterController.GetComponent<Health>();
}
void Update() {
// Update the text every frame
this.playerDebugStatisticsText.SetText(string.Format("{0:N2}", this.playerHealth.currentHealth));
}
}
3 ways
Create an inspector reference to the other object and access it from your script - a public or private (with [SerializeField]) attribute in your script - and drag the component in like in this video: https://youtu.be/dMgQOP7kdxg?t=425
Use the singleton pattern: https://www.youtube.com/watch?v=5p2JlI7PV1w
Use dependency injection - https://github.com/modesttree/Zenject
Your way isn't terrible if you don't do it in the Update() loop, and cache your objects (like it appears you are doing), but if you need that performance in Start(), the above options can help.

Unity3D Text not changing after being set in Start()

I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.

How do I deal with app backgrounding to restore the Exoplayer, which I inject with Dagger2?

I have a Fragment which contains an instance of Exoplayer which I provide with Dagger 2 like this:
#Inject SimpleExoPlayer mPlayer;
For the most part, this works well, I can play stuff on my player, the state is correctly restored on lifecycle changes, etc.
The issue I have is that when I click on the Overview button, navigate to another app, and then back, the player is in a black screen state where the seek bar has been restored to its saved position, but it will not play anything, nor respond to play commands on the UI, and just stays black until the Fragment gets recreated.
I am now trying to modify things to get my code to deal with the player just like in this code lab:
private void releasePlayer() {
if (player != null) {
playbackPosition = player.getCurrentPosition();
currentWindow = player.getCurrentindowIndex();
playWhenReady = player.getPlayWhenReady();
player.release();
player = null;
}
}
which should be called in onStop() above API 23.
The initializePlayer() is called in onStart() and it is supposed to look like this. In my case the only difference is that I don't create the player, Dagger does it for me on creation.
private void initializePlayer() {
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
new DefaultTrackSelector(), new DefaultLoadControl());
playerView.setPlayer(player);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPosition);
[...]
}
Note that both code snippets are from the linked code lab.
This is where I am struggling with Dagger. When the Fragment is created or recreated, everything is fine, as Dagger will provide me with a player, but if I have set the player to null in onStop(), and the Fragment is not destroyed and it is restored and only onStart() and onResume() are called, Dagger will not create a new instance, unless I am missing a way on how to this.
Can anyone point to some code examples of Dagger2 and ExoPlayer set up, preferably with a Fragment?
Also shed some light into this, please :)
EDIT: Solved thanks to #David Medenjak
After the hint on using a Provider<> I solved the issue by having a:
#Inject Provider<SimpleExoPlayer> mSimpleExoPlayerProvider
And:
SimpleExoPlayer mPlayer
So when I initialize the player inside onStart I will get a new instance of the Player from the Provider if there is no instance attached to mPlayer, and hold to that player instance util I release the player in onStop where I set mPlayer to null.
if (mPlayer == null) {
// Get new instance of player if mPlayer is null
mPlayer = mSimpleExoPlayerProvider.get();
}
Dagger will not create a new instance, unless I am missing a way on how to this.
If all you want to do is get a new instance from Dagger every time, then you should inject Provider<SimpleExoPlayer> and call provider.get() when you need a new object.
For this to work the player needs to be unscoped, or you will get the same object every time.

How to see the Auto Reference section on Plugin Inspector?

In the latest Unity manual
https://docs.unity3d.com/2019.1/Documentation/Manual/PluginInspector.html
they assert that the Plugin Inspector
now features an "Auto Reference" concept:
So using the latest Unity (and even trying .2 etc),
However no matter what I do I cannot make this appear. Every single Unity project I have tried, even Unity examples, does not have the feature.
How it looks for me ..
What is going on?
how to access the Auto Reference ?
tl;dr- "Auto reference" only works for managed plugins. that is a .dll file that was written in, and compiled from C#. Unmanaged plugins (dll's written in a language that is not C#, are unmanaged and can't be auto referenced)
edit: I just noticed there were more hidden comments, one of which was Aybe mentioning it working for managed DLL's.
edit2: if you want the project to test it out i can upload it.
I wanted to check if there was a difference between managed and unmanaged DLL's when inspecting in the editor (testing in Unity 2019, but I assume the same goes for 2018).
I made the following two DLL's. One in C# (managed) and one in CPP (unmanaged). I added some simply functionality to it to make sure it wouldn't be caused by having an empty dll.
Managed C# plugin
using System;
namespace TestDLLManaged
{
public class TestDLLManaged
{
public static float Multiply(int a, float b)
{
return a * b;
}
}
}
Compiled it into a DLL targeting .Net 3.5 framework (unity 2018 and later versions support 4.x, but wanted to play it on the safe side) and placed the .dll file in the /Assets/ folder (Apparantly the Assets/Plugin folder is intended to be used with native/unmanaged plugins, and not managed).
Unmanaged/native C++ plugin
//header filer
#pragma once
#define TESTDLLMULTIPLY_API __declspec(dllexport)
extern "C"
{
TESTDLLMULTIPLY_API float MultiplyNumbers(int a, float b);
}
//body
#include "TestDLLMultiply.h"
extern "C"
{
float MultiplyNumbers(int a, float b)
{
return a * b;
}
}
Also compiled this into a dll, and placed it in the /Assets/Plugin folder.
I call both DLL's inside DLLImportTest.cs and perform a simple calculation to make sure both DLL's are actually imported, and functioning like so
using static TestDLLManaged.TestDLLManaged;
public class DLLImportTest : MonoBehaviour
{
const float pi = 3.1415926535f;
[DllImport("TestDLL", EntryPoint = "MultiplyNumbers")]
public static extern float UnmanagedMultiply(int a, float b);
// Use this for initialization
void Start()
{
UnityEngine.Debug.LogFormat("validating unmanaged, expeceted result = 100: {0}", UnmanagedMultiply(10, 10f));
UnityEngine.Debug.LogFormat("validating managed, expeceted result = 100: {0}", Multiply(10, 10f));
}
}
When inspecting the DLL's in the editor it seems that the Managed (C#) plugin does have the option to auto reference and the Unmanaged/native (cpp) dll indeed doens't have the functionality. Now I don't actually know why this is the case, as it is nowhere to be found in the documentation. Maybe it's a bug, maybe there is another reason behind it. I may make a forum post about it later asking for more clarification.
As a little extra I decided to run a benchmark the two function, and to my surprise found that the managed C# plugin was actually faster than the cpp one.
private void BenchMark()
{
Stopwatch watch1 = new Stopwatch();
watch1.Start();
for (int i = 0; i < 10000000; i++)
{
UnmanagedMultiply(1574, pi);
}
watch1.Stop();
UnityEngine.Debug.LogFormat("Unmanaged multiply took {0} milliseconds", watch1.Elapsed);
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (int i = 0; i < 10000000; i++)
{
Multiply(1574, pi);
}
watch2.Stop();
UnityEngine.Debug.LogFormat("Managed multiply took {0} milliseconds", watch2.Elapsed);
}
Results:
Unmanaged multiply took 00:00:00.1078501 milliseconds
Managed multiply took 00:00:00.0848208 milliseconds
For anyone wishing to view the differences/experiment with it themselves, i've made a git-hub repo here containing the project i used above.
This question has been nicely resolved by #remy_rm
Compiled c# dlls ("managed plugins") do have the auto-reference feature
Actual native plugins ("unmanaged plugins") do NOT have the auto-reference feature
In fact this does apply identically on both PC and Mac:
Unity (sometimes) refers to:
c# compiled as a dll as "managed plugins"; and they (sometimes) refer to
native plugins (say, an actual static library for iPhone which is compiled C) as "unmanaged plugins".
(Whereas, all other Unity-related writing on the www generally refers to compiled c# as "dlls" and native plugins as "plugins".)
The auto-reference system is only for compiled c# .. "managed plugins".
A huge thanks to #remy_rm for spending hours resolving this issue.
Unity are trying and trying to improve their comic documentation - not quite there yet :)

GetComponent returning 0 in Unity Game Engine

I´m having a unity problem with getting a variable from another script. I´m working in c#.
In this case I´m getting the health of the player to the GUI script, but the variable just returns 0. I tried to understand by searching for similar problems but i could not figure it out. Thanks! /PixzleOne
How the health is set in the player script in the monobehavior part:
public int health = 100;
How I tried to get the health in the GUI script:
int playerHealth;
public GameObject player;
void Update () {
playerHealth = player.GetComponent<playerScript>().health;
print (playerHealth); //Only for me to see if it returns anything.
}
You probably have the value changed in the inspector for the object. Inspector values will override script-defined values.
An important thing to note - if you previously declared your public variable (also referred to as an inspector variable) without a default value like so:
public int myValue;
then update it with a value in the script:
public int myValue = 1;
the inspector will not pick up the change. You'll have to change it in the inspector yourself. I remember this getting me stuck at one point when I first started with Unity.
When in doubt, check the inspector.