I made and android 2d game in unity 5 with about 15 scenes and applied scene change script to buttons, I observe uneven delay of scene changing by onclick button, some scenes load quickly while other load after a short delay of about 1~2 seconds and some times 2~3 seconds, suggest what could be done.
Accurate, but probably undesired answer:
There is nothing you can really do about this
Unity scenese, when you load a new one, have to be deserialized from disk (they are not kept in memory!). The larger the scene is (the more gameobjects, monobehaviours, etc. etc.) there are the longer this process is going to take. Additionally, each MonoBehaviour script needs to be sent an Awake() and Start() invokation which has some significant overhead.
You can reduce the overhead by using fewer scripts with Awake and Start methods (calling the same logic under a different method signature from a single Main script), as well as fewer scripts overall (further centralizing your program), as well as compiling the game under Fast But No Exceptions and .NET Subset (neither of these are available for Editor running, however), both mentioned in the prior linked article.
It is also possible that Unity compiles out scenes in the Resources format (which is clunky and slow) and you may benefit from using Asset Bundles instead.
However you're still going to be bound by the load times between various scenes regardless of your optimization efforts (what few options exist). A complex scene will always take longer to transition to than a smaller one, there's no way around that.
Related
I've been trying to use a mixture of Unity's Animators and Playables in my game, and for the most part it works well, but there's two issues that I've been having for a long time, and I've at best worked around them. Today I bashed my head against them again, and after finding no solution online I decided to get my lazy ass to finally ask for help.
The basic setup is that my characters have:
An Animator with its controller, state machine, etc. that is used mostly for movement, jumping, climbing, etc. In case this is relevant, each character has an override controller of a generic one.
A very simple playable graph with just an output (wrapping the animator) and an input (wrapping the specific clip I want to play at the time). This is used for actions and attacks.
The problems I have are:
1- I can't seem to figure out an elegant, clean way to know when the clip fed to the graph (second part above) is finished. Currently I circumvent this by simply calculating how long the clip is and dividing by the current animation speed factor; I also have to account for when the animation is paused (e.g. hitstop). This gets the job done but is quite unelegant, and I'm sure there must be a better way.
2- Most importantly, when I'm done with the graph and standalone animation, the values of all of the properties the clip touches become locked at their last value. They stay locked even during any animation played by the regular animator; even if any of these later animations change its value, it snaps back to that locked "last frame" value when they end.
I've tried several things to solve this:
2.1- Set the default / desired value of the properties in the idle / default animation (to "mark" them as animatable properties in the normal animator's animation). This only fixes the issue for whatever animation is touched; any other animation played after that instantly reverts to the value locked by the last frame of the animation played by the graph.
2.2- Destroy the playable wrapping the animation (I do this anyway for cleanup since I need to recreate it each time a new animation plays).
2.3- Destroy the graph and recreate it each time (surprisingly, even this keeps the values locked).
2.4- Disabling the animator and enabling it again.
I'm frankly starting to lose my mind with the second problem, so any help would be exceedingly appreciated. Thanks in advance for any help!
Although this question is pretty old, I'm adding answer (along with my related follow up question) just in case there's more people that end up here from a search engine.
Animations (both "legacy" and non-legacy) can fire off events at some frame - just pick point (frame on dopesheet, place in graph on curves) and click "add event"...
There's some difference on how to specify which object/script & function to call between legacy and non-legacy - but in both cases it's basically a callback so you can know for sure when some animation started/finished (or any point in between).
Instead of trying to change values of those properties that are "locked by animations" from void Update() you seem to need to do those from within void LateUpdate().
From my testing - using/doing "legacy" animations (that also means "animation" component instead of "animator controller") allows you to use Update() - at least once the animation is finished.
And also worth keeping in mind that "animator controller" (component) doesn't accept importing "legacy" animations for any of it's states.
And animation (component) doesn't seem to play (at least not auto-play) non-legacy animations.
As of my question, well it's basically same as OPs question - is it possible to somehow "unlock" these properties (obviously without any states/animations playing) while using "newer" animator controller?
Although - based on things I've read while trying to find what's going on. Those "legacy" animations are not really "legacy" - and seem to be there to stay for reasons like being better for performance.
My main scene is taking 20 secs to load and after running the profiler it points to StandaloneInputModule as what makes it take that time.
I've searched in project for that script but it does not exist, i've only found a StandaloneInput
¿Where can i find this script/reduce this load time?
StandaloneInputModule is in the Event System GameObject that you have in your project and it's the responsable of your input in the game that you are developing :)
The problem is essentially that you may have a ton of world space UI Canvases in your game. Each of these canvases has a "graphics raycaster" script, because I think they're put there automatically when you create a canvas (could be wrong). Just remove all of those graphic raycasting checks on all of those canvases. The event system was having to try to keep track of all of those objects, and thus the "Eventsystem.Update()" was having a really hard time. Getting rid of those "graphic raycaster" scripts freed up a ton of CPU time in my game.
The good news is that the "Event System" script and the "Input module" script are not terrible for performance in and of themselves. This is great news for me, because I thought it was on Unity's end, and it turns out not to be (unless you need a lot of graphic raycaster checks).
Peace!
Firstly, I'm new to Unity and I'm currently learning c#, please be gentle!
As a project, I'd like to create a simple 3d platform game. The idea being the player starts on a square tile, which is the game platform playing area. They explore different elements on this tile by moving around.
The perspective is 3rd person, so the player is looking down on the action. As they approach the edge of the tile Unity recognises this and adds another tile to the existing one, basically doubling the playing area.
As the player moves around further to the tiles edge, other tiles are added, increasing the discovered areas each time.
My thinking to achieve this would be to have 5 tile game objects, that have different elements like trees already built on them. The question is what is the best way to achieve this.
Would it be to build the complete level with all tiles and then using code restrict how far ahead the player can see, basically to the width and length of the tiles.
Or would it be better to trigger a new tile to appear as the player approaches the edge of the current tile.
Thought, links to example code that I could recycle would be very handy.
Thank you.
The question is primarily opinion based, but here is some advise:
There is no right way to make a game in unity. The correctness is mainly focused on performance; memory and processing.
There are two approaches here:
condition: Your world is endless (or very large) and player moves very slowly over time (say each tile takes more than a second to traverse).
solution: Do not instantiate everything at start, instead when player reaches the edge of a tile look for the next tile in your level structure to retrieve its data and then instantiate its objects.
condition: Your world is not very large (say it has less than overall 10K objects) OR player can move fast (as in Age of Empires game).
solution: Instantiate everything in loading phase and deactivate the game objects as they are being instantiated so that nothing is getting processed at the start of the game. In this case the level structure is a collection of game objects where you activate or deactivate them.
Hints:
Pooling is a good practice when it comes to repetitive objects. Pool is basically an empty game object with a script, and many many deactivated children.
e.g. If you have 1K trees of the same kind you better have a tree pool. Create a game object named tree pool, add a pool script to it and make that script generate 1K deactivated tree game objects in the loading phase. Then whenever your level generator needs a new tree just fetch a tree from tree pool and activate and reposition it. Make sure you clean up the pool after the game ends to prevent memory leak.
you can implement the pool as you like to provide object variations for a specific pool.
Instantiation in run-time is costly especially in mobile devices. Whenever you need to instantiate several game objects at once consider using a coroutine to prevent lag or freeze (this applies to loading phase too).
e.g.
IEnumerable CreateObjects(Data[] data)
{
foreach(var e in data)
{
Instantiate(e);//instantiate here and then wait
yield return null;//this line prevents lag
}
}
//...
StartCoroutine(CreateObjects(data));
//...
Having many active game objects is also costly especially in mobile devices. If many active game object have heavy scripts, the update methods will ruin performance. If many active game objects have rigidbodies or colliders the physics engine processing gets heavy.
Activating game objects is costly but less than instantiation, since it only runs Start method on its script if any, and also causes the physics engine to re-evaluate its structure if it has static collider or rigidbody.
Rendering is costly if only the rendered visuals are (fully or partially) visible to the cameras.
Create an editor project where you can design your levels. in this project you will make use of unity's editor classes to generate some kind of data (JsonObject) which represents your whole world. (collection of levels, tiles in each level and objects in each tile). Moreover you can have other data such as objectives and stuff each stored in a different JsonObject. Then use this data in your game by reading it and storing its structure in memory.
The reason I recommend JsonObject to store data is its size, portability, flexibility, accessibility and simplicity to work with. JsonObject is a dictionary stored as a plain text. and since it's a text you can encrypt it as you like
I'm trying to load a scene asynchronously so I can have a nice progress bar and I found that the returned AsyncOperation.progress stops at 0.9. I don't have a problem with that but what is happening is that after that, it takes up to 50s to load the scene and that doesn't show on the progress. After deleting some objects I found that there is 1 (the main scene object) that is causing this delay.
My question is, is there any way to load this object in the first 90% of the load (which is happening super fast right now - 1s)?
Thanks in advance
If this GameObject is inside the scene, it is loaded with the scene. The problem you have is with the all script logic inside the scene. The loading thread actually finished, but the scripts, instantieting etc., takes all device resources and it looks like stuck at 90%.
To solve it I think you should delay all scripts executions on Awake or Start methods. That should help, but still all the time needed on particular device to execute scripts will take all CPU, and will look like stuck again.
So, it seems it all comes to the substances I was using. It's really strange for me because I explicity check all of them as "bake and discard substance" which seems to do nothing. After baking all the textures and switch from substance to texture in the material the loading came down from 42s to 1s
Our first game is about to go live. We have found that the performance of sprite kit is reasonably good. We are moving hundreds of sprites around and have effect nodes and sounds. However you must not dare to set the score. The SKLabelNode is very slow.
after running diagnostics it was found that the following code was the culprit.
scoreLabel.text = [NSString stringWithFormat:#"Score: %d",my_score];
In the diagnostic tool the setText command was showing as the most expensive. We even made sure that it was not being called that often. It still resulted in a lag causing the sprites to jerk/jitter/hickup. Once we removed the line...we got smooth motion.
If we are not able to use the SKLabelNodes inside the game scene, what other options are there?
Be careful you aren't loading the entire font family.
If I load "Chalkboard SE" it will take 4-6 seconds, and appear to work.
But if I load ChalkboardSE-Regular , it's virtually instantaneous ~100ms or less.
Once it's added to the scene, subsequent calls are very quick. But if you transition to another scene, it might re-load, so do it early.
I did some testing with font families first, and the results are pretty catastrophic. Caching strong references doesn't help. https://gilesey.wordpress.com/2015/01/14/ios-spritekit-font-loading-times-of-sklabelnodes/