I update UI-Components (espcially Text) regularly in my game. My code looks like this:
private void ShowScore(string newScore) {
var scoreText=Find("Score").GetComponent<Text>();
if (scoreText.text!=newScore) scoreText.text=newScore;
}
My idea behind this is to only update the textbox when the value has really changed and so preventing unneccessary updates that might cause performance issues and/or bad UI experience like "flickering" and so on.
Now my question is: Is that even necessary or does Unity itself already the same validation internally?
Since the source code of Unity's UI system is open-source, you can actually look this up. Regarding your question, the specific code is here: https://bitbucket.org/Unity-Technologies/ui/src/31cbc456efd5ed74cba398ec1a101a31f66716db/UnityEngine.UI/UI/Core/Text.cs#lines-212
The relevant part of the setter is
else if (m_Text != value)
{
m_Text = value;
SetVerticesDirty();
SetLayoutDirty();
}
which, as you suspected, makes sure that the element will only be marked as "dirty" (requiring a visual update) if the new text is different from the one it had before
Related
I have a button (in UI), that I want to hide sometimes (but show again later), which means that it shouldn't show anymore and I shouldn't be able to click it. The only solution I found (that has actually managed to hide the button), is SetActive().
But in Update(), when I do SetActive(false) (the true/false is controlled with the variable wave_happening in my script), Update() doesn't run anymore, so I can't set it to true again.
When I do GameObject.Find("Start Button").SetActive(true) in another script, it just gives me a NullReferenceException (Object reference not set to an instance of an object).
This is my Update() function:
void Update() {
wave_happening = enemy_spawner_script.wave_happening;
Debug.Log(wave_happening);
transform.gameObject.SetActive(wave_happening);
}
Is there a solution to stop this problem, or another way to hide a button?
I'm fairly new to Unity and C#, so I don't know very much.
You can try disabling the button's rendering and functionality components:
GetComponent<Button>().enabled = false; // remove functionality
GetComponent<Image>().enabled = false; // remove rendering
Now, adding that to your Update function, plus a few changes for performance so you are not enabling/disabling every single frame, only when needed:
private bool isShowing = true; // or whatever your default value is
void Update() {
wave_happening = enemy_spawner_script.wave_happening;
Debug.Log(wave_happening);
if(wave_happening != isShowing) {
show(wave_happening);
isShowing = wave_happening;
}
}
void show(bool isShow) {
GetComponent<Button>().enabled = isShow; // remove functionality
GetComponent<Image>().enabled = isShow; // remove rendering
}
It's really difficult to do this well. Lots of issues arise:
Inevitably the button will be in a H or V layout group, and, as a basic software engineering issue of course you want it to work whether or not it is in a layout group, as that layout detail may be changed by your designers as the project goes on. For this reason it is a really good idea, as the OP initially guessed, to simply use .SetActive
But then you have the problem of the button being off so Update is not running. A simple solution is just to put the button in a wrapper. That is to say, simply in a UI Panel. Have the button manager script on that wrapper rather than on the button per se.
Then you just have a pretty Property on the manager script,
public bool Showme
{
etc...
and then you can just go ...
void Update()
{
Showme = enemy_spawner_script.wave_happening;
}
Can't get simpler looking code.
However, if you use a wrapper Panel. It is true that you have to be pretty expert at using the UI (particularly the auto sizing stuff) to make it work just the way you want. But, that's part of building Unity expertise unfortunately. :/
The concerns about performance is ... truly ridiculous. There's no difference between Unity's raw code "checking a boolean" and yourself "checking a boolean". However for sure as a matter of style it's crap to poll it in Update. (Note that in point "B" just above, if you're going to have heinously ugly "anti-polling" code, bury it in that Property.)
And then ...
"Trick" solution
A tip in Unity UI is you can add a CanvasGroup anywhere. Why would you do this? It allows you to FADE the whole thing, which, is often a quick solution to achieve what you want.
Hence ..
public CanvasGroup fader;
and then ..
void Update()
{
fader.alpha = enemy_spawner_script.wave_happening ? 1f : 0f;
}
and you're done!
I am tasked with writing a system to process result files created by a different process(which I have no control over) and and trying to modify my code to make use of Parallel.Foreach. The code works fine when just calling a foreach but I have some concerns about thread safety when using the parallel version. The base question I need answered here is "Is the way I am doing this going to guarantee thread safety?" or is this going to cause everything to go sideways on me.
I have tried to make sure all calls are to instances and have removed every static anything except the initial static void Main. It is my current understanding that this will do alot towards assuring thread safety.
I have basically the following, edited for brevity
static void Main(string[] args)
{
MyProcess process = new MyProcess();
process.DoThings();
}
And then in the actual process to do stuff I have
public class MyProcess
{
public void DoThings()
{
//Get some list of things
List<Thing> things = getThings();
Parallel.Foreach(things, item => {
//based on some criteria, take actions from MyActionClass
MyActionClass myAct = new MyActionClass(item);
string tempstring = myAct.DoOneThing();
if(somecondition)
{
MyAct.DoOtherThing();
}
...other similar calls to myAct below here
};
}
}
And over in the MyActionClass I have something like the following:
public class MyActionClass
{
private Thing _thing;
public MyActionClass(Thing item)
{
_thing = item;
}
public string DoOneThing()
{
return _thing.GetSubThings().FirstOrDefault();
}
public void DoOtherThing()
{
_thing.property1 = "Somenewvalue";
}
}
If I can explain this any better I'll try, but I think that's the basics of my needs
EDIT:
Something else I just noticed. If I change the value of a property of the item I'm working with while inside the Parallel.Foreach (in this case, a string value that gets written to a database inside the loop), will that have any affect on the rest of the loop iterations or just the one I'm on? Would it be better to create a new instance of Thing inside the loop to store the item i'm working with in this case?
There is no shared mutable state between actions in the Parallel.ForEach that I can see, so it should be thread-safe, because at most one thread can touch one object at a time.
But as it has been mentioned there is nothing shared that can be seen. It doesn't mean that in the actual code you use everything is as good as it seems here.
Or that nothing will be changed by you or your coworker that will make some state both shared and mutable (in the Thing, for example), and now you start getting difficult to reproduce crashes at best or just plain wrong behaviour at worst that can be left undetected for a long time.
So, perhaps you should try to go fully immutable near threading code?
Perhaps.
Immutability is good, but it is not a silver bullet, and it is not always easy to use and implement, or that every task can be reasonably expressed through immutable objects. And even that accidental "make shared and mutable" change may happen to it as well, though much less likely.
It should at least be considered as a possible option/alternative.
About the EDIT
If I change the value of a property of the item I'm working with while
inside the Parallel.Foreach (in this case, a string value that gets
written to a database inside the loop), will that have any affect on
the rest of the loop iterations or just the one I'm on?
If you change a property and that object is not used anywhere else, and it doesn't rely on some global mutable state (for example, sort of a public static Int32 ChangesCount that increments with each state change), then you should be safe.
a string value that gets written to a database inside the loop - depending on the used data access technology and how you use it, you may be in trouble, because most of them are not designed for multithreaded environment, like EF DbContext, for example. And obviously do not forget that dealing with concurrent access in database is not always easy, though that is a bit away from our original theme.
Would it be better to create a new instance of Thing inside the loop to store the item i'm working with in this case - if there is no risk of external concurrent changes, then it is just an unnecessary work. And if there is a chance of another threads(not Parallel.For) making changes to those objects that are being persisted, then you already have bigger problems than Parallel.For.
Objects should always have observable consistent state (unlike when half of properties set by one thread, and half by another, while you try to persist that who-knows-what), and if they are used by many threads, then they should be already thread-safe - there should be no way to put them into inconsistent state.
And if they want to be persisted by external code, such objects should probably provide:
Either SyncRoot property to synchronize property reading code.
Or some current state snapshot DTO that is created internally by some thread-safe method like ThingSnapshot Thing.GetCurrentData() { lock() {} }.
Or something more exotic.
I need to rework a UI created using the old UI.
I can't change the architecture of the program. The program uses a lot of static variables and my UI need to access them and edit them (i know static variables are quite bad but can't rework the whole architecture like i said).
Currently i'm doing something like this :
public void SetBool()
{
UIData.SomeBool = SomeToggle.isOn ;
}
public void SetAnotherBool()
{
UIData.SomeOtherBool = SomeOtherToggle.isOn ;
}
...
So i have a function for each static variable i want to edit associated with a specific toggle, this is ugly. How can i create a generic function to edit bool using toggle and slider to edit float values.
I thought about something like this :
public void SetBool(bool boolToSet)
{
boolToSet = gameObject.GetComponent<Toggle>.isOn;
}
And then add listener to the toggle for the event OnValueChanged and this function with the bool i want to change as parameter. But I have heard that calling GetComponent is bad for the performance.
I wanted to know if u had any better idea. Maybe i'm missing something important i'm quite to new to unity and c#.
Thanks
Sorry for my poor english.
GetComponent performance isn't that bad as it's just searching a list on a GameObject. It's just not advisable to call it every frame in many places without caching. For a user initiated UI action it will have basically no performance impact. FindObjectOfType on the other hand searches the whole hierarchy so is quite slow, and GetComponentsInChildren may be slow if the branch of the hierarchy you are searching is large.
Still it is good practice to cache your own component references in Awake(). I do internal state configuration in Awake and any external connections and dependencies in Start to make sure an object is properly initialized before speaking to the outside world.
If you want to pass in a Value type and change the value you need to pass by reference:
private Toggle toggle;
public void Awake() {
toggle = GetComponent<Toggle>();
}
public void SetBool(ref bool boolToSet) {
if (toggle != null) {
boolToSet = gameObject.GetComponent<Toggle>.isOn;
}
}
Then from wherever you call SetBool:
SetBool(ref myBoolField);
If you can guarantee a Toggle component exists you can remove the null check from SetBool. RequireComponent can help with this but it only stops you assigning something in the inspector... if code changes or you construct via script I don't think it does anything.
I am writing an application that will do some processing on the live preview images on windows phone 8. To achieve a good performance, I decided to use to the native interfaces provided with new sdk. Everythings work Ok for initializing the camera in native side, and feeding frames to a Image component in xaml. Now, I will write the code that will run in OnFrameAvailable method.
My problem is getting a processed value from the native component. Just to make things as simple as possible I just set an integer value in OnFrameAvailable and wrote an accessor of this value through a WinRT component to make it accesible in managed side.
I got stuck on what is an elegant way of accessing this value. When I try to access it in a loop in a thread i get the notorious "attempted to read or write protected memory " exception. I know the code does not make very much sense but I tried to minimize to point out the issue.
Here is how I do it:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
nativeCapture = new NativeCapture();
while (nativeCapture.Done == false) ;
viewFinderBrush.SetSource(nativeCapture.NPhotoCaptureDevice);
DrawElementThread = new Thread(drawElementsFunction);
DrawElementThread.Start();
base.OnNavigatedTo(e);
}
void drawElementsFunction()
{
while(true)
{
int a = nativeCapture.DetectedRectangleCoordinates; // Exception occurs here
}
}
Here you'll also notice that I am accsessing another value, Done, but I dont get the exception for it. However, I should note that is just set in the constructor of the native component whereas DetectedRectangleCoordinates is set everytime OnFrameAvailable called which I expect anytime a preview frame from the camera is available.
Therefore, I susptected that there might be some locking mechanism on WinRT components. Each time the OnFrameAvaible method called DetectedRectangleCoordinates becomes unaccessible. However, I could not find a statement about this and couldn't figure out how to debug such a thing.
I would really appreciate if you provide me with some pointers related to this or similar issues? Is it something related to access mechanisms in WinRT components? Or it is a bad threading practice I am doing? If so, how would I synchronize the thread in managed code and native code?
EDIT:
Putting a breakpoint on the line giving the exception and stepping does not cause the exception, and I get the expected value.
EDIT:
I put a breakpoint on the get function on native side. this pointer is pointing to null there. I could not understand why it is because it is being called from the object that is just constructed. ( nativeCapture object).
I have worked quite some time on what may be going wrong, but adding the code to Loaded event handler of the page solved the issue. I am not sure what it is related about, but when the code piece I have given in the question is run in OnNavigatedTo method, nativeCapture component might have self null pointer (this->) on its methods.
I hope this could help people if they have similar problems.
I am a bit new to threading (not new to C#, just haven't done much threading). Can someone explain to me why this does not work?
I have a thread which calls a method I will call "Loop". Loop contains a while loop which will continuously run, and on every loop of the while I want it to check if the A Key is down (using Microsoft's Keyboard class within the XNA Framework). But for some reason it never registers that anything is being pressed.
static Thread thread = new Thread(Loop);
static bool abort = false;
public static void Begin()
{
thread.Start();
}
private static void Loop()
{
while (!abort)
{
if (Keyboard.GetState().IsKeyDown(Keys.A))
Console.WriteLine("A pressed.");
}
}
Might anyone know why the Console.WriteLine() is never being called?
EDIT:
I guess I should explain a little bit. What I am actually trying to do is create something similar to ActionScript's events in C#. So I want to pass a "condition" and an "action" to call if that condition is met in this separate class which contains this thread. What this would do would allow me to just add "event listeners" to objects and it would automatically constantly check if one of the events gets triggered, rather than leave it to me to write If statements in code to check for the events.
Upon trying to do so, the first thing I tested was regarding this XNA Keyboard stuff, because it was one of the reasons I originally wanted to build this system, but it didn't work. So I created the standalone code which i posted above to see if I had made an error in my previous code and it still didn't work.
I never use XNA so I didn't really "know" but I've run into similar situations where you can't get keyboard (and other) input from a worker thread. I googled and found that in XNA this does seem to be the case. See this for example
So you need to (and probably want to) process your game input in the GUI thread. Just checking for input on each update tick should be fine. I doubt even if it did work, you would gain any performance - and you might introduce some interesting synchronization bugs ;-)
It does look like your creating your worker thread properly - this just isn't an application for it.