Unity - GameObject.Find() works only on server - networking

I am making a simple networking game. The scene has a button named 'ReloadButton' and i am trying to find this button and add a listener to it through my script attached on the player.
private Button reloadBtn;
void Start()
{
GameObject tempGO = GameObject.Find("ReloadButton");
if (tempGO != null)
{
reloadBtn = tempGO.GetComponent<Button>();
reloadBtn.onClick.AddListener(weaponManager.Reload);
}
}
I am doing it this way because direct referencing of 'ReloadButton' to the script through public Buttonvariable is not possible.
The code works fine on the server, the listener is also added correctly. but on the client, the GameObject.Find("ReloadButton") throws a NullReferenceException.
Seems like the client cannot find the Button itself.
I cannot proceed further in my project without solving this problem, I hope some of you can point me towards the problem.

Related

How to turn off Motion Controller line pointer

That's it, I'll step on my pride!
I'm using MRTK v2 and working fine except that at some point I want to turn off the line extending from the Motion Controller to the object and that provides input. After looking around and trying to find it in the MRTK documentation (it's gotta be easy, right?), I'm still banging my head on the wall and it's starting to hurt....
The MRTK documentation explains quite well how to configure it here:
https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/Input/Pointers.md
But I'm looking to do this in script, enabling and disabling it as I need it in my application.
Any clue how to do this?
Many thanks!
Answered my own question. Simple:
PointerUtils.SetMotionControllerRayPointerBehavior(PointerBehavior.AlwaysOff);
See documentation here: https://github.com/microsoft/MixedRealityToolkit-Unity/blob/mrtk_release/Documentation/Input/Pointers.md
Great question! Here's one way to do this that has worked for me. You can see my solution at this repository: https://github.com/julenka/MixedRealityToolkit-Unity/tree/so/linepointer_off. Open the scene Assets/TurnOffLinePointerTest.unity and then use hand simulation to press the buttons. The code to turn the pointers on/off is in Assets/PointerConfigurationExample.cs.
Note: the reason you need to use this approach of modifying the mediator instead of directly setting myPointer.IsActive = false is because the default mediator overwrites these values every frame. Luckily, you can customize this behavior.
Step 1: Update MRTK a bit so that PointerMediator can be accessed
Apply the changes from this commit to your MRTK clone. This change updates the FocusProvider in MRTK to make the PointerMediator publicly accessible, and makes the DefaultPointerMediator extensible by updating fields to be protected instead of private, and making methods virtual. See this pull request that implements this change directly into MRTK.
Step 2: Create a custom PointerMediator that will turn off far pointers
Create a custom Pointer Mediator like the one from this commit.
using System.Collections.Generic;
using Microsoft.MixedReality.Toolkit.Input;
public class CustomPointerMediator : DefaultPointerMediator
{
public bool FarPointersDisabled {get; set;}
public override void UpdatePointers()
{
base.UpdatePointers();
if (FarPointersDisabled)
{
foreach(var pointer in farInteractPointers)
{
pointer.IsActive = false;
}
}
}
}
Note that this mediator extends DefaultPointerMediator so it adapts almost all the default mediator logic. Make sure you have fully applied the changes from the first commit otherwise you will not be able to extend DefaultPointerMediator.
Step 3: Tell MRTK to use your custom pointer mediator
In your pointer profile, configure MRTK to use the custom pointer mediator instead of the default pointer mediator. Notice in the picture that I've created a custom pointer profile as part of a custom input system (don't modify the default profile otherwise your changes might get overwritten when you update MRTK).
Step 4: Component that uses custom mediator to turn line pointers on / off
You can now write your component which will use your custom mediator to turn the line pointers on and off.
public class PointerConfigurationExample : MonoBehaviour
{
/* Turns off all far interaction pointers */
public void TurnOffFarPointers()
{
Debug.Log("Line pointers off");
SetFarPointersDisabled(true);
}
public void TurnOnFarPointers()
{
Debug.Log("Line pointers on");
SetFarPointersDisabled(false);
}
private void SetFarPointersDisabled(bool isDisabled)
{
FocusProvider focusProvider = (FocusProvider) MixedRealityToolkit.InputSystem.FocusProvider;
if (focusProvider != null)
{
foreach(var mediator in focusProvider.PointerMediators)
{
// Note: you could check here to make sure you only disable pointers for hands
CustomPointerMediator myMediator = (CustomPointerMediator) (mediator.Value);
if (myMediator != null)
{
myMediator.FarPointersDisabled = isDisabled;
}
}
}
}
}

DayDream, detect pointer without using Event System

Google's new DayDream samples are using the Event System to detect if the pointer is on an object.
Previously it wasn't working like that at all, it was a reticle, and you would then create a Raycast between the Camera and the reticle, such as:
Vector3 rayDirection = GvrController.Orientation * Vector3.forward;
if (Physics.Raycast(origin, rayDirection, out hitInfo, Mathf.Infinity)) {
And then you detect if a specific Object is between the reticle and the Camera.
This way doesn't exactly work anymore. Google is now using the event system, and then checking if the reticle is positioned on an object.
Is there a way for me to check that for any object without using the Event System.
The Event System is a good method, it's just I have about 40 different objects that all work the same way, and implementing an event point/click for these 40 different objects seems like an overkill when previously I could just check an object by tag.
Anyone was able by any chance to be able to detect if the pointer is positioned on an object without using the Event system?
Raycasts don't seem to properly work anymore as the pointer seems to be more of a 2D object, just like a Mouse.
This works approximately, but not very well:
Vector3 origin = Head.transform.position + GvrController.ArmModel.wristPosition;
Vector3 rayDirection = GvrController.ArmModel.pointerRotation * Vector3.forward;
Any help would be appreciated :)
If you don't want to use EventTrigger component, you can simply use your same old script and implement IPointerEnterHandler, IPointerExitHandler, OnPointerClickHandler etc and use same compare tag method for every object.
I think its much more easy to use than custom raycast. As there is always a Graphics Raycaster (or Physics Raycaster for 3D Objects) at work so why not use what it has to offer.
public class MyOldScriptWhichUsedRaycasting: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public void OnPointerEnter (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerExit (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerClick (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
}
Hope this helps

Async Page Asp.net webforms threads

I would like to solve a specific question I got, so this question is more likelly a discussion.
Basiclly, there is an asp.net project with a WebForm1.aspx, with a button on it. As soon as the clien press the button a thread is launch, and inmediatlly then, there is a Response.Redirect like this:
protected void Button1_Click(object sender, EventArgs e)
{
BL.Class1 cd = new BL.Class1();
cd.Run(); // or cd.AsyncRun();
Response.Redirect("~/WebForm2.aspx",true);
}
Of course evrything should be nonstatic. Bussiness Logic class looks somthing like this:
public class Class1
{
public int Signal = 0;
// non blocking Run... the webserver continues with this process running backwards
public void RunAsync()
{
Signal = 0;
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100000); // simulate heavy task!
}
).Start();
Signal = 1;
}
// blocking Run...
public void Run()
{
Signal = 0;
System.Threading.Thread.Sleep(100000); // simulate heavy task!
Signal = 1;
}
}
With this in mind, here is the discussion:
- In WebForm2.aspx I would like to pool either from the client (javascript/ajax/nonstatic webservice) or the server to the client (registerscript with scriptmanager), in order to have the "Signal" variable set to "True" after the heavy process.. and tell the user (via a div with red background to green color) or something else.
- If so, how would be the best method if I do not want to use SignalR or Node.js or WebApi or WebSockets jet?
- Do you have any document, book where to explain such situation in an MVC project approach?
All communitty, really thanked on helping within this issue.
br,
Sounds like a simple meta refresh would do the trick, or a JavaScript that reloads the page on a set interval - no need for anything fancy if you don't want to.
Simply render the page (server-side) either with a red or a green div depending on the completion status of the heavy job.

Automatically read a file - easy

This should be a really easy question, but I just cant seem to get it done, I have a section of code calculating X Y points on a graph, then saving them to file.
If a certain condition is met I want to plot the values on a graph, I am using this code to plot the graph- http://www.kodejava.org/examples/805.html
But I don't want it to ask for the user to point to the file location, I just want it to open a file which has a directory hard coded in, and plot it automatically. So basically remove the buttons at the top and carry out the commands of the buttons automatically.
Would be fantastic if somebody could point me in the right direction, I'm a physicist not a coding expert so as much help as possible would be excellent.
Hope I can help one of you in return sometime.
1) Inside public static void main, just above frame.setVisible(true); insert openButton.setVisible(false);
2) Inside class GraphPanel, inside the method public void actionPerformed(ActionEvent e) insert datapanel.actionPerformed(e); as the first line.
3) Inside class DataPanel inside public void actionPerformed comment out from the beginning JFrame fileFrame = new JFrame(); to initialized = readFile(datafile);
4) Just after the comment, insert initialized = readFile(new File("path_to_data_file"));
Now if you open, and press plot, the hard coded file will be read and plot will be drawn.
Heck,, I don't care if this gets downvoted :). I've never touched Java. After reading your problem, specially I'm a physicist not a coding expert first i searched in google how to compile and run a java file. Then started reading the java program. I even made another version which does not need the button press also, Just open and your graph will be drawn. But that's only if needed, then provided. "Welcome to my java attempt" :)
Update:
For doing without pressing plot, in GraphPanel and DataPanel, and rename the actionPerformed methods to something else like GraphPanel::start_working and DataPanel::start_working Now inside GraphPanel::start_working call DataPanel::start_working instead of earlier datapanel.actionPerformed(e); . If compiler cribs, add some empty actionPerformed for compilation. (perhaps we can remove the implements ) Now your flow is ready without any user action. you just need to start it. So you set plotButton.setVisible(false); to hide the plot button and call graphpanel.start_work(); to start the flow in main.
Update:
Inside GraphPanel
public void start_working() {
datapanel.start_working()
if (!datapanel.isInitialized()) {
return;
}
datapanel.refreshData();
panel.setDisplayPlot(true);
panel.update(panel.getGraphics());
frame.setSize(700, 600);
frame.setVisible(true);
frame.pack();
}
And inside DataPanel
public void start_working(ActionEvent e) {
initialized = readFile(new File("PATH_TO_FILE");
panel.update(panel.getGraphics());
frame.pack();
frame.setVisible(true);
}
in main last 5 lines
openButton.setVisible(false);
plotButton.setVisible(false);
graphpanel.start_working();
frame.setVisible(true);
frame.pack();

Flex 4 Desktop App TooltipManager

I have a flex app that used to be an internet based app. In it I have a function that creates tooltip error messages when I tell it to create an error message. I pulled this app out verbatim to a desktop app and restructured things a bit to get it to run, but I did not mess with the core fundamentals of the mxml file that utilizes this aside from changing the root tag from a type of 's:Group' to 's:Window'
Everything runs correctly, but the tooltips are not displaying. I can't seem to figure out why, so I thought I'd run this by you guys. Here's the tooltip code (inline mxml code in the fx:script cdata tag):
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
public var errorTip:ToolTip;
private function createErrorMsg(errorMsg:String, object:Object):void {
if (errorTip){ToolTipManager.destroyToolTip(errorTip);};
errorTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(root).x + object.width,object.getBounds(root).y) as ToolTip;
errorTip.setStyle("styleName", "errorTip");
errorTip.visible = true;
errorTip.enabled = true;
}
Basically, I pass the function a string and an object (text input, checkbox, button, etc...etc...) and it positions it and displays the error message. This fully works in my web version, but not in my desktop version.
Here's the code that instantiates the window:
var window:LoginWindow = new LoginWindow();
Window.systemChrome = NativeWindowSystemChrome.NONE;
Window.transparent = true;
Window.open(true);
Window.maximize()
Any ideas?
On a side note, I check to see if the errorTip exists at the beginning of the function and then destroy it so that the higher scoped variable 'errorTip' always equals the reference to the currently displayed error. This allows me to just destroy that error tip on form validation and then error check again, but it only allows one tooltip to be displayed at a time. Is there a better way to query the tooltip manager for all of it's currently displayed tooltips and destroy them all?
To resolve this you must change the line that calls 'createTooltip' to the following:
errorTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(root).x + object.width,object.getBounds(root).y, null, object as IUIComponent) as ToolTip;
The idea behind this is that you can now just call 'createErrorMsg("myError",myComponent)' and it'll display an error message there, which you can then add another function:
private function clearError():void
{
if(errorTip) errorTip.visible = false;
}
to actually remove the error message. The down side of this is that it only displays one message at a time but I'll tweak it a bit to change that up. So here's my better resolution:
Error messages will (traditionally) only be displayed in a batch set. (Basically you will only have a handful of tooltips displayed at one point in time and they will all be related to the form you are on). This won't always be true, but that's not my concern here. I created a utility class that performs error message handling:
package Utils
{
import mx.controls.ToolTip;
import mx.core.IUIComponent;
import mx.managers.ToolTipManager;
public class ErrorUtils
{
private static var errorCache:Array = new Array();
public function ErrorUtils()
{
}
public static function createErrorMsg(errorMsg:String, object:Object):void {
var errorTip:ToolTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(object.root).x + object.width,object.getBounds(object.root).y, null, object as IUIComponent) as ToolTip
errorTip.setStyle("styleName", "errorTip");
errorTip.visible = true;
errorTip.enabled = true;
var position:int = errorCache.length;
errorCache.push(errorTip);
}
public static function clearAllErrors():void
{
for each(var error:ToolTip in errorCache)
{
ToolTipManager.destroyToolTip(error);
}
}
}
}
To use the class you simply call ErrorUtils.createErrorMsg("my message",invalidComponent), and to clear the errors you simply call ErrorUtils.clearAllErrors()
That way if you have a form and you have a validation function for it, you simply call that function every time it comes back as invalid. The only thing that this is missing is any kind of way to clear a specific error, but to handle that you could place all of the creation calls inside of a master validation function that validates all the fields in your form, then call that each time you gain or loose focus on a field and call 'ErrorUtils.clearAllErrors()' at the beginning of the function.
BTW:
this is the source of the original tutorial I received to do this, I just abstracted it a bit
http://aralbalkan.com/1125
so credits go to the above site for the original code

Resources