Alright, so basically I have this slight issue that I'm trying to get a fix for. I'm using a GameObject called GameControl that I have learned from the Unity Tutorial guy. What I'm trying to do is be able to edit the options after they have been loaded. I can get them to save and load just fine. I had to switch the options up differently for the Singleplayer and Multiplayer mode because they have different save and load data. Now when I save/load this data back. I'm having troubles getting them to edit after loading, because it seems to be continuously loading the saved data, so if I were to make a change, it alters back to the saved data.
When I was just following along, I had this when the options were both the same and I used:
void Start() {
GameControl.control.Load();
}
Which seemed to work just fine, but now I have two different load files SP Options and MP Options. And I just don't know where to put these files, I thought maybe in my Switch Operation where I have it to load when I click Singleplayer, or when it loads Multiplayer at click. But this is where I have the continuous loading problem. And when I go to edit the options in the Window, it reverts back, please help me understand where to put these loads. I don't want to have a load button, I don't like the idea of that, I want it to be an automatic load, when you click Singleplayer (get singleplayer load files); and Multiplayer (get multiplayer load files).
void OnGUI() {
GUI.skin=mainSkin;
menuSelection=GUI.SelectionGrid(new Rect(Screen.width*.025f,Screen.height*.025f,buttonW,buttonH), menuSelection, button, 1);
switch(menuSelection) {
default:
break;
case 0:
windowRect=GUI.Window(0,windowRect,SPOptionsWindow,"Singleplayer Options (Pre-Game)");
break;
case 1:
windowRect=GUI.Window(1,windowRect,MPOptionsWindow,"Multiplayer Options (Pre-Game)");
break;
case 2:
LeaderboardsWindow();
break;
}
}
Here is where I have it loading the Load files; however I am unsure this is where it's supposed to be unless there is more code to make it stop running after the first time it loads. I've also tried to load it in the SPOptionsWindow(); and MPOptionsWindow(); but I get the same result.
Ahhhhh, long time fix! So basically what I did to correct this was to add more code in the GameControl.cs file. Although some features aren't the same, all I had to do was just recreate the same types with different naming conventions. More code, however it definitely works. However temporarily. Thinking long-term, however, I'm not sure if this is the exact fix that I would appreciate to have.
Problems may occur: •The actual options taking place would require more code to implement. •Maybe I won't be able to implement more code, but I would have to change it back to being the same?
These I don't really know until I reach that bridge, but however, it's a fix for now, and if there are any other answers to this, please throw your idea out there :)
Related
This is my first question here so please go easy on me. :)
I'm also new to Blazor but not c#.
I am building a Blazor server-side application where a user can enter some information and check if it's valid or not based on some data on the server.
So far I have no issues with calling the function of the class that does the lookup and returns a record to display on the browser.
My problem comes when I want to display that information.
In the c# code, I have a variable called SdItem which contains the record that comes back from the query.
To display the data on the razor page I use the following lines.
#if (SdItem != null)
{
<div>
Code: #SdItem.Code<br />
Desc.: #SdItem.Desc<br />
</div>
}
When SdItem gets the data it obviously does not display the information until I call StateHasChanged();
This of course throws an exception so I had to change it to await InvokeAsync(StateHasChanged);
Although after this change the information shows on the screen and all seems to be fine, I came across a new issue which I could not find a solution or an explanation anywhere on the internet.
During debugging, MS Edge automatically starts and displays the website.
To test this strange issue I also start Firefox to point to the same local address.
Then I use my smartphone as well and that is where I start the query.
When I get the results back, not only do they show up on the phone but on all active browsers that are currently displaying the site.
Why does this happen and how can I stop it.
At the moment I managed to stop this from happening with an ugly code
try { StateHasChanged(); } catch { }
This suppresses the exception and the result is only being displayed on the browser that does the request. This is ugly and I don't like to use it.
Any help would be appreciated.
Just as information, in case this could be the reason. The queried data is in a List in a class which is added as a scoped service. But T is a private variable in the code on the razor file.
"When SdItem gets the data it obviously does not display the information until I call StateHasChanged" Why is this obvious? I would expect Blazor to update the display whenever displayed data is changed. You should very rarely need to call StateHasChanged. This makes me wonder what else is going on.
First thought that springs to mind is that SdItem should be a property...
public Whatever SdItem { get; set; }
...and not a private field...
private Whatever SdItem;
I'm not sure if needs to be public, but when using properties, Blazor (almost) always updates the display. When using private fields, if often doesn't.
"This of course throws an exception" Again, I don't see why this is so obvious that you say "of course." It all depends on where you are calling StateHasChanged. Yes, if you're inside an async block then you'll need to call InvokeAsync, but if you arent, then you shouldn't need to do that.
More code would be useful, as its hard to know exactly what you're doing from the small snippet you provided, but try using a property (if you aren't already), and see if that avoids the need to call StateHasChanged.
If not, please update your question with more information.
Essentially, after testing a few level prototypes, I've decided to stick with my current game idea so I started creating a GameManager to control the flow of levels, etc. I don't have any additional libraries or asset packages being used outside of the default, but for some reason the buildIndex of all of my scenes is -1, which I learned according to the API, means that they're supposed to be loaded through an AssetBundle. Now I can't load anything with SceneManager and I'm not sure how to move forward. I did temporarily have the 2d-extras-master folder in the project as I assumed I'd be using it, but removed it after realizing I wouldn't need it. Does anyone know how to reset the buildIndices of my scenes to the values in the Build Settings? Any/All help is greatly appreciated!
Edit: I should also mention, that the latest Scene I added (when I still had the 2d-extras-manager) still retained a normal buildIndex of 0
Edit #2: So I've found that I can access the buildIndices of the other scenes amongst themselves. It's only when I try to access the buildIndices from my MainMenu Scene that things don't work
Edit #3: I've found a fix, but it doesn't necessarily answer the question. I found that I can force the LoadScene function to work if I know what the buildIndex is, but if I search for it via a scene name, it would return -1.
ex.
// where 1 is the buildIndex of Scene "Main" in BuildSettings
// works
SceneManager.LoadScene(1);
// doesn't work
int index = SceneManager.GetSceneByName("Main").buildIndex; //returns -1
SceneManager.LoadScene(index);
// also doesn't work (Where current scene is buildIndex 0)
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
SceneManager.GetSceneByBuildIndex or SceneManager.GetSceneByName and functions alike work only on loaded scenes. If scene isn't loaded it will return -1. Reason is, you can load scenes additively, so it's possible to have even 5 loaded scenes.
It's true that the api is lacking in many ways.
In your case you are trying to use it right after SceneManager.LoadScene(1);, int index = SceneManager.GetSceneByName("Main").buildIndex; returns -1 most likely because scene will be loaded on the next frame "officially".
You could try to wait 1 frame in coroutine and then do that. But usually you will have scene index or scene name to load/save it and not care about logic after scene has been loaded. You can create a manager which will store all of the loaded scenes where you could look up their build indices if you need them to decide what scene to load next.
Alternatively you can use Addressables package which handles a lot, it's hard to get into but scene loading works way better there in my opinion.
In the build menu, accessed by clicking in File on Unity Editor you can organize your scenes and add them to the flow like in this image
I'm not sure of it, but I'm supose when you didn't assigned a Scene to the flow, it get sceneIndex = -1. So load a scene, go to BuildSettings, add it to the build flow, do the same to all of them. I think this way you can solve it.
You can use this method to get buildIndex.
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneUtility.GetBuildIndexByScenePath.html
And after checking the validity of the buildIndex, if the buildIndexis not equal to -1, then the scene exists in the build settings.
public static bool SceneExists(string scenePath)
{
return SceneUtility.GetBuildIndexByScenePath(scenePath) != -1;
}
I am experiencing a problem with loading of my work order page.
When I load my page I am just passing the id of the work order WO.aspx?inspectionid=12345
Now on computer 1 I am loading
WO.aspx?inspectionid=1
Now on computer 2 I am loading
WO.aspx?inspectionid=2
To reproduce my issue I click the respective inspection on each separate computer at the exact same time (well as close as I can to a manual simultaneous click)
Now when I debug my LoadWorkOrder function in my code, it calls a stored procedure and populates a Dataset. Now before the first call completes and loads up the rest of the page, I see that my second call is already hitting my LoadWorkOrder function, thus causing one of the pages to error out.
So my question is, is there a way to properly handle multiple calls on the same function. Is this a threading related issue? I am not quite sure even what to google to help solve my issue.
private void LoadWorkOrder()
{
//Bizlogic.cInspectionsBizLogic.GetInspection(dstInspection, mintInspectionID);
dstInspection = new cInspectionsDST();
Bizlogic.cInspectionsBizLogic.GetInspection(ref objDataAdapterForUpdate, dstInspection, mintInspectionID);
if (dstInspection != null && dstInspection.Tables[0].Rows.Count > 0)
{
Bizlogic.cSchedulerDST dstItem = new cSchedulerDST();
dstItem = Bizlogic.cSchedulerBizLogic.GetScheduleItemForInspectionID(mintInspectionID);
LoadInspectionAddressHeader();
I don't see anything special here, its just a simple loading of a dataset. The error message I do seem to be getting "There is no row at position 0". Within my cInspectionsDST.Designer.cs file. These DataSets are created within Visual Studio I've inherited so changing those is unfortunately not an option.
dstInspection was a static variable once I removed that and reworked the code I no longer had this issue
We need a screenshot of our app for a unit test. CaptureScreen() and CopyFromScreen() somehow ignore the app and return pictures of an empty desktop. So we wrote this to fake a PrtScn keystroke:
public static Bitmap GetAltScreenshot()
{
Clipboard.Clear();
SendKeys.SendWait("{PRTSC}");
while (!Clipboard.ContainsImage())
{
Thread.Sleep(500);
}
return new Bitmap(Clipboard.GetImage());
}
Alt isn't part of the keystroke, so this should return a bitmap of the entire screen. Yet somehow this snippet returns just the focused window. Which is fine, that solves our problem - but we don't understand how.
Why does this return a shot of just the focused window, instead of the entire monitor?
There is in fact a "reason", turn to the MSDN Library article that documents the key abbreviations you can use. Note the entry for PRINT SCREEN:
{PRTSC} (reserved for future use)
The is a somewhat clumsy way of saying "We know it doesn't work, maybe will fix that some day". That day hasn't yet arrived. So you are probably testing the failure mode of this key and actually like the way it works. This is of course not healthy, they may actually fix the problem some day and break your program.
Do note the Note about the <appSettings> entry that you can add to your .config file, further down that same MSDN page. I suspect, but do not know for a fact, that the SendInput method is more reliable.
I started using FMOD library, because I need to play sounds without gaps in C# application (both one sound in a loop and many sounds in a sequence). Can anyone show me the correct way to do it? I tried make something based on examples, but it's not working as I would like it to work.
Firstly, when I try to set if the sound is looped, while it's playing,
if (value)
sound1.setMode(FMOD.MODE.LOOP_NORMAL);
else
sound1.setMode(FMOD.MODE.LOOP_OFF);
nothing is going on. It only works fine, when I set th mode, before I start playback.
The second issue is: how can I be notified that the sound has reached the end? I tried to do it this way:
channel.setCallback(eofCallback);
where eofCallback is a reference to SoundEndCallback
private FMOD.RESULT SoundEndCallback(IntPtr channelraw, FMOD.CHANNEL_CALLBACKTYPE type, IntPtr commanddata1, IntPtr commanddata2)
{
FMOD.RESULT result;
if (type == FMOD.CHANNEL_CALLBACKTYPE.END)
{
//logic here
}
return FMOD.RESULT.OK;
}
But this callback is reached only when I manually invoke stop() on channel, not when the track ends.
Or eventually do you know any other library that would give me easily what I need? I chose FMOD, because it's quite popular, but I don't like its oldschool C++-like way of coding (no events, no exceptions, etc.).
And I have teh answer for my second question: to get notified you have to firstly set callback as mentioned before, and after that you've got to use System.update() method (it must be called periodically in a loop). This is a kind of polling,
To set the loop mode of a sound at runtime use Channel::setMode, Sound::setMode is like setting the defaults for any channels played from that sound (it won't affect currently playing sounds).
As for Channel::setCallback, make sure you are calling System::update regularly to have the callbacks fire for events like the sound playing to the end.