I developed a game using Unity 2d for Android and WP8. The games is about a player that goes through a level eating orange. When the player collides with an orange it plays a soundclip.
So, when you play the first time, there is no matter, all sounds play well. Then when you choose go to menu option to start again the level, the game crashes at the first collide. If then you chose menu, and reload the level, it works fine.
So it works well once , then fails once, then works well once, and go on the same.
This erros happens in WP8 and not in Android.
The problem is in WP8 with this code:
void OnTriggerEnter2D(Collider2D collider){
if (collider.tag == "Player") {
NotificationCenter.DefaultCenter ().PostNotification (this, "IncrementarPuntos", this.puntosGanados);
AudioSource.PlayClipAtPoint (itemSoundClip, Camera.main.transform.position, itemSoundVolume);
Destroy (this.gameObject);
}
}
the line with error is
AudioSource.PlayClipAtPoint (itemSoundClip, Camera.main.transform.position, itemSoundVolume);
because itemSoundClip is null.
I dont understand why itemSoundClip sometimes goes null.
this is the exception
$exception {System.NullReferenceException: Object reference not set to an instance of an object.
at UnityEngine.AudioSource.PlayClipAtPoint(AudioClip clip, Vector3 position, Single volume)
at Item.OnTriggerEnter2D(Collider2D collider)
at Item.$Invoke0(Int64 instance, Int64* args)
at UnityEngine.Internal.$MethodUtility.InvokeMethod(Int64 instance, Int64* args, IntPtr method)} System.Exception {System.NullReferenceException}
Something important to know.
My orange item is a prefab. This item have a script which I add a clip sound(itemSoundClip)
In my scene I use a Generator script which takes that orange item, and creates instances of it in a random time with this line
Instantiate (obj [Random.Range (0, obj.Length)], transform.position, Quaternion.identity);
Maybe when Instantiates ocurrs, the item cant load the clip?
In my unity project, i play sound in WP8:
public AudioClip coinCollect;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "coin_gold")
{
AudioSource.PlayClipAtPoint(coinCollect, other.gameObject.transform.position,1);
gold++;
Destroy(other.gameObject);
}
}
And in Unity Inspector i add my sound
I find a solution. If the variable of itemClipSound is null, then I load the sound through Resources with this.
if (itemSoundClip == null)
itemSoundClip = (AudioClip) Resources.Load("cogerItem");
Related
When I press the home key and return to my game, a black screen occurs.
I read online that is because textures are lost.
So, I want to know how to keep the texture valid when I resume the game. Are there any reasons for the problem? Any advice will be appreciated.
Generally,There are two reasons for this problem.
Firstly,The resource of Texture have been disposed.
Secondly,You have load repeated resources.
My problem is the second problem.
Because I always create new world in Screen's show method.
My solution,I just need to judge whether the world is null.
I only need create the world when it is null.
Based on your reply (as an answer), you can check if the world is null by checking if it's null.
public void resume() {
If(world == null) {
System.out.println("world is null");
// create world
} else {
// do stuff when it's not null.
}
}
Of course you can reference the world by making it public static when you declare it in play state so you can use it in your core code that extends the ApplicationAdapter.
Edit: Running some tests, I guess you need to set world = null; after calling world.dispose; in the dispose() method.
[Question]
On Windows Phone 8.1, what exactly happens in between the time when the user leaves the app and the OnSuspended event fires? I'm having trouble with the ability to manage objects in that span, in particular MediaCpture object.
To better explain the problem, here is the scenario:
The user is on a page with a video preview being pumped to a CaptureElement
The user taps the Start button
The user taps Back button and returns to the page with a broken MediaCapture
With WinRT there isn't an ObscuredEvent and OnNavigatingFrom doesn’t fire unless you’re going to another page in the same Frame. After some investigation, I've found that the only event that fires is Window.Current.VisibilityChanged
I've gone ahead and hook it when the page is NavigatedTo and unhooked in OnNavigatedFrom (see ex2 below). Inside the event, I check for parameter that tells if the app is hiding or showing and dispose/initialize accordingly(see ex.1 below).
[Problem]
However, this only works with the debugger attached. If I do this without the debugger attached, it doesn't reinitialize and frequently crashes the camera and I have to literally reboot the device.
Code Example 1 (note: e.Visible == false is leaving the app and true when returning)
async void Current_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
{
if (!e.Visible) //means leaving the app
{
await DisposeAll(); //cleans the MediaCapture and CaptureElement
}
else
{
if(mediaCaptureManager != null) await DisposeAll();
await Initialization(); //set up camera again
}
}
Example 2 (hooking into the event)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.navigationHelper.OnNavigatedTo(e);
}
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.VisibilityChanged -= Current_VisibilityChanged;
this.navigationHelper.OnNavigatedFrom(e);
}
[Update: Resolution]
Instead of using VisibilityChanged, hook into Window.Current.Activated on the page's constructor. With the debugger completely detached, the Activated event will provide the WindowActivationState parameter in the WindowActivatedEventArgs. Like this:
private async void CurrentOnActivated(object sender, WindowActivatedEventArgs e)
{
if(e.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//dispose MediaCapture here
}
else if(e.WindowActivationState == CoreWindowActivationState.CodeActivated || e.WindowActivationState == CoreWindowActivationState.PointerActivated)
{
//initialize MediaCapture here
}
}
See my answer in https://stackoverflow.com/a/28592882/3998132. Using Window.VisibilityChanged in conjunction with your Page\UserControl Loaded\Unloaded handler should solve your issue I believe.
Using Window.Activated is less desirable than Window.VisibilityChanged because Activated relates to being visible AND having focus where as VisibilityChanged only pertains to visibility. For showing a preview having focus is not applicable. Since Windows Store apps on Windows Phone can only have one Window showing there is no difference in using either however if your app becomes universal and runs on let's say on Windows 8+ Modern shell (which can show multiple Store apps with the Snap window feature) or Windows 10 desktop (which can support multiple Store apps showing at the same time) you will not want to stop preview when a user changes focus from your app but your app is still showing.
I'm not sure if it wouldn't be more suitable to use Suspending/Resuming events. Note only that in this case, you will have to debug it properly - it behaves little different while being run with/without debugger attached.
As for the code - hooking your event in OnNavigatedTo/OnNavigatedFrom is not a good idea - when the OS suspends the app and you are using SuspensionManager then OnNavigatedFrom will be called, but when you go back to your app (resume it), then OnNavigatedTo will not be called.
Using Window events may also work here, but why not subscribe it once, somewhere in constructor? - it's window-wide and hence in phone there is only one window, which stands for app, then subscribe once. In this case, you may add a line that recognizes the current page in window and if that page contains mediacapture then dispose (create similar). Then you can also dispose/initialize in navigation events in case user doesn't leave your app and just navigate.
I've been researching this issue for hours and while I've found somewhat similiar situations, i have yet to find a simple fix. Basically I have a timeline where some animation plays. Eventually I get to my main game screen (frame 256) where a stop(); is called and the user then gets to click on one of 3 doors. Clicking on any door takes the user ahead a bunch of frames and they get to play a game. Once the game is done or the user clicks back, it takes the user back to the original frame (frame 256) and every single time it does this, it says my "upDoor" is a null reference and then the upDoor button(instance of upStairsDoor button) is no longer on the stage.
This seems to happen regardless of which door the user picks first. If the user picks the upDoor and plays the minigame there or picks the outsideDoor and plays that specific minigame, when the user returns to this frame (frame 256), it throws this error on the door and then of course because it throws an error, nothing else works at that point and I have to exit the game.
It's not a typo! Please don't suggest I check my instance names. As I mentioned, the door works fine the first time you get to the frame, it's just when you go back to it. I've read that it might have to do with the garbage collector but when we return to the frame, shouldn't it recreate all of the instances that I've placed to the stage? It doesn't error on ANY other button or movieClip that I've dragged to the stage, only this one particular door.
I forgot to mention that it's error'ing on a line of code that references the upDoor button. I have these lines of code here...(frame 256)
if (downDoor.enabled) {
downDoor.enabled = false;
}
if (upDoor.enabled) {
upDoor.enabled = false;
}
if (outDoor.enabled) {
outDoor.enabled = false;
}
What these do is disable the doors until the user clicks another object on the screen which then runs a function that sets all the doors to enabled. The error in question is saying I can't access a property of a null reference.
Thanks for the input guys. What ended up being the solution for me was to implement all of the movieclips and buttons programatically when the frame loads and then remove them all when I switch frames. That way, everytime the frame is reloaded from a gotoAndPlay, everything gets re-created again.
I'm currently playing around with some AS3 platform gaming, and trying to go with a cleaner object-based approach for platforms. In short, I'm trying to detect if the player object is colliding with platform - ala:
if (!player.hitTestObject(this)) {
//player falls
}
However, the problem is in actually referencing the player object - the player is at the following location (from the stage); manager.player - wheras the platforms are at manager.level.foreground.
Is there any way to actually reference the player object from within the foreground object as listed above, without passing in a constructor from the player to each and every instance of the platform?
you could do
if (!this.parent.parent.player.hitTestObject(this)) {
//player falls
}
but i strongly advise against this as it is extremely inflexible to changes, and cause a possible debugging nightmare:)
would it not be neater to let the manager handle the collisions between it's children?
You can get a static reference to the place that the player object is created in. In that class, you basically return a reference to the player.
I made a Flash project in FlashDevelop to create an Ad.
The Preloader is setup by making use of the Additional Compiler argument:
-frame=NameOfLabel,NameOfMainClass
My main class is simply called "Main", at the top / default package level.
So frame #1, being the Preloader portion of the SWF, has:
Very few bitmaps, vector-graphics and text (to stay under 50kb);
A YouTube video player in the center (does not count in the filesize limit);
The frame #2 has everything else (the Main class basically embeds all it's dependencies). This includes:
Assets from precompiled SWF (Bitmaps, Symbols, Fonts, XML data);
All classes imported (this is recursive for every classes importing other classes);
Now my big problem is, my client requested the "replay" functionality long after I've completed 99.9% of the project.
I have the project more-or-less broken into different states (Intro, Ready, SlideMenu, etc.), but I'm not sure how I can easily reset the Flash movie back to the very beginning (where it was preloading and showing the YouTube video).
The easy solution would be to simply call an ExternalInterface JavaScript method that would refresh the Flash container, BUT I don't think I have control over what's going on the HTML / JavaScript side.
Is there an easy way to invoke a replay function from AS3?
Would not simply going back to frame 1 do the trick ?
The following seems to do the trick!
private function onReplayClick(e:MouseEvent):void {
var theStage:Stage = this.stage; //Temporarly store the stage.
//Kill any animations happening:
TweenMax.killAll(); //3rd party, may not be applicable for you :P
//Remove ALL containers / child DisplayObjects
SpriteUtils.recursiveRemove(theStage); //custom-made
// (this object is no longer attached to the stage at this point)
//Nullify any Singleton / Static variables:
Main.INST = null;
// Load the 'bytes' of the current SWF in a new Loader, then...
// add it to the stage
var swf:Loader = new Loader();
swf.loadBytes( theStage.loaderInfo.bytes );
theStage.addChild( swf );
}
By doing a deep recursive cleanup of the DisplayObjects, and any static variables (like Singleton instances), it leaves you with a blank stage.
After that, you can instantiate a new Loader that will load the SWF itself via the current LoaderInfo's bytes property.
Add the Loader to the Stage, and you're up and running again!