I have a simple project. A button adds points one at a time to a counter. I then change the scene via another button and return to the original scene. The point counter has gone back to zero. How do i prevent this?
Many ways to achieve this. But for starters you can save the number in Player Prefs.
"PlayerPrefs` is a class that stores Player preferences between game sessions. It can store string, float and integer values into the user’s platform registry"
So forexample this is your button callback function:
public void ButtonCallback()
{
number++;
PlayerPrefs.SetInt("MyNumber", number);
}
To get the number next time you are in the scene, you can get the number using:
int number = PlayerPrefs.GetInt("MyNumber");
You will probably need to check if number exists in the first place when you launch the scene first time using:
PlayerPrefs.HasKey("MyNumber");
Read up more on this on:
https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
Related
I have monster named Fungant in my 2D platform game.
It can hide as mushroom and rise to his normal form.
I try to handle it in code, but I don't know how to get information about finished animation (without it, animation of rising and hiding always was skipped).
I think the point there is to get info about complete of the one of two animations - Rise and Hide.
There is current code:
if (
fungantAnimator.GetCurrentAnimatorStateInfo(0).IsName("Fungant Rise")
)
{
fungantAnimator.SetBool("isRising", false);
isRisen = true;
fungantRigidbody.velocity = new Vector2(
walkSpeed * Mathf.Sign(
player.transform.position.x - transform.position.x),
fungantRigidbody.velocity.y
);
}
if (fungantAnimator.GetCurrentAnimatorStateInfo(0).IsName("Fungant Hide"))
{
fungantAnimator.SetBool("isHiding", false);
isRisen = false;
}
I try this two ways:
StateMachineBehaviour
I would like to get StateMachineBehaviour, but how to get it?
No idea how to process this further.
AnimationEvents
Tried to do with animation event but every tutorial have list of functions to choose (looks easy), but in my Unity I can write Function, Float, Int, String or select object (what I should do?).
I decided to write test() function with Debug only inside, and create AnimationEvents with written "test()" in function field, but nothing happens.
Same as above, no more ideas how to process this further.
I personally would use animation events for this. Just add an event to the animation and then the event plays a function after the animation transition is finished.
For more information on how to use animation events you can click here.
This post may also help you to add an event when the animation is finished.
I hope this answer helps you to solve this problem.
I want to show a text for the first time running like "Hi, my name is NAVI." and then when the player will start the game again the next time it will another text for example "Welcome back."
Using player prefs is probably the easiest solution, though definitely not the only one*.
Due to the lack of boolean playerpref I usually opt to use SetInt/GetInt instead, but that's personal preference. You could also do it with a string or float.
private void Start()
{
if(PlayerPrefs.GetInt("HasLaunched", 0) == 0)//Game hasn't launched before. 0 is the default value if the player pref doesn't exist yet.
{
//Code to display your first time text
}
else
{
//Code to show the returning user's text.
}
PlayerPrefs.SetInt("HasLaunched", 1); //Set to 1, so we know the user has been here before
}
Playerpref stores values between sessions, so the next session will still have "HasLaunched" set to 1. This is however stored on the local device. so users can manually reset it if they'd really want to.
If you ever want to show the "first launch" text again, simply set HasLaunched back to zero, or delete it altogether with DeleteKey("HasLaunched");
*There are plenty of alternative solutions, like storing it in a config file locally, or using a remote database (this would be required if you don't want users to be able to reset it). They would however come down to the same principle. Setting a value to true or 1 somewhere, and checking that value on launch.
I'm using the A* pathfinding algorithm for my 2D game (from my understanding, Unity Nav Meshes don't work in 2D). I would like to be able to pre-calculate navigation grids for all of my scenes, and save them in resource files that can be loaded whenever the player enters a new scene. Rather than having to remember to click "calculate" for every scene -- and remember to recalculate all of my scenes if I make a change to my navigation grids -- I want to be able to programatically have the Unity Editor iterate though each scene and calculate the grids.
Is there a way to create a command in the Unity editor that will iteratively open each scene in the editor and run a method on a MonoBehaviour that's in the scene? Alternatively, is there another way to accomplish what I'm trying to do?
Yes you can!
In editmode you can't use SceneManager but have to use the EditorSceneManager.
First of all you need the scenes you want to iterate.
Could be e.g. a public static field with a list of SceneAsset in the Inspector where you simply reference the scenes
public static List<SceneAsset> Scenes = new List<SceneAsset>();
or you could get them by script e.g. for only use the scenes added to the build settings using EditorBuildSettings.scenes
List<EditorBuildSettingsScene> Scenes = EditorBuildSettings.scenes;
For both you can get a list of the scene paths e.g. using LinQ Select (this is basically a kind of shortcut for a foreach loop) and AssetDatabase.GetAssetPath like
List<string> scenePaths = Scenes.Select(scene => AssetDatabase.GetAssetPath(scene)).ToList();
for the EditorBuildSettingsScene from EditorBuildSettings.scenes you can also simply use
List<string> scenePaths = Scenes.Select(scene => scene.path).ToList();
Now you can iterate over them all and do your stuff by using EditorSceneManager.OpenScene, EditorSceneManager.SaveScene and EditorSceneManager.CloseScene (and if you need it AssetDatabase.SaveAssets)
foreach(string scenePath in scenePaths)
{
// Open a scene e.g. in single mode
var currentScene = EditorSceneManager.OpenScene(scenePath);
/* Do your calculation for currentScene */
// Don't know if it makes changes to your scenes .. if not you can probably skip this
EditorSceneManager.SaveScene(currentScene);
// Finally Close and remove the scene
EditorSceneManager.CloseScene(currentScene, true);
}
// you might be doing changes to an asset you want to save when done
AssetDatabase.SaveAssets();
Before starting you should probably ask to save the current open scene(s) using EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
// Saved => the foreach loop here
}
else
{
// aborted => do nothing
}
Than in order to finally start that method the simplest would be to add a [MenuItem]
public static class Calculation
{
[MenuItem("YourMenu/RunCalculation")]
public static void RunCalculation()
{
// all the before mentioned snippets here
// depending how exactly you want to do it
}
}
This will add a new menu YourMenu with one entry RunCalculation to the top menubar of the Unity Editor.
Note:
Since this uses a lot of types (EditorSceneManager etc) that only exist in the UnityEditor namespace you should either place the whole script in an Editor folder (so it is ignored in the final build) or use pre-processors like
#if UNITY_EDITOR
// ... code here
#endif
so in the build the code is also ignored.
Note that I'm assuming so far you also did your calculation in editmode. The thing is if this calculation relies somewhere aon any Start or Awake method you have to call it manually from that editorscript before running the calculation.
Well, this should be much simpler than it is! Or I'm blinded by my own ignorance!
What I want is some means of getting the string name of the last playable level that was played.
To clarify:
All playable levels are given sequential names - "Level_01" thru "Level_100".
All non-playable scenes are given names such as "Start Menu" and "LevelCompleted" these scenes contain buttons like "Main Menu" and "Replay Last Level".
I am NOT using the UI system and do not wish to do so at all. Rather, I have set up objects with colliders and am using my game mechanics to act as "buttons". For example, when the player shoots the button called "Replay Last Level" the OnCollisionEnter2D should load the last level played.
Whenever a level is completed or lost by the player they are taken to "LevelCompleted" and shown some game statistics (scores, times, etc.). They are given three choices: "Main Menu", "Replay Last Level" and "Continue".
What I need is simply a string variable that always contains the name of the previously loaded PLAYABLE level (i.e. those with names like "Level_01" and not like "Start Menu". )
Then I will use that string to enter into my GameManager script in the appropriate place. The last level played will load when "Replay Last Level" is shot by the player. When the player shoots "Continue" I want to play the next playable level.
So pretty simple concept: I just lost "Level_02". I am now in "LevelCompleted". I shoot "Replay Last Level". I enter "Level_02" again. If, instead, I shoot "Continue" it takes me to the next playable level, in this case, "Level_03" if that level has been unlocked. If it has not been unlocked then the "Continue" button will take me back to "level_02".
BTW, I have a GameManager Script on an otherwise empty game object. It is a singleton that persists to every scene. Within this script are two classes - one is the main public class that is the singleton and does a whole bunch of stuff with data in larger arrays - the other is simply a serializable "public Class GameData". It contains only variables that are written to a file and then reload as needed during the game.
So as is often the case the answer was way simpler than I thought!
In my Gamemanager Script, I set up a public static string variable "currentLevel".
Then on Awake() I did this:
Scene scene = SceneManager.GetActiveScene();
if (scene.name != "LevelCompleted")
{
currentLevel = scene.name;
}
I realized that my "LevelCompleted" scene would never be opened by another "non-playable" scene like "Start Menu" and that it would only ever be opened by a playable level like "Level_xx". By using the conditional, it assures that when that scene "LevelCompleted" is opened, the variable is not updated by the singleton GameManager such that the variable will always contain the last played playable level.
In the scene "LevelCompleted", in the button "Replay Last Level", I have:
private string lastLevelPlayed;
void OnCollisionEnter2D(Collision2D collision)
{
lastLevelPlayed = GameManager.currentLevel;
SceneManager.GetSceneByName(lastLevelPlayed);
}
I've implemented Unity Ads and have:
void Start()
{
Advertisement.Show();
}
In the scrip connected to my unity advertisement GameObject.
When I test my game an advertisement is shown when the scene loads (it a scene that displays results of your game session) and this is what I want, but I don't think it's good to show an advertisement every single time this scene loads, since it will load quite often. Is there some kind of algorithm in the background deciding if the ad should be shown?
I think there should be some kind of limit to how many ads can be shown in x amount of time, not just in unity, but in ads in general, that's why I thought it might be built in already.
So, my question, should I leave it like this, and let the Advertisement plugin to the job, or should I ad some kind of randomizer, like:
int number = Random.Range(1, 2);
if (number == 1) {
Advertisement.Show();
}
to show the ad about 50% of the time?
Full disclosure, I asked this on the unity forums as well, several days ago, and it has yet to be approved (so it's not published), will probably delete that one.
Disclaimer: I have no experience whatsoever with the Unity Ads
framework.
Based on the blog post made by the Unity team, I would say that a simple solution can be to check if the scene showed ads the last time it was loaded and depending on the situation, show a new one or do nothing at all.
We can do that in two steps:
Create a static class for keeping track of when an ad was shown.
Determine on your scene whether the condition is met to show a new one or not based on the value of the static class, and update it.
For example:
public static class AdvertisementTracker
{
/// Create a property or method to store and retrieve whether
/// an advertisement was shown at a given time.
/// You can use a bool, datetime, IList<DateTime> or whatever property that you need.
public static bool AdShown = false;
public static DateTime LastTimeShown;
public static IList<DateTime> TimesShown = new List<DateTime>();
/// You can even have a method that takes the elapsed time between calls and check
/// if they meet the criteria you wish to show your ads.
public static bool ElapsedTimeConditionMet(float elapsedTime)
{
// For example, the elapsed time exceeds 40 seconds, so a new add can be shown.
return elapsedTime >= 40.0f;
}
}
Then, on your scene, attach the following script to your advertisement object:
using UnityEngine;
using UnityEngine.Advertisements;
using System.Collections;
public class SimpleAdScript : MonoBehaviour
{
void Start()
{
Advertisement.Initialize("<the ad ID>", true);
StartCoroutine(ShowAdWhenReady());
}
IEnumerator ShowAdWhenReady()
{
while (!Advertisement.isReady())
yield return null;
if(!AdvertisementTracker.AdShown)
{
Advertisement.Show();
}
AdvertisementTracker.AdShown = !AdvertisementTracker.AdShown;
}
}
The objective of the script is to check if an ad is ready from the Unity framework.
If it is, it then checks if an ad was shown last time. If this is not the case, then it gets shown, otherwise the static class gets updated to be ready for the next iteration.