Unity3d HLAPI, Unet, network aware spawining - networking

Hello I am trying to create my first game in unity which I wanna be network aware but I encoured a problem with network prefabs spawning. Here's my code:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Builder : NetworkBehaviour {
public GameObject preview;
public Transform currentPreview;
bool isPreviewing = false;
GameObject buildingPreview;
private NetworkIdentity networkId;
// Use this for initialization
void Start ()
{
networkId = GetComponent<NetworkIdentity>();
}
// Update is called once per frame
void ViewPreview()
{
buildingPreview = Instantiate(preview, transform.position, transform.rotation) as GameObject;
currentPreview = buildingPreview.transform;
isPreviewing = true;
}
void Update ()
{
CmdBuild();
}
void CmdBuild()
{
if (networkId.isLocalPlayer)
{
}
else
{ return; }
if (Input.GetKeyDown(KeyCode.E))
{
if (!isPreviewing)
ViewPreview();
else
{
Destroy(buildingPreview);
isPreviewing = false;
}
}
if (isPreviewing)
{
Preview();
}
}
[Command]
void CmdSpawnBuilding()
{
GameObject buildingPlaced = Instantiate(preview, currentPreview.position, currentPreview.rotation) as GameObject;
NetworkServer.Spawn(buildingPlaced);
}
void Preview()
{
currentPreview.position = transform.position + transform.forward * 3f;
currentPreview.rotation = transform.rotation;
if (Input.GetButtonDown("Fire1"))
{
CmdSpawnBuilding();
isPreviewing = false;
}
}
}
Compiler says there's no problem but in unity I've got such error: "UNetWeaver error: Script Builder uses [Command] CmdSpawnBuilding but is not a NetworkBehaviour. UnityEngine.Debug:LogError(Object)" My code runs perfetly good without "[Command]" line despites it's not network aware. Also, I know it's a bit messed up but I was trying to figure it out what's wrong and so yeah, messed code a bit.

Your class needs to inherit from NetworkBehaviour, like this:
public class Builder : NetworkBehaviour

Related

Net Framework Xunit With Moq Unit Testing Keep Calling The Original Function

I have a problem with mocking cause it keep calling the original function. This is my demo code
First file is interface that contains the function that I want to mock.
public interface IDemoReplace
{
int FunctionToBeReplaced();
}
Second file is a class that actually has the implementation for the function
public class DemoReplace : IDemoReplace
{
public int FunctionToBeReplaced()
{
//this function contains sql query in my real project
return 1;
}
}
Third file is a class that I want to test
public class ClassToBeTested
{
public int TestThisFunction()
{
IDemoReplace replace = new DemoReplace();
var temp = replace.FunctionToBeReplaced();
return temp;
}
}
Last file is the test class
public class TestClass
{
[Fact]
public void TryTest()
{
using (var mock = AutoMock.GetLoose()) {
//Arrange
mock.Mock<IDemoReplace>()
.Setup(x => x.FunctionToBeReplaced())
.Returns(returnTwo());
var classToBeTested = mock.Create<ClassToBeTested>();
var expected = 2;
//Act
var actual = classToBeTested.TestThisFunction();
//Assert
Assert.Equal(expected, actual);
}
}
public int returnTwo() {
return 2;
}
}
This test will be failed with expected is 2 and actual is 1. When I tried to debug it doesn't call returnTwo but call the original function instead.
I am new to unit testing so what did I miss? Please be considered that the code above is only a demo of what is happened in my actual project. FunctionToBeReplaced is actually a function that execute and return record from database so I want to mock that function.
Thanks :)
This is a design issue. The subject under test is tight coupled to implementation concerns that make it difficult to isolation the subject so that it can be unit tested.
It (subject) is manually creating its dependency
IDemoReplace replace = new DemoReplace();
Ideally you want to explicitly inject dependencies. Those dependencies should also be abstractions and not concretions.
public class ClassToBeTested {
private readonly IDemoReplace dependency;
public ClassToBeTested(IDemoReplace dependency) {
this.dependency = dependency;
}
public int TestThisFunction() { ;
var temp = dependency.FunctionToBeReplaced();
return temp;
}
}
At run time, the implementation (or mock) can be injected, either purely, or via a container.
The test in the original example shown should now behave as expected.
public class TestClass {
[Fact]
public void TryTest() {
using (var mock = AutoMock.GetLoose()) {
//Arrange
var expected = returnTwo();
mock.Mock<IDemoReplace>()
.Setup(x => x.FunctionToBeReplaced())
.Returns(expected);
var classToBeTested = mock.Create<ClassToBeTested>();
//Act
var actual = classToBeTested.TestThisFunction();
//Assert
Assert.Equal(expected, actual);
}
}
public int returnTwo() {
return 2;
}
}

Intercept global event Xamarin Forms

In MainActivity.cs I have this method
public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
{
if (keyCode.ToString().Equals("F1"))
{
App.Left = true;
App.Right = false;
}
else if (keyCode.ToString().Equals("F2"))
{
App.Left = false;
App.Right = true;
}
else
{
App.Left = false;
App.Right = false;
}
return base.OnKeyUp(keyCode, e);
}
In my Page class, how can I constantly check whether left or right are true and in case trigger an event?
Create a plugin using Dependency Service and your shared interface should look like this:
public interface IKeyEvent
{
event Action<KeyResult> OnKeyEvent;
}
public enum KeyResult {None, Left, Right};
Implement this for different platforms (Android/iOS/UWP) accordingly and bind it to PCL project. (Check dependency service implementation for help)
Link it to platform-specific KeyUp event.
for android it would be like this:
Droid.KeyEventHandler
[assembly: Dependency(typeof(KeyEventHandler))]
namespace YourNameSpace.Droid
{
public class KeyEventHandler : IKeyEvent
{
public static KeyEventHandler Current;
public KeyEventHandler()
{
Current = this;
}
public event Action<KeyResult> OnKeyResult;
public void RaiseKeyEvent(KeyResult key)
{
OnKeyResult?.Invoke(key);
}
}
}
MainActivity
public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
{
KeyResult keyResult = KeyResult.None; // need to reference YourNameSpace.Shared project to use this enum
if (keyCode == KeyCode.A)
{
keyResult = KeyResult.Left;
}
else if (keyCode == KeyCode.D))
{
keyResult = KeyResult.Right;
}
else
{
keyResult = KeyResult.None;
}
if (KeyEventHandler.Current != null)
{
KeyEventHandler.Current.RaiseKeyEvent(keyResult);
}
return base.OnKeyUp(keyCode, e);
}
NOTE: Left and right keys are mapped to A and D of physical keyboard respectively, for some reason my Macbook's F1/F2 keys were not registering to simulator so I used A/D.
Hope this helps :)

Mobile map package returns null for map

I downloaded Arcgis sample mmpk file and even I made a mmpk myself.
In both files I have 1 map(checked by debug) but when I try load the map (with codes in Esri guide page) it returns null for map.
Good to say that I can show online map in my map view and android studio shows no warning or error.
import static n.k.masoud.sbmap.R.id.mapView;
public class ActivityMain extends AppCompatActivity {
private MapView mMapView;
private ArcGISMap map;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapView = (MapView) findViewById(mapView);
code and file from main site
try {File mmpkFile = new File(Environment.getExternalStorageDirectory(),"devlabs-package.mmpk");
String mmpkPath = mmpkFile.getAbsolutePath();
final MobileMapPackage mobileMapPackage=new MobileMapPackage(mmpkPath);
mobileMapPackage.addDoneLoadingListener(new Runnable() {
#Override
public void run() {
this if gets false
if (mobileMapPackage.getLoadStatus() == LoadStatus.LOADED) {
showMessage(String.format("Number of maps = %d", mobileMapPackage.getMaps().size()));
map = mobileMapPackage.getMaps().get(0);
} else {
dealWithLoadFailure();
}
}
});
mobileMapPackage.loadAsync();
}
catch (Exception err){
Log.e("TAG", "onCreate: "+err);
}
map.addDoneLoadingListener(new Runnable() {
#Override
public void run() {
if (map.getLoadStatus() == LoadStatus.LOADED) {
Log.e("TAG", "run: map loaded ok" );
// Once map is loaded, can check its properties and content
if (map.getBookmarks().size() > 0) {
}
} else {
dealWithLoadFailure();
}
}
});
map.loadAsync();
As I told part below works correctly
// for online maps
// ArcGISMap map = new ArcGISMap(Basemap.Type.TOPOGRAPHIC, 29.453826, 60.852134,12);
mMapView.setMap(map);
mMapView.addLayerViewStateChangedListener(new LayerViewStateChangedListener() {
#Override
public void layerViewStateChanged(LayerViewStateChangedEvent layerViewStateChangedEvent) {
// Each layer may have more than one layer view state.
StringBuilder layerStatuses = new StringBuilder();
for (LayerViewStatus status : layerViewStateChangedEvent.getLayerViewStatus()) {
if (layerStatuses.length() > 0) {
layerStatuses.append(",");
} layerStatuses.append(status.name());
}
showMessage(String.format("Layer '%s' status=%s", layerViewStateChangedEvent.getLayer().getName(), layerStatuses.toString()));
} });
}
#Override
protected void onPause(){
mMapView.pause();
super.onPause();
}
#Override
protected void onResume(){
super.onResume();
mMapView.resume();
}
}
if the line
if (mobileMapPackage.getLoadStatus() == LoadStatus.LOADED)
is returning false, then the mobile map package is not loaded and won't contain any maps.
In your dealWithLoadFailure() function you can retrieve the load error:
mobileMapPackage.getLoadError()
and see what it is. It should tell you what the error causing the load failure is.
One of my friends tried this way but didn't got any result just like me.
So he changed the official guide code to this and got well response.
I think he got code from Internet , so I don't know about it's copyright permission.
private void setupMobileMap() {
if (mMapView != null) {
File mmpkFile = new File(Environment.getExternalStorageDirectory(), "devlabs-package.mmpk");
final MobileMapPackage mapPackage = new MobileMapPackage(mmpkFile.getAbsolutePath());
mapPackage.addDoneLoadingListener(new Runnable() {
#Override
public void run() {
// Verify the file loaded and there is at least one map
if (mapPackage.getLoadStatus() == LoadStatus.LOADED && mapPackage.getMaps().size() > 0) {
mMapView.setMap(mapPackage.getMaps().get(0));
} else {
// Error if the mobile map package fails to load or there are no maps included in the package
//setupMap();
//Log for Error
}
}
});
mapPackage.loadAsync();
}
}

QR detection using ZXing with Vuforia in Unity

We have implemented the QR detection functionality using ZXing.dll in Unity 5.3.4f1 with Vuforia Unity SDK 5.5.9. We have a QR detection script on GameObject which remains active throughout the app and using below mentioned (QRScanner.cs) code ( as mentioned on Unity Zxing QR code scanner integration ).
We are also using Vuforia for image detection (50 image targets) in the same scene where QR detection is expected. The Vuforia plugin is getting enabled / disabled multiple times as per our requirement. Both the image and QR detection is working perfectly for us on Android and iOS devices until the app is in focus. Whenever VuforiaBehaviour gets disabled and enabled, QR detection stops working after that. QRScanner script always receives null data after the app is resumed or AR camera is reloaded. We have tried keeping our QR detection script on AR camera prefab and also tried
qcarBehaviour.RegisterTrackablesUpdatedCallback(OnTrackablesUpdated);
qcarBehaviour.RegisterQCARStartedCallback(OnTrackablesUpdated);
callbacks every time AR camera starts but with no success. The QR detection stops working completely after pausing Vuforia plugin for any reason.
Does anybody have any idea how to fix this issue?
QRScanner.cs
using UnityEngine;
using System;
using System.Collections;
using Vuforia;
using System.Threading;
using ZXing;
using ZXing.QrCode;
using ZXing.Common;
/* ///////////////// QR detection does not work in editor //////////////// */
[AddComponentMenu("System/QRScanner")]
public class QRScanner : MonoBehaviour
{
private bool cameraInitialized;
private BarcodeReader barCodeReader;
public AppManager camScript;
void Start()
{
barCodeReader = new BarcodeReader();
StartCoroutine(InitializeCamera());
}
private IEnumerator InitializeCamera()
{
// Waiting a little seem to avoid the Vuforia's crashes.
yield return new WaitForSeconds(3f);
var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
// Force autofocus.
// var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
// if (!isAutoFocus)
// {
// CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
// }
// Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
cameraInitialized = true;
}
private void Update()
{
if (cameraInitialized)
{
try
{
var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
if (cameraFeed == null)
{
return;
}
var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
// QRCode detected.
Debug.Log(data.Text);
Application.OpenURL (data.Text); // our function to call and pass url as text
data = null; // clear data
}
else
{
Debug.Log("No QR code detected !");
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
i have this problem to
but i fix that with place code on ARcam
using UnityEngine;
using System.Collections;
using Vuforia;
public class CameraSettings : MonoBehaviour
{
#region PRIVATE_MEMBERS
private bool mVuforiaStarted = false;
private bool mAutofocusEnabled = true;
private bool mFlashTorchEnabled = false;
private CameraDevice.CameraDirection mActiveDirection = CameraDevice.CameraDirection.CAMERA_DEFAULT;
#endregion //PRIVATE_MEMBERS
#region MONOBEHAVIOUR_METHODS
void Start () {
Debug.Log("CameraSettings Start");
VuforiaAbstractBehaviour vuforia = FindObjectOfType<VuforiaAbstractBehaviour>();
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPaused);
VuforiaARController.Instance.RegisterTrackablesUpdatedCallback (OnTrack);
//VuforiaARController.Instance.RegisterVideoBgEventHandler(BgEventHandler);
}
#endregion // MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
public bool IsFlashTorchEnabled()
{
return mFlashTorchEnabled;
}
public void SwitchFlashTorch(bool ON)
{
if (CameraDevice.Instance.SetFlashTorchMode(ON))
{
Debug.Log("Successfully turned flash " + ON);
mFlashTorchEnabled = ON;
}
else
{
Debug.Log("Failed to set the flash torch " + ON);
mFlashTorchEnabled = false;
}
}
public bool IsAutofocusEnabled()
{
return mAutofocusEnabled;
}
public void SwitchAutofocus(bool ON)
{
if (ON)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
Debug.Log("Successfully enabled continuous autofocus.");
mAutofocusEnabled = true;
}
else
{
// Fallback to normal focus mode
Debug.Log("Failed to enable continuous autofocus, switching to normal focus mode");
mAutofocusEnabled = false;
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
}
else
{
Debug.Log("Disabling continuous autofocus (enabling normal focus mode).");
mAutofocusEnabled = false;
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
}
public void TriggerAutofocusEvent()
{
// Trigger an autofocus event
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO);
// Then restore original focus mode
StartCoroutine(RestoreOriginalFocusMode());
}
public void SelectCamera(CameraDevice.CameraDirection camDir)
{
if (RestartCamera (camDir))
{
mActiveDirection = camDir;
// Upon camera restart, flash is turned off
mFlashTorchEnabled = false;
}
}
public bool IsFrontCameraActive()
{
return (mActiveDirection == CameraDevice.CameraDirection.CAMERA_FRONT);
}
#endregion // PUBLIC_METHODS
#region PRIVATE_METHODS
private void OnTrack() {
//Debug.Log("CameraSettings OnTrack");
}
private void BgEventHandler() {
//Debug.Log("CameraSettings BgEventHandler");
}
private void OnVuforiaStarted() {
//Debug.Log("CameraSettings OnVuforiaStarted");
mVuforiaStarted = true;
// Try enabling continuous autofocus
SwitchAutofocus(true);
//RestartCamera (CameraDevice.CameraDirection.CAMERA_DEFAULT);
}
private void OnPaused(bool paused) {
bool appResumed = !paused;
//Debug.Log("CameraSettings OnPaused");
if (appResumed && mVuforiaStarted)
{
// Restore original focus mode when app is resumed
if (mAutofocusEnabled)
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
else
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
// Set the torch flag to false on resume (cause the flash torch is switched off by the OS automatically)
mFlashTorchEnabled = false;
}
}
private IEnumerator RestoreOriginalFocusMode()
{
// Wait 1.5 seconds
yield return new WaitForSeconds(1.5f);
// Restore original focus mode
if (mAutofocusEnabled)
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
else
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
private bool RestartCamera(CameraDevice.CameraDirection direction)
{
ObjectTracker tracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (tracker != null)
tracker.Stop();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Deinit();
if (!CameraDevice.Instance.Init(direction))
{
Debug.Log("Failed to init camera for direction: " + direction.ToString());
return false;
}
if (!CameraDevice.Instance.Start())
{
Debug.Log("Failed to start camera for direction: " + direction.ToString());
return false;
}
if (tracker != null)
{
if (!tracker.Start())
{
Debug.Log("Failed to restart the Tracker.");
return false;
}
}
return true;
}
#endregion // PRIVATE_METHODS
}

How to send a STOMP message with Spring4 when controller is mapped

I have the following code...
#Controller
#RequestMapping("/stomp/**")
public class StompController {
#MessageMapping("/hello")
#SendTo("/topic/greet")
public Greeting greet(HelloMessage message) throws Exception{
System.out.println("Inside the method "+message.getName());
Thread.sleep(3000);
return new Greeting("Hello, "+message.getName()+"!");
}
}
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/stomp/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp/hello").withSockJS();
}
}
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
document.getElementById('response').innerHTML = '';
}
function connect() {
var socket = new SockJS('/stomp/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/stomp/topic/greet', function(greeting){
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function disconnect() {
stompClient.disconnect();
setConnected(false);
console.log("Disconnected");
}
function sendName() {
var name = document.getElementById('name').value;
stompClient.send("/stomp/app/hello", {}, JSON.stringify({ 'name': name }));
}
function showGreeting(message) {
var response = document.getElementById('response');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
response.appendChild(p);
}
</script>
The Client side code seems to connect fine but I don't see the console message meaning to me "/stomp/app/hello" is the wrong path. What should the proper path be?
I also tried /app/stomp/hello no dice...
Update
I can remove the #RequestMapping("/stomp/**") and remove the stomp related stuff and it works fine for my simple test, however, I need it to work for a more complex application that will not allow this.
#RequestMapping and #MessageMapping annotations can be used in similar ways, but are totally different.
#MessageMapping can also be used at the type level (see reference documentation), so you could annotate your controller with #MessageMapping("/stomp/**").
Nothing prevents you from annotating a Controller with both #MessageMapping and #RequestMapping - similar programming model, different purposes.

Resources