Unity console doesn't work properly - c#

Usually, when I would print something using Debug.Log() it would show up in the console and I could double click on it to go to the function call. Also, a single click would expand the text to expose a kind of history of the calls (a certain function calls another function which called another one, and so on. Until the Debug.Log() was called).
But now I only get this weird behavior where the functions calls are replaced by the memory addresses of the stack.
I can't post images yet so here's what the console looks like
I can still manage to find where the call occurred by expanding the message but it's a nightmare
Can you find the call?
Hint: it's from PointCloudGenerator.cs at line 290
it wouldn't be so bad but the thing is that the double click behavior doesn't work at all and it's quite frustrating to try and figure out where the call originated. The exact same thing happens with warnings and errors too.
EDIT: I'm using Unity 5.6.3p3 and my editor is Visual Studio 2017 Enterprise
This is where the log was called:
private IEnumerator ReadCornerData(long capacity, CloudBounds cloudBounds)
{
List<Vector3> corners = new List<Vector3>();
List<Vector3> borders = new List<Vector3>();
using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateOrOpen("Global\\CornerData", capacity, MemoryMappedFileAccess.ReadWrite))
{
using (MemoryMappedViewAccessor accessor = memoryMappedFile.CreateViewAccessor())
{
byte dataAvailable = 0;
accessor.Write(0, ref dataAvailable);
accessor.Write((int)capacity / 2, ref dataAvailable);
int memIndex = 0;
while (dataAvailable != 0xF)
{
accessor.Read(memIndex, out dataAvailable);
yield return new WaitForEndOfFrame();
}
UnityEngine.Debug.Log(dataAvailable);
}
}
}
`
It's in a coroutine but it does the same thing when it is anywhere in my code really

Right click on the Console window tab/title box and set the Stack Trace Logging to Script Only instead of Full.
In most cases, this should also fix the "double click to open" issue.

Related

In Unity, I want to change the scene and then change the text displayed, but the scene change always happens last

I'm a beginner and this is my first post here so please let me know if I could do anything better.
Using PUN 2 in Unity, I'm trying to return a connection error message when the user attempts to connect to a Photon server but fails.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //Library that provides utilities for scene management
using Photon.Pun; //Library for Photon, provides networking utilities
using Photon.Realtime; //Helps solve problems relating to matchmaking and fast communication
using UnityEngine.UI; //
public class MenuMan : MonoBehaviourPunCallbacks
{
public override void OnDisconnected(DisconnectCause cause) //Callback for when device fails to connect to server. Parameter 'cause' is the cause of this failure
{
Debug.Log("failed :("); // FOR DEBUGGING
Debug.Log(cause); //Prints in the console the cause of this connection failure
DisplayErrorMessage();
}
public Text Message;
public string MessageValue = " ";
public void DisplayErrorMessage() //Method that displays a connection error message to the user
{
SceneManager.LoadScene("Character Select Menu"); //Ensures user is on the Character Select menu
MessageValue = "AAAAAAA";
//Message.text = MessageValue;
Debug.Log(Message.text);
Debug.Log(MessageValue);
}
}
When I run this code, the text "AAAAA" flashes for a second, then disappears. Through testing I found out this is because the message displays first for some reason, and only after does the scene change thus resetting the text.
I tried using coroutines to delay MessageValue from being altered until the scene changed:
public override void OnDisconnected(DisconnectCause cause) //Callback for when device fails to connect to server. Parameter 'cause' is the cause of this failure
{
StartCoroutine(GoToCSM());
DisplayErrorMessage();
}
IEnumerator GoToCSM()
{
Debug.Log("cor started");
SceneManager.LoadScene("Character Select Menu")
yield return new WaitForSeconds(3);
DisplayErrorMessage();
Debug.Log("Done");
}
public Text Message; //Initialises a 'Text' type object, which will be set to the Connection fail message
static string MessageValue = " "; //Initialises a string which will be written to the 'text' component of the above object
public void DisplayErrorMessage() //Method that displays a connection error message to the user
{
MessageValue = "AAAAAAA"; //Writes the string to be displayed to MessageValue
Message.text = MessageValue; //Sets the above text to the 'text' component of the Message object, thus displaying it on the screen
}
However the coroutine never goes past the yield statement. It just stops at the yield statement and doesn't continue (even the Debug.Log("Done") doesn't get logged).
But when I tried switching some things round and put SceneManager.LoadScene("Character Select Menu") beneath the yield statement, that was executed just fine, as well as the debug statement below. I have no idea why this could be, and am very confused.
This was meant to be an extremely simple 10 minute task and I've wasted days trying to figure out what to do now. Any help would be extremely greatly appreciated. Thank you!
When switching scenes the object running the coroutines gets destroyed. Which results in it never executing the delayed code in the coroutines, this also applies when loading the same scene as you have currently loaded.
Unity reloads the whole scene, it resets everything!
This is also the reason why you see the text flashing for a few seconds. You set the text of some component in your scene, then unity reloads it and its reset.
SceneManager.LoadScene is not instant it just tells unity to start loading the Scene and then switching to it when ready.
Which by the way is not a very performant thing to do and should only be done when you need to really reset it.
If you want to pass values such as cause of disconnection from one scene to another you should use static variables.
These are not stored in objects(that get deleted on scene load). They are static and get saved when switching scenes.
It would help if you shared some more details about the structure of your project. That can help us find a solution that suits your needs.

Improve multi-threaded code design to prevent race condition

I'm running into an issue that I'm not sure is solvable in the way I want to solve it. I have a problem with a race condition.
I have one project running as a C++ dll (the main engine).
Then I have a second C# process that uses C++/CLI to communicate with the main engine (the editor).
The editor is hosting the engine window as a child window. The result of this is that the child window receives input messages async (see RiProcessMouseMessage()). Normally this only happens when I call window->PollEvents();.
main engine loop {
RiProcessMouseMessage(); // <- Called by the default windows message poll function from the child window
foreach(inputDevice)
inputDevice->UpdateState();
otherCode->UseCurrentInput();
}
The main editor loop is the WPF loop which I don't control. Basically it does this:
main editor loop {
RiProcessMouseMessage(); // <- This one is called by the editor (parent) window, but is using the message loop of the (child) engine window
}
The RawInput processor which is called sync by the engine and async by the editor:
void Win32RawInput::RiProcessMouseMessage(const RAWMOUSE& rmouse, HWND hWnd) {
MouseState& state = Input::mouse._GetGatherState();
// Check Mouse Position Relative Motion
if (rmouse.usFlags == MOUSE_MOVE_RELATIVE) {
vec2f delta((float)rmouse.lLastX, (float)rmouse.lLastY);
delta *= MOUSE_SCALE;
state.movement += delta;
POINT p;
GetCursorPos(&p);
state.cursorPosGlobal = vec2i(p.x, p.y);
ScreenToClient(hWnd, &p);
state.cursorPos = vec2i(p.x, p.y);
}
// Check Mouse Wheel Relative Motion
if (rmouse.usButtonFlags & RI_MOUSE_WHEEL)
state.scrollMovement.y += ((float)(short)rmouse.usButtonData) / WHEEL_DELTA;
if (rmouse.usButtonFlags & RI_MOUSE_HWHEEL)
state.scrollMovement.x += ((float)(short)rmouse.usButtonData) / WHEEL_DELTA;
// Store Mouse Button States
for (int i = 0; i < 5; i++) {
if (rmouse.usButtonFlags & maskDown_[i]) {
state.mouseButtonState[i].pressed = true;
state.mouseButtonState[i].changedThisFrame = true;
} else if (rmouse.usButtonFlags & maskUp_[i]) {
state.mouseButtonState[i].pressed = false;
state.mouseButtonState[i].changedThisFrame = true;
}
}
}
UpdateState() is called only by the engine. It basically swaps the RawInput to the currently used input. This is to prevent input updating in the middle of a frame loop (aka. during otherCode->UseCurrentInput();)
void UpdateState() {
currentState = gatherState; // Copy gather state to current
Reset(gatherState); // Reset the old buffer so the next time the buffer it's used it's all good
// Use current state to check stuff
// For the rest of this frame currentState should be used
}
MouseState& _GetGatherState() { return gatherState; }
void Reset(MouseState& state) { // Might need a lock around gatherState :(
state.movement = vec2f::zero;
state.scrollMovement = vec2f::zero;
for (int i = 0; i < 5; ++i)
state.mouseButtonState[i].changedThisFrame = false;
}
So as you can see the race condition happens when RiProcessMouseMessage() is called while Reset() was called in the main engine loop. If it wasn't clear: The Reset() function is required to reset state back to it's frames default data so that the data is read correctly every frame.
Now I'm very much aware I can fix this easily by adding a mutex around the gatherState updates but I would like to avoid this if possible. Basically I'm asking is it possible to redesign this code to be lock free?
You are asking lock-free which is not quite possible if both ends alter the buffer. But if you ask lock that is optimized and almost instantaneous then you can use FIFO logic. You can use the .net's ConcurrentQueue "https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=net-5.0" to write updates and poll updates from this queue.
If you really get rid of the lock then you may check lock-free circular arrays aka lock-free ring-buffer,
If you want to dig deeper into hardware level to understand the logic behind this then you can check https://electronics.stackexchange.com/questions/317415/how-to-allow-thread-and-interrupt-safe-writing-of-incoming-usart-data-on-freerto so you will have an idea about concurrency at the low-level as well; With limitations, a lock-free ring buffer can work when one end only writes and the other end only reads within known intervals/boundaries can check similar questions asked:
Circular lock-free buffer
Boost has well-known implementations for lock-free: https://www.boost.org/doc/libs/1_65_1/doc/html/lockfree.html

Issue with loaded Midi.Net DLL

Lately I'm having some issues in different applications that I have made. All of these applications use a Midi-controller to send midi-notes to a lighting desk. The issue is the same for all of these applications.
In runtime, when I'm working on the application, it sometimes occurs that my complete application freezes. I don't get any warningmessages, nor is the debugger popping up to tell me what's wrong. It always occurs when I want to play a midi-note. The only thing I can do at that point, is to reboot the entire machine, which is not that funny.
Because the application hangs and I don't get any debugging information, I'm certain it has to do with the DLL I use to send Midi-notes and that there's an issue there or in the way I have implemented the dll.
I've posted the code below and I would appreciate it, if someone could tell me what I'm doing wrong?
This is de code in the mainform initializing the Midi
MidiTools midi;
private void initMidi()
{
midi = new MidiTools();
midi.Enabled = true;
}
The initMidi() is called from inside the Form_Load-function.
The code to play a Midi-note is:
midi.playNote(22,0)
Below is the code inside the MidiTools-class file
using Midi;
namespace MidiTest
{
class MidiTools
{
public bool Enabled { get; set; }
OutputDevice outputDevice = OutputDevice.InstalledDevices[1];
Channel selectedChannel = Channel.Channel16;
int velocity = 127;
private void playNote(int noteNumber, int delay)
{
// CONVERT THE NOTE
Note selectedNote = (Note)noteNumber;
if (Enabled)
{
Thread.Sleep(delay);
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss NOTE: ") + selectedNote.ToString());
outputDevice.Open();
outputDevice.SendNoteOn(selectedChannel, selectedNote, velocity);
outputDevice.Close();
}
}
}
}
The Midi-library itself was downloaded from this link:
https://midi-dot-net.googlecode.com/files/midi-dot-net_src_1.0.5.zip
In the past I've tried multiple ways of fixing this problem. I've tried inserting a bigger delay, I've tried cueing the messages in a list and processing them one by one to prevent a midinote from being asked to play wile another note is still being sent, but none of those helped.
In 98% of the cases it works, it's just occasionally that it freezes on me.
I'm using the M-Audio Midisport controller. (http://www.m-audio.com/products/view/midisport-4x4-anniversary-edition) but it has also happened on other controllers.
So any help is greatly appreciated.
Best regards,
Kenneth

Xamarin.Mac NSThread.Start() stack overflow

I've got a rather complex Xamarin.Mac application. In fact, it's a windows forms application, but we're using Mono for Mac compatibility with a native Mac GUI. One of our business logic components involves watching the filesystem for changes using FSWatcher. Unfortunately, FSWatcher on Mac is horribly broken, leaving us to use the native FSEvents API via Xamarin.Mac.
Deep down in business logic, I've got a custom class called CBFileSystemWatcher which wraps the .NET FSWatcher, and on mac provides an adapter between the FSWatcher-expecting business logic and FSEvents on mac. INSIDE this compatibility class, I've got
private FSEventStream eventStream;
//...
this.eventStream.ScheduleWithRunLoop (NSRunLoop.Main);
which schedules the filesystem events on the main run loop. Unfortunately, this means the GUI blocks FS event handling, so suddenly if a modal dialog is open, for example, fs events stop getting processed.
My thought is to create a new runloop for the FS event scheduling, which I figure looks like
NSThread.Start(()=>{
// Some other code
this.eventStream.ScheduleWithRunLoop (NSRunLoop.Current);
});
The snag is, I think, that this code runs inside maybe two other layers of thread starts. For testing purposes, I've got the following code where I NEED the above code:
NSThread.Start(()=>{
int i = 0;
});
with a breakpoint on the middle line to determine whether it was hit. 9 times out of ten I get the following stack overflow:
Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0
Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0
(the addresses change, though often recur)
One time out of ten the code works exactly as expected and I break on i=0
To test this further, I placed the above test inside my main AppDelegate.cs FinishedLaunching method. There, the code reliably works.
To further confuse matters, I placed the following code at the start of FinishedLaunching:
var fooThread = new Thread(() =>
{
var barThread = new Thread(()=>{
NSThread.Start(() =>
{
int i = 4;
});
});
barThread.Start();
});
fooThread.Start();
With breakpoints on fooThread.Start();, barThread.Start();, and int i = 4; the code works exactly as expected, where the points are hit in reverse order.
My question is, does anyone have any ideas on how to even begin deubgging this? The SO is so out of the blue I don't even know where to start.
A year later, I have this answer for you:
http://forums.xamarin.com/discussion/37451/more-modal-problems-nsmenu-nsstatusitem

While loop not working as intended in Pong game

I am attempting to create a Pong game in C# with Visual C# Express 2010.
For the most part, I have the main idea of the game finished, however I have an issue with the ball moving. I have create a for loop, like this:
public void ballSet()
{
if (!Values.isPaused)
{
while(true)
{
if (Values.totalTime.Elapsed.Seconds > 1)
{
Values.totalTime.Restart();
ballMove(50, 50);
}
}
}
}
public void ballMove(int factorX, int factorY)
{
Values.ballLastX = ball.Location.X;
Values.ballLastY = ball.Location.Y;
this.ball.Location = new Point(this.ball.Location.X + factorX, this.ball.Location.Y + factorY);
}
The "ballMove(50, 50);" is just for testing purposes at the moment. The issue is that when ballSet() is called, the form seems to close with a code of 0, meaning that there was no error.
I call ballSet() over here.
public Pong()
{
InitializeComponent();
ballSet();
Values.totalTime.Start();
}
I have already checked and the program does somewhat work when I remove the while loop in ballSet(), as well as the if statement checking the stopwatch (Values.totalTime is a Stopwatch). Obviously since the while loop is commented out, ballMove() is only called once, and the the ball moves once and stops.
Does anyone know how to fix this? I want the ball to be moving constantly, while still having it possible to perform other tasks such as moving the bat in Pong.
This is the output I can give you while running Pong.
http://pastebin.com/nj1pdg3U
From looking at your code, the while loop will never end. I know that's not your reported behaviour, but try swapping ballSet() and Values.totalTime.Start(); around.
Like so:
Values.totalTime.Start();
ballSet();
This is because (in theory) the call to ballSet() will wait for a return, and the totalTime counter will never start, therefore never entering your IF block in the loop.

Categories

Resources