First time setting a gameobject to active it lags - c#

When I first set a particular gameobject in the Canvas element to active, (SetActive(true)), it lags for a good second or so. Sequential activations are instantaneous. Note that this only happens in the standalone player. In the editor, it doesn't lag at all. My guess is obviously that the first time it has to load the asset. However, can I preload this particular asset in any way? I attempted to do so in the build settings under optimization, but that didn't affect anything. And no, I don't have any code in the Start() function or the OnEnable() function of the said gameobject that's being enabled.

The accepted answer is a workaround, not a solution. Keeping hundreds of UI elements loaded is an utter waste of memory.
You should instead divide up your canvases, as written in this wonderful article by Unity. The reason for the lag is Unity's updating all canvas contents, even disabled objects, when you enable an object for the first time. To prevent unused objects from updating, isolate them in a different canvases. You can even put those canvases as children of your original canvas if you wish.

That's expected.The lag depends on how many UI components and GameObjects that are under the hierarchy of the Canvas. There is so much memory allocation and draw calls when SetActive(true) is used on a Canvas or UI component. The fix is simple. Instead of using SetActive(true) for UI, disable the component by modifying the enabled property.
For example, to enable/disable the the Canvas:
Canvas canvas;
canvas.enabled = true; //Enable
canvas.enabled = false; //Disable
Let's say that you only want to disable a Text component under a Canvas, use the enabled property to disable that Text component instead of SetActive(true). The-same thing applies to other UI components.

Related

Setting a button's alphaHitTestMinimumTreshold results into no call to Button.OnPointerDown

I want to create a button that has a custom shape in Unity.
I created a default UI>Button object and set it's Image to the following sprite:
It doesn't show it on this website, but the circle is the only part of this image that is transparent. It's a .png sprite.
When I set this as the sprite for my button, I could click on the entire rect transform of this sprite to activate the button using my button's OnPointerDown() method and un-hide some other sprites around it:
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
Debug.Log("Foo");
}
Each time any part of the sprite was clicked, transparent or not, "Foo" would print.
Now I set the button alphaHitTestMinimumThreshold to 0.5:
GetComponent<Button>().image.alphaHitTestMinimumThreshold = .5f;
And as the docs suggest, I disabled atlassing...
...and enabled read/write for the sprite:
Yet now, when I click the button in my scene.. nothing happens. No matter where I click, "Foo" doesn't print anymore.
Then I tried changing the alphaHitTestMinimumThreshold to a lot of different values. Again, the entire button was not clickable anymore. If I don't touch the alphaHitTestMinimumTreshold at all however, my "Foo" prints again.
Why does changing alphaHitTestMinimumTreshold to any value make my OnPointerDown method to never be called?
So after 12 hours of messing around with all sorts of options, I found out that there were 3+ consecutive issues causing this behaviour.
If you ever run into your transparent buttons not working, be sure to try the following steps:
Make sure read/write is enabled in the texture import settings
Try if setting the Sprite Mode Mesh Type to Full Rect helps (sometimes the button's hitbox is off)
Disable atlassing under Project Settings > Editor > Sprite Packer > Mode
..and finally what did the trick for me: if you're working in a prefab that's nested inside another prefab (say your have a prefab for your button and then another prefab for your UI canvas/contents), remove the nested prefab from the parent prefab (aka remove the button prefab from the UI prefab), and just add it back in again. It was that freaking simple for me.
I triple checked whether my nested button prefab differed from the button prefab blueprint, and it didn't. But somehow, removing it from the UI prefab and adding it back in again solved my problem with a large sprinkle of magic.
With transparency buttons, I found that detection improves when the image is a child of the button object. So hierarchy is Canvas>Button>Image.
I know, old thread, but it came up so heres my solution:
It did all of the suggestions, but it didn't work.
HOWEVER,
What finally worked for me, was TO SPECIFY THE RIGHT SIZE. My game Object was elongated, but the sprite had "preserve aspect ratio" ticked. I just didn't bother to size it properly.
So when you have an image, set the size of the gameObject to the right dimensions.

How to control Unity Animation?

As far as I know, there are ways to manage Animation
Immediately,
Managing in the form of objects.
Managing with Sprite Images.
Is it effective to manage animations
in object format to manage character's joints in 2D animation?
What should I do to make it easier for me to understand Unity Animation?
As a beginner, we need a lot of data. I need your help. Help me.
I am going to explain the animation by manipulating GameObjects.
You need to add an Animator component to the GameObject you wish to animate. The animator component needs an animator controller. You also need to create an animation clip which represents an animation.(Animation controller is automatically created when you create an animation clip)
Now, to get started with animation you need to focus on animation clips. After you add an animation clip, you can record an animation into it. You do this by hitting the record button in the Animation window. While recording, any changes made to the GameObject will be recorded into the animation clip. (For example, you might move your GameObject). Any such change will create a key frame in the Animation timeline. The time point where key frame should be created can be changed.
Unity will interpolate the changes between two keyframes automatically.
However, there is also an animation curve which allows you to define how changes are applied between time points.
After you record animations you can define how transitions between different animations are made in the Animator Window.
unfortunably I am not really sure what your question is about?
For question this might be helpful:
https://www.youtube.com/watch?v=PuXUCX21jJU
Usually you have a Image File with the animation movements of your 2D Image object and using the "Sprite Editor" to cut them out for Unity.
You then add this Clip on a Animimation Component to be added to your "GameObject".
Since this is a "C#" question, maybe you want to know how to access this Compnent. The best is to use it in the "Init()" and add:
var anim = GetComponent();
Now you can use the "Animation" Component to play the configured Animation Clips.
I hope this helps you a little bit.

Screen flashes when loading new scene

I have a level selection menu, inside this I have buttons to load my scene levels.
I am using the next method to switch the scenes:
UnityEngine.SceneManagement.SceneManager.LoadScene();
The problem is that I have dark-gray faders in my scene and when I load the different scenes the screen flashes white. Instead of staying in the same dark-gray tone like I would want it.
I will gladly supply any further information that you need.
Does anyone know a solution?
The last frame of the previous scene is contiguous with the first frame of the next scene so one needs to ensure that there is nothing in either frame that could make a visible difference e.g. resetting the state of something like a material colour via a script called from an Awake function.

Changing Sprites using scripts in Unity2D C#

I am wanting to make a birds-eye view pixel-art game.
I currently have two sprite sheets set up, and split and whatnot
groundSheet and characterSheet these are split up into
ground_0_0_0 (A concrete floor)
ground_1_0_0 (grass)
character_0_0_0 (man idle animation frame 1)
character_0_0_1 (man idle animation frame 2)
character_0_1_0 (man run animation frame 1)
character_0_1_1 (man run animation frame 2)
character_1_0_0 (woman idle animation frame 1)
character_1_0_1 (woman idle animation frame 2)
character_1_1_0 (woman run animation frame 1)
character_1_1_1 (woman run animation frame 2)
The numbers after are a note as to:
first number - the main set of sprite animations (eg man)
second number - the animation set in use (eg run or idle)
third number - the frame of said animation.
(the ground has this as i plan to have animated grounds late on)
Now, I wish to make a script for the character (and ground alike) that has an editable value that is view able in the unity editor, for example how things like the sprite renderer has sprite, colour etc. Which dictates what first number to use (see above) what second number and the delay for the animation of the third number. This will then tell the sprite renderer what pictures to load and how quickly to load them. I also wish for the script to scan for the file starting with for example character_0_0_ and then count how many files after it, so it knows what to do when animating. I would like this script to be checking for a change in one of the variables viewable in the unity editor to change and as soon as it does it checks everything it needs for an animtion.
Something else could be done where there is only 1 box to edit in unity, which you put character_0_0_ or ground_1_0_ or something similar, and it checks everything that way (it also makes the script universal, and usable on the ground, character and walls (which I am adding later)).
This may seem confusing, but it make sense for me and many of you will probably mention a much easier way to do animations and such, but please only say these if it does what I want above.
For scripts and such my file layout:
/Assets
/scripts
ground.cs
character.cs
/sprites
characterSheet.png
character_0_0_0
character_0_0_1
character_0_1_0
character_0_1_1
character_1_0_0
character_1_0_1
character_1_1_0
character_1_1_1
groundSheet.png
ground_0_0_0
ground_1_0_0
(For some reason Stack overflow said the above was code, so i had to make it as that)
ground.cs and character.cs are the scripts in which I want to made as explained above.
In my object view thingy I have
Main Camera
ground
character
I am practically a newb to C# and JS I know bascially the grammar of C# (like where to use {} and put ; at the end of the lines). If you help me with this, i request that you explain the script, like use the // thing to simply explain what each command does, I know a few but not all of them. And I know someone is going to say it is really well documented in tutorial X and such, but most tutorials are not in unity 5 and while helping with the matter do not touch on it exactly.
Thank you for your help, if there is anything about this question/request that you do not understand (It is pretty complex) I will explain.
Maybe I am completely wrong, but it seems to me that you are trying to recreate an Animation system.
Is there a specific reason for which you wouldn't use Unity's animation system?
You can do everything that you describe here with it (change sprite, choose animation speed). And you would have almost no code to write. Just drag and drop you sprites in the editor for a start
EDIT - answer to first comment:
What you should do is create all the animations you need. Then in the animator, you choose which condition will trigger a transition to another animation (for instance, boolean jump is true will transition to animation jump). Then in your code you can call GetComponent().SetBool("Jump", true).
To have different character, you can create different gameObjects (one per character). They all have a different animator with animations specific to the character.
The other solutiojn if you really want one one gameObject and one animator is that you also add string condition to you animation (example, if character=="character1" and jump==true, transition to jump animation).
If I were you I would really focus on testing and learning all you can do with Unity animator. I can't think of a case were you would need to recreate the animation system yourself
Your question was long winded and hard to understand but ill try to help,
firstly if you want editable values in the unity editor I would Suggest using a serialized structure of information like this
[System.Serializable] // this makes it viewable in the inspector
public struct Sprite_Manager;
{
public Sprite[] Render_Sprites; // array of sprites to store sprites
public SpriteRenderer S_Renderer;
public float Anim_Delay;
}
public class Character : MonoBehavior {
Sprite_Manager SMG = new Sprite_Manager(); // instantiate a new instance of the struct
void Set_Sprite()
{
for(int i = 0; i < SMG.Render_Sprites.Length; i++)
{
SMG.S_Renderer.sprite = SMG.Render_Sprites[i];
}
}
void Update
{
Invoke("Set_Sprite", SMG.Anim_Delay);
}
}
Not sure if this is exactly what your looking for but this is one way you could setup a structure of sprite based information and use Invoke to setup some sort of delay when passing new sprites to the renderer.

Unity 2D - Dynamically instantiate new prefab inside NGUI's "UI Root"(as Parent)

Im new to unity. When I instantiate a new prefab GameObject from inside script as follows:
GameObject newArrow = (GameObject)Instantiate(arrowPrefab);
newArrow.transform.position = arrowSpawnTransform.position;
But this is creating the object in the root hierarchy(and not inside "UI Root" of NGUI). When I add any object outside of the UI-Root (of NGUI) it adds it to some location far away from the camera, also with a huge dimension. Can someone help me with how to add the newly created prefab under "UI Root" ?
It would be great of someone also lets me know about the positioning and scaling associated with native unity and NGUI. I try hard but am not understanding where to keep what object and in what size so that it comes out as expected. I'll appreciate any help that can be provided. Thanks !
EDIT:
I have found a way to place the new prefab inside "UI Root" thru:
newArrow.transform.parent = gameObject.transform.parent;
after instantiating.
But still the scaling is huge. It's like multiple times bigger than the screen size. Please help me with this. What should I be doing ?
When working with UI elements in NGUI, don't use Instantiate. Use NGUITools.AddChild(parent, prefab).
NGUI's scale with respect to the rest of the objects in the scene is rather microscopic. If you look at the UIRoot object, you will notice that its scale is measured in thousandths of a meter (default object resolution of 1 typically represents a meter). That is why when you instantiate a prefab and attach it to any object under the UIRoot it appears gigantic relative to the scale of the UIPanel. You could manually scale down the object to the appropriate size, or let NGUI do it for you (as indicated by Dover8) by utilizing NGUITools.AddChild(parent, prefab). In fact, this is the proper way to do so. Don't try to do it manually. The results will be unpredictable and can lead to inappropriate behavior of components. Here's a link to Tasharen's forum on this topic: http://www.tasharen.com/forum/index.php?topic=779.0
Positioning is a bit more complicated. Everything is relative to anchors. Anchor positions are a relationship between a parent object (usually a panel) and a target (usually some form of widget such as a sprite or label). They are controlled by four values relative to the edges of the panel (or parent object), right, left, bottom, and top with respect to the edges of the target (varies by position). Each of these are modified by an integer value (in pixels) that modify the dimensions of the target relative to the parent. There are many examples included with NGUI. I suggest that you look over them. In particular, pay attention to Example 1 - Anchors. I learned a lot from studying these examples, but they don't really cover the full power of NGUI, but they are an excellent starting point.

Categories

Resources