My Unity game works fine in Unity Editor.
I wanted to test it on my iPhone so I built the app and loaded it in my iPhone via Xcode. Problem is the app seems to be stuck in a loop.
After multiple searches I learned that using the Simulator gives me more info on the problem so I did use it and it returns this:
Job.Worker 10 (31): EXC_BAD_ACCESS (code=2, address=0x133ac1000)
After more searches I've found a way to get more infos:
thread #31, name = 'Job.Worker 10', stop reason = EXC_BAD_ACCESS (code=2, address=0x133ac1000)
frame #0: 0x00007ff836167049 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 41
frame #1: 0x00007ff82e58865d MTLSimDriver`+[MTLSimTexture decompress:expandedTex:srcFormat:destFormat:width:height:destRowBytes:srcRowBytes:] + 209
frame #2: 0x00007ff82e58ad3f MTLSimDriver`-[MTLSimTexture replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:] + 801
frame #3: 0x0000000119112ca7 libiPhone-lib.dylib``UploadTextureData(TextureCreateDataMetal&) + 986 **frame #4:** 0x0000000117f134d0 libiPhone-lib.dylib\``CopyToTextureMemory2DThreaded(TextureCreateData*, TextureUploadMemory&) + 53
frame #5: 0x0000000117ec94b0 libiPhone-lib.dylib``DoCopyTextureDataJob(TextureUploadInstruction*) + 60 **frame #6:** 0x0000000117fc7af2 libiPhone-lib.dylib\``JobQueue::Exec(JobInfo*, long long, int, bool) + 100
frame #7: 0x0000000117fc7e0b libiPhone-lib.dylib``JobQueue::Steal(JobGroup*, JobInfo*, long long, int, bool, bool) + 359 **frame #8:** 0x0000000117fc7fe7 libiPhone-lib.dylib\``JobQueue::ExecuteJobFromQueue(bool, bool&) + 221
frame #9: 0x0000000117fc8243 libiPhone-lib.dylib``JobQueue::ProcessJobs(JobQueue::ThreadInfo*, void*) + 387 **frame #10:** 0x0000000117fc7302 libiPhone-lib.dylib\``JobQueue::WorkLoop(void*) + 286
frame #11: 0x00000001183768cc libiPhone-lib.dylib``Thread::RunThreadWrapper(void*) + 686 **frame #12:** 0x00007ff836176259 libsystem_pthread.dylib\_pthread_start + 125
frame #13: 0x00007ff836171c7b libsystem_pthread.dylib`thread_start + 15
But.. It's mostly gibberish to me..
Context
When my scene loads, my Unity game executes a Firebase Function to get all the characters created by the current player/user. While waiting for the function to run and get data from the server, I display a loading animation.
After getting the data, I display a "card" for each character found. A card contains the name and the level of the character.
After every cards have been initialized and populated with correct data, I disable the loading animation and the scene is finally ready.
Now the user can select a card corresponding to a character and it will update the character 3D model visible in the scene with corresponding character appearance.
Problem
When generating the cards, I pre-select the first character's card. This action involves updating the character preview (character 3D model).
The error in Xcode is thrown as soon as I try to access the character according to my Debug.Log()s.
At the beginning of the scene, before it tries to execute the function, Xcode says:
Unloading 5 Unused Serialized files (Serialized files now loaded: 0)
UnloadTime: 1.856800 ms
Unloading 68 unused Assets / (50.2 KB). Loaded Objects now: 1057.
The character is always present in the scene and I never get rid of it. If the player has no character returned by the Cloud Function, the character (3D model) will just be hidden (gameObject.SetActive(false) in Unity C#) but is still there.
With this, plus the mention of "texture" in the error thrown and the fact that it is thrown when my code tries to access the Character object, they all seem related but what can I do?
It's been two weeks already I couldn't gather more info than this.. I hope this is enough for you to help me because I'm absolutely out of idea to solve this and why my character wouldn't exist anymore if I don't code it to do so.
More infos:
Unity version: 2021.3.17f1
macOS version: Ventura 13.1
Xcode version: 14.2
iOS version (my iPhone and Simulator): 16.2
Thanks #Skywalker and #Sam Varshavchik, your comments helped a lot in fact!
I'll give details if it can help anyone in the future:
I tried really hard trying to get more info before editing my question and add tons of code and explanation after reading your comments.
My character object in my scene looks like this:
Player / PlayerIdentity.cs + others
|_ Model / PlayerModelManager.cs
Player gameobject contains all the Player's scripts (identity, movement, inventory etc.), and Model gameobject contains the actual 3D model (skinned mesh renderers) and a script (PlayerModelManager.cs) to manage it (change hairstyle, gender, change hair color etc..)
When selecting a card in my scene, it goes like this (simplified):
MyScene.UpdateCharacterPreview() > PlayerModelManager.SwitchGender() > PlayerIdentity.SetGender().
Instead of pre-selecting the first character (in Scene Start() method) I want to display on screen, I commented this code and decided to observe how it would behave if I "manually" trigger this code by selecting myself a character's card to show the character preview.
Fortunately, it showed a new error in Xcode -> the infamous NullReferenceException for PlayerIdentity.cs reference in my PlayerModelManager.cs script.
But I didn't understand because in Unity it is not null, the reference is there as it should be. So I did some research and stumbled upon this. Especially the last post.
In my scene, I disable in the Awake() method the whole Model gameobject (and therefore PlayerModelManager.cs) to hide the character while getting data from server. If the player has no character returned by the server, the model stays hidden.
Code used to hide the model is playerModelGameObject.SetActive(false).
The PlayerModelManager.cs gets its reference to PlayerIdentity.cs in its Awake() method.
My assumption is : by disabling the player model in my scene Awake() method, PlayerModelManager.cs doesn't have time to get its reference to PlayerIdentity.cs in its own Awake() method.
So instead, I disabled the player model in my scene Start() method, so the
PlayerModelManager.cs's Awake() method can be executed entirely and get necessary references.
I don't really know why it only happens on iOS builds but now it is solved at least.
If anyone has the knowledge to know why, I would be very interested.
Thanks
Related
Well I know animator system in Unity is very useful for many things but I find myself having my own state machine in the code and somehow the state machine that the animator provides is not accurate due to blend time maybe I dont know, so I find often my character being in state 2 in the animator state machine and state 0 in my own state machine and its crazy as I cant seem to make it match in limit cases when its about to end the action. So I would like to know if there is a way to just say with code "play this animation from frame A to frame B" and loop it or not loop, that would be much better for me, of course I will lose all the blend features but really I will be better, all I can fin in the docs refer to using the animator so far. Thanks a lot for any help regarding this =)
Edit: Forgot to add that I found Animation.Play but apparently this only play animation saved on separate files like when we use the Animation timeline to record a certain motion, but I have a character with a lot of frames there and I dont think it serves in this case (or in my tests it never finds the specified animation at least, maybe i miss somethnig)
before anything, you can your own state machine with Animator. in fact, you don't need to two different state machine for your purposes. (Watch this video here)
and about your question, I found a good answer here: Link
From what I've seen you can either do AnimationState.normalizedTime
which returns the progress of an animation on a scale of 0 to 1. So if
you have a 30 frame animation and you want frame 15, you can do if
(normalizedTime == 0.5)* Or the better and more reliable option is to
use AnimationEvents that fire on specific frames.
*You won't really be able to do this if we're dealing in floats--You can only get the approximate value or you'll have to check greater
then or equal to 0.4 AND less then or equal to 0.6 because the
animation could go faster than the current frame rate or the
normalized time value could be 0.50000001 because of the nature of
float values.
I'm making a 2D game in Unity, and attempting to have one character move after another in order to attack them. In order to make this movement look natural, I want to add a delay, i.e. character follows the exact path other character took, but 0.5 seconds behind.
Since I'm utilizing the State Pattern for my characters behaviour, the movement logic is in a scriptable object. This means I don't directly have access to Update() or IEnumerator, but I work around this by passing in a reference to a MonoBehaviour script attached to the characterGameObject (not sure if this part is relevant, but included just in case there was some weird side effect that I didn't know about).
I first tried to use IEnumerator, with every Execute() call of the scriptable object (which occurs once every game tick) starting a couroutine which first waited for a set amount of time, and then moved the object.
void Execute(StateController stateController){
Vector3 movementVector =
Vector3.MoveTowards(actor.transform.position,targetWithOffset,
Time.deltaTime);
stateController.StartCoroutine(stateController.MoveTorwards(movementVector,
delay));
}
public IEnumerator MoveTorwards(Vector3 movementVector, float delay)
{
yield return new WaitForSeconds(delay);
gameObject.transform.position = movementVector;
}
However, this resulted in an extremely weird glitchy movement, where the character constantly teleported around itself as it moved torwards the target.
Does anyone have insight into this? Am I missing a fundamentally simple implementation, or was my method correct and the glitchy movement has come from a side effect (doubtful, because the code works perfectly without the IEnumerator, and the glitch still occurs when the delay var is set to zero.
character follows the exact path other character took, but 0.5 seconds
behind.
Step 1: Define what the "exact path" is.
Implement a "consumable" point-to-point path structure (ie Queue<Vector3>), and keep recording the path of the first character to it by recording it's current position on an update loop (ie Update(), directly or indirectly).
Step 2: Try to "consume" the path from oldest node to newest.
For now, ignore the idea of a delay; just make sure that the path system to work, and that the movement looks right.
On each update (Update() or indirect) of the follower entity, move towards the next node in the path until it's reached; when it is, "consume" that node (remove from "path", ie .Dequeue()), and any next nodes that are so close as to be considered "reached"; this, obviously, will make the entity start walking towards next node, if there is any "unreached" node left.
Step 3: Delay the following of the path at start and after the path is empty (and/or based on events & triggers if you need more than that).
When the path goes from a length/count of <=1 nodes to >1 nodes, before you start following the first (or next) segment, do the delay; this will create the effect you're looking for.
If the path's length ever gets <=1 again, it means it's being consumed immediately upon creation, which means the "follower" entity has reached the "followed" entity. In this case, from your description, the "follower" entity attacks the "followed" entity; meaning the game is not instantly ended; in that case, to allow the "followed" to distance itself again (as is implied should be the case) after it starts moving, the delay is applied again before the "follower" starts following. --- This approach to the implementation of delay makes the behavior happen automagically to this case, as it's the same check as is done at "start" (actually a loop); no need for secondary checks.
I am to make a mobile painting game in Unity and I've encountered a serious problem: the Input class in Unity is frame-dependent. Thus I can't get the position of touch frequent enough to make my application draw smoothly; as a result I get something like just points on the background, not connected between each other.
I tried to just connect the points that are detected in Unity, and than my result was just the same points connected with lines, of course. I was trying this in Unity Editor with about 180-200 fps, and on mobile phone with 30-50 fps it looks even worse. I expect that I have to get the touch positions somehow in android studio or Xcode, and only then use them in my C# code in Unity editor.
Am I thinking right to use extern from Unity tools, or there is another easier way to do it directly in Unity? If there is none and I am right, can somebody give me some links to guides/tutorials how to do it and integrate it with Unity? I have never worked outside of Unity and have no experience in integration some external tools with it.
Note: I've tried FixedUpdate without any luck - it doesn't matter how often I try to get the position variables, it is about how often they are updated; I also tried Event.current.mousePosition(in unity editor) in OnGUI method, but it also gave me no difference.
Upd: As I have already said, I need to get positions more frequently than the Input class gives me. It updates not fast enough! Here's what I get without connecting the points. The image shows the mousePosition detection frequency in 180-200 fps. On phones it is even slower!
Upd: Here is my simplified code.
void Draw() //this method is invoked every frame
{
//some calculations of x and y based on Input variables
currentMousePosition = new Vector2( x, y); //current mouse position on sprite
if(currentMousePosition != previousMousePosition)
{
while(currentMousePosition != previousMousePosition)
{
mySprite.texture.SetPixels((int)previousMousePosition.x, (int)previousMousePosition.y, 3,3, myColorArray);
if (currentFrameMousePos.x > previousFrameMousePos.x)
previousFrameMousePos.x++;
if (currentFrameMousePos.x < previousFrameMousePos.x)
previousFrameMousePos.x--;
if (currentFrameMousePos.y > previousFrameMousePos.y)
previousFrameMousePos.y++;
if (currentFrameMousePos.y < previousFrameMousePos.y)
previousFrameMousePos.y--;
}
} else mySprite.texture.SetPixels((int)currentMousePosition.x, (int)currentMousePosition.y, 3,3, myColorArray);
previousMousePosition = currentMousePosition;
}
//mySprite.texture.Apply() is invoked independently in another place to improve performance
The issue is, it is not possible to queue up touch positions that occurred mid frame so by "Quickly" sliding your finger you will miss certain texels on your image. You should look at this line formula Bresenham's line algorithm. This is super fast, and all integer math. Inside your Update() function call this method.
Vector2 oldPoint;
public void UpdateDrawPoint(Vector2 newPoint){
BresenhamLine(newPoint, oldPoint);
oldPoint = newPoint;
}
Firstable I am not a PRO programmer but only a student who hava a little problem with an excelent library Midi-Dot-Net.
I use a Midi-Dot-Net library to write a simple application in Visual Studio in C# language. But I stuck on a very confusing problem.
I placed a little code into Form1.cs
public void NoteOn(NoteOnMessage msg) {
if (InvokeRequired) {
BeginInvoke(noteOnHandler, msg);
return;
}
inputStatusLabel.Text = String.Format("{0}", msg.Pitch);
String nutka = inputStatusLabel.Text;
if (nutka == "A0") {
clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
}
}
So, I placed new String and called it nutka, and nutka will receive name of the pressed note on my USB MIDI Keyboard. Then I placed IF statment, and compared nutka to "A0" (first note on the keyboard).
Then if it's "A0" I pressed my outputDevice plays specific note. And it plays but it plays twice, one - when I press key (with note A0) on keyboard and second time - when I release that key.
I did a breakpoint on public void NoteOn(NoteOnMessage msg) and noticed that an application returns here twice and plays twice that note, still don't know why.
One more thing, there is a method public void NoteOff(NoteOffMessage message), but it seems not working.
I really can't figure it out, and I'm looking for any help.
UPDATE
...
UPDATE
...
UPDATE
Another problem appears (the first part was resolved thanks to CL and Chris Dunaway advice and step-by-step Justin explanation).
Thank you Justin :) i see life without any problems is not possible :)
With clock.Schedule i can play only the MIDI sound but i want to play example piano notes (wav file format) and in 4-5
weeks my college will help me recording my own piano sounds for every note. I also want to play them simultaneous.
I thought everything will be just fine and now... got problem with simultaneous playing. I was trying to check three possibilities:
1) I was trying to play piano sounds from basic notes library i have and use SoundPlayer for it:
SoundPlayer noteA0 = new SoundPlayer(Properties.Resources.A0);
noteA0.Play();
i use it for every note statement with different SoundPlayer name (depend on note name) and what i noticed is - i can't play notes simultaneously.
2) so i used next WMP library and WindowsMediaPlayer:
for example:
var noteA0 = new WMPLib.WindowsMediaPlayer();
noteA0.URL = #"c:\sounds\piano\A0.wav";
Ok... it plays simultaneous but it looks like the more notes i play or i just play a song the bigger latency i got and finnaly my programm stuck on playing anything...
3) i was trying to use Microsoft.DirectX.AudioVideoPlayback:
Audio noteA1 = new Audio(#"C:\sounds\piano\A1.wav");
noteA1.Play();
i started my programm, pressed a key and boom! crashed with an error message:
An unhandled exception of type 'System.BadImageFormatException' occurred in Midi.dll
Additional information: Could not load file or assembly 'Microsoft.DirectX.AudioVideoPlayback.dll' or one of its dependencies.
It is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)
Of course i didn't forget to use:
using System.Media;
using Microsoft.DirectX.AudioVideoPlayback;
using Microsoft.DirectX;
Right now i have no idea what can i do more and again - i need a help of an experienced person :)
Expanding on CL.'s answer, here is the sequence of events that is probably happening:
You push a key on your MIDI keyboard which sends out a Note On message, with a Pitch of A0, and a velocity (the exact velocity may vary every time).
Your code receives this and, since it matches your if statement, sends out a Note On message, with a pitch of A0, and a velocity of 80.
Here's where it gets tricky. Some MIDI devices send a corresponding Note Off message with the same Pitch when you release the key. Other devices will send a second Note On message with the same Pitch, but with a Velocity of 0. These two types of message are (or should be) functionally equivalent, and each device can do either to stop a note playing (or even both). So,
You release the key on your keyboard which sends out a Note On message, with a Pitch of A0, and a Velocity of 0.
Your code receives this and, since it also matches your if statement, sends out a Note On message, with a pich of A0, and a velocity of 80.
Since a Note On with a Velocity of 0 is also a Note Off, what happens is your code is turning your keyboard's "Note Off" back into a Note On, thus playing the sound twice.
As Chris Dunaway suggested, you need to determine if a Note On is actually a "Note Off" by testing for a Velocity of 0.
if (nutka == "A0" && msg.Velocity != 0) {
clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
}
The MIDI 1.0 Detailed Specification says:
MIDI provides two roughly equivalent means of turning off a note (voice). A note may be turned off either by sending a Note-Off message for the same note number and channel, or by sending a Note-On message for that note and channel with a velocity value of zero. The advantage to using "Note-On at zero velocity" is that it can avoid sending additional status bytes when Running Status is employed.
Due to this efficiency, sending Note-On messages with velocity values of zero is the most commonly used method. However, some keyboard instruments implement release velocity where a Note-Off code (8nH) accompanied by a "velocity off" byte is used. A receiver must be capable of recognizing either method of turning off a note, and should treat them identically.
This is my first post here so please be gentle. This is my first time making a game in C# XNA (I know it's not supported anymore). I am attempting to spawn rocks on the ground the the player collides with. I have made collision with many other objects in the game, but for some reason it's not working on these rocks.
Whenever I run the code I get a Null reference exception on line 146 of my room.cs (see first link below)
I have only tried adding collision to the first rock in the first case of the switch statement in my room.cs, so ignore the the other statements in the switch beyond line 146, they are there just to draw the textures in the correct place.
If there is anything more I need to add please say so. Like I said this is my first time posting here so I may not be very good at this.
Room.cs
http://pastebin.com/WeYSpBZa (line 146 is where the error occurs on runtime)
Rock.cs (didn't know if you needed this to help figure it out, so I added it anyway)
http://pastebin.com/6NYZrFir
Your rocklist is null. Instantiate this field in the constructor : rockList = new List<Rock>();