I have just started using Unity3D and my school project consists of using iBeacons and detecting them with my mobile device. I'm doing a 2D project and in my scene, I have an empty game object that contains code handling the detection of the iBeacon:
public class iBeaconReceiverExample : MonoBehaviour
{
private Vector2 scrolldistance;
private List<Beacon> mybeacons = new List<Beacon>();
private bool scanning = true;
private bool guion = false;
public GameObject Nipper;
// Use this for initialization
void Start()
{
iBeaconReceiver.BeaconRangeChangedEvent += OnBeaconRangeChanged;
iBeaconReceiver.BluetoothStateChangedEvent += OnBluetoothStateChanged;
iBeaconReceiver.CheckBluetoothLEStatus();
Debug.Log("Listening for beacons");
}
void OnDestroy()
{
iBeaconReceiver.BeaconRangeChangedEvent -= OnBeaconRangeChanged;
iBeaconReceiver.BluetoothStateChangedEvent -= OnBluetoothStateChanged;
}
// Update is called once per frame
void Update()
{
foreach (Beacon b in mybeacons)
{
if (0.00 < b.accuracy && b.accuracy < 2.00)
{
CreateNipper();
}
}
}
public void CreateNipper()
{
GameObject nipper = Instantiate(Nipper, new Vector3(1, 1, -7), Quaternion.identity) as GameObject;
nipper.transform.SetParent(transform);
}
private void OnBluetoothStateChanged(BluetoothLowEnergyState newstate)
{
switch (newstate)
{
case BluetoothLowEnergyState.POWERED_ON:
iBeaconReceiver.Init();
Debug.Log("It is on, go searching");
break;
case BluetoothLowEnergyState.POWERED_OFF:
//iBeaconReceiver.EnableBluetooth();
Debug.Log("It is off, switch it on");
break;
case BluetoothLowEnergyState.UNAUTHORIZED:
Debug.Log("User doesn't want this app to use Bluetooth, too bad");
break;
case BluetoothLowEnergyState.UNSUPPORTED:
Debug.Log("This device doesn't support Bluetooth Low Energy, we should inform the user");
break;
case BluetoothLowEnergyState.UNKNOWN:
case BluetoothLowEnergyState.RESETTING:
default:
Debug.Log("Nothing to do at the moment");
break;
}
}
private void OnBeaconRangeChanged(List<Beacon> beacons)
{
//
foreach (Beacon b in beacons)
{
if (mybeacons.Contains(b))
{
mybeacons[mybeacons.IndexOf(b)] = b;
}
else
{
// this beacon was not in the list before
// this would be the place where the BeaconArrivedEvent would have been spawned in the the earlier versions
mybeacons.Add(b);
}
}
foreach (Beacon b in mybeacons)
{
if (b.lastSeen.AddSeconds(10) < DateTime.Now)
{
// we delete the beacon if it was last seen more than 10 seconds ago
// this would be the place where the BeaconOutOfRangeEvent would have been spawned in the earlier versions
mybeacons.Remove(b);
}
}
}
The "Init()" method starts the iBeacon plugin and starts searching for an iBeacon around my mobile device. My only concern here is that I have two scenes and once I go to another scene (a random scene) and go back to the original scene (the one containing the iBeaconReceiverExample script), my application crashes "Unfortunately, (Game Name) has stopped."
I have used adb Logcat to track the log of my device but it hasn't helped me at all. I have tried making two whole new scenes (thinking that maybe my scene was going crazy) but nothing worked. When I don't attach this script to my game object, my application doesn't crash so clearly the problem has to be somewhere here.
Have someone played with iBeacons on Unity and encountered this problem? What is the solution to this problem?
Thank you in advance! :)
Related
I am trying to convert my PC game code in unity to android and I am stuck on the controls change. Please help!
This is the code:
Getting the state of rocket.
enum State { Dying, Alive, Transcending }
State state = State.Alive;
// Update is called once per frame
void Update()
{
if (state == State.Alive)
{
RespondToThrustInput();
RespondToRotateInput();
}
}
When the rocket collides with anything it checks whether it's friendly or not before changing its state from alive to dead.
private void OnCollisionEnter(Collision collision)
{
if (state != State.Alive) { return; }
switch (collision.gameObject.tag)
{
case "Friendly":
break;
case "Finish":
state = State.Transcending;
audioSource.Stop();
audioSource.PlayOneShot(finishgame);
finishgameParticles.Play();
Invoke("LoadNextScene", levelloaddelay);
break;
default:
state = State.Dying;
audioSource.Stop();
audioSource.PlayOneShot(death);
deathParticles.Play();
Invoke("LoadFirstScene", levelloaddelay);
break;
}
}
private void LoadFirstScene()
{
SceneManager.LoadScene(9);
}
Loading next scene using build index.
private void LoadNextScene()
{
if (nextscenetoload > 7)
{
nextscenetoload = 0;
}
SceneManager.LoadScene(nextscenetoload);
}
Space for ignition or force and audio sources for playing sound effects.
private void RespondToThrustInput()
{
if (Input.GetKey(KeyCode.Space))
{
ApplyThrust();
}
else
{
audioSource.Stop();
mainengineParticles.Stop();
}
}
Apply thrust is the method I wrote with the logic of the rocket thrust.
private void ApplyThrust()
{
rigidbody.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
if (!audioSource.isPlaying)
audioSource.PlayOneShot(mainengine);
mainengineParticles.Play();
}
Rotation of the rocket or Left and right. Here I am trying to rotate the rocket using the A and D keys
void RespondToRotateInput()
{
float rotationThisFrame = rcsThrust * Time.deltaTime;
if (Input.GetKey(KeyCode.A))
{
rigidbody.freezeRotation = true;
transform.Rotate(Vector3.forward * rotationThisFrame);
rigidbody.freezeRotation = false;
}
else if (Input.GetKey(KeyCode.D))
{
rigidbody.freezeRotation = true;
transform.Rotate(-Vector3.forward * rotationThisFrame);
rigidbody.freezeRotation = false;
}
}
For PC games there is a keyboard to use to control, but for the android there are touches, you have to verify if there is a touch on the screen, like this:
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
//do something
}
also you need more work to determine where the touch is located and do you customizations... or in case you're not interested about this input handling, you can use some assets from Unity Assets Store to cover this part for you.
check this link for more information about touch control in Unity documentation:
https://docs.unity3d.com/ScriptReference/Input.GetTouch.html
I am working on a multlayer third person game and I am using motion controller for animations and photon for network manager.I ahve a problem: when I connect and join the room the other players don't move on others player screen. They move only on their devices. Here is what I deactivated:
using UnityEngine;
using com.ootii.Input;
using com.ootii.Actors;
using com.ootii.Actors.AnimationControllers;
public class netView : Photon.MonoBehaviour {
public Camera cam;
public UnityInputSource uis;
public GameObject canvas;
public ActorController ac;
public MotionController mc;
// Use this for initialization
void Start () {
if (photonView.isMine) {
cam.enabled = true;
uis._IsEnabled = true;
canvas.active = true;
ac.enabled = true;
mc.enabled = true;
} else {
cam.enabled = false;
uis._IsEnabled = false;
canvas.active = false;
ac.enabled = false;
mc.enabled = false;
}
}
}
Here is a video: https://youtu.be/mOaAejsVX04 . In it i am playing in editor and on my phone. In my device I move around and the editor player does not move. Also in editor, the player from the device just stays there, doesn't move while on phone is moveing around.
For input I am using CrossPlatformManager class. How can I repair it?
In your case I think the problem is that you don't synchronize the transform to begin with. You need either a PhotonTransformView Component attached to your network object, with a photonView observing that PhotonTransformView, or inside your network behaviour manually writing and reading to that network object stream.
I strongly encourage you do go through the basic tutorial which will show you all the above technique step by step:
https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/pun-basics-tutorial/player-networking#trans_sync
https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/pun-basics-tutorial/player-networking#beams
it doesn't matter the input technique you use, what matters is the synchronization of the transform.
I am using Vuforia 6.2 AR SDK for in Unity. But while I test the application in Android phone the camera seems like blurry. I searched in Vuforia's developer website and found some camera focus mode but I can't implement because that guideline was for older Vuforia SDK, I can't find the script they mentioned in their website. Here is their code sample but it's not working. I created different script and run this line on Start() function, but still not working.
CameraDevice.Instance.SetFocusMode(
CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
try this
void Start ()
{
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPaused);
}
private void OnVuforiaStarted()
{
CameraDevice.Instance.SetFocusMode(
CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
private void OnPaused(bool paused)
{
if (!paused) // resumed
{
// Set again autofocus mode when app is resumed
CameraDevice.Instance.SetFocusMode(
CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
}
This code is the right code.
bool cameramode = false;
public void OnCameraChangeMode()
{
Vuforia.CameraDevice.CameraDirection currentDir = Vuforia.CameraDevice.Instance.GetCameraDirection();
if (!cameramode) {
RestartCamera(Vuforia.CameraDevice.CameraDirection.CAMERA_FRONT);
camBtnTxt.text = "Back Camera";
} else {
RestartCamera(Vuforia.CameraDevice.CameraDirection.CAMERA_BACK);
camBtnTxt.text = "Front Camera";
}
}
private void RestartCamera(Vuforia.CameraDevice.CameraDirection newDir)
{
Vuforia.CameraDevice.Instance.Stop();
Vuforia.CameraDevice.Instance.Deinit();
Vuforia.CameraDevice.Instance.Init(newDir);
Vuforia.CameraDevice.Instance.Start();
}
I want to re-present the data transfer arrows for Wi-Fi (as seen in the Quick Settings panel) in my app. I have been looking at the source code for Quick Settings and have been roadblocked by a couple of non-public APIs (AsyncChannel & WiFiManager.getWifiServiceMessenger) - does anyone know if there is any conceivable way around this?
For example, NetworkController...
// wifi
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Handler handler = new WifiHandler();
mWifiChannel = new AsyncChannel(); //Private
Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); // Private
if (wifiMessenger != null) {
mWifiChannel.connect(mContext, handler, wifiMessenger);
}
...is handled in...
// ===== Wifi ===================================================================
class WifiHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case WifiManager.DATA_ACTIVITY_NOTIFICATION:
if (msg.arg1 != mWifiActivity) {
mWifiActivity = msg.arg1;
refreshViews();
}
break;
...
}
}
}
...where mWifiConnectivity is communicated to the Quick Setting panel.
I am thinking this is not possible, but thanks for your consideration and confirmation of this hunch :-\
check out this other question here in SO, looks like he's done the monitoring part.
As in the title I've been able to connect to Google Game Services, exchange data between two devices and everything is running fine, except one thing: disconnection callbacks.
I tried to intercept both onPeersDisconnected and onP2PDisconnected without any success. The onP2PDisconnected method is being called in the device that get disconnected from Internet but not into device that is still online (so there is no way to tell the player that the other one got disconnected).
After the match is started it seems that the second device is never notified of the accidental disconnection. If the user close the game properly the onPeersLeft method is being called thought.
Is a ping between the two devices really necessary to overcome this "bug"? Am I doing something wrong?
Here is the code I use:
void startQuickGame() {
// quick-start a game with 1 randomly selected opponent
final int MIN_OPPONENTS = 1, MAX_OPPONENTS = 1;
Bundle autoMatchCriteria = RoomConfig.createAutoMatchCriteria(MIN_OPPONENTS,
MAX_OPPONENTS, 0);
RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this);
rtmConfigBuilder.setMessageReceivedListener(this);
rtmConfigBuilder.setRoomStatusUpdateListener(this);
rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
mListener.switchToScreen(R.id.screen_wait);
keepScreenOn();
resetGameVars();
getGamesClient().createRoom(rtmConfigBuilder.build());
}
And here the simple listeners:
#Override
public void onPeersDisconnected(Room room, List<String> peers) {
Log.d(TAG, "onPeersDisconnected");
updateRoom(room);
}
void updateRoom(Room room) {
Log.d(TAG, "UpdateRoom: "+room.getParticipants().size());
mParticipants = room.getParticipants();
}
#Override
public void onP2PDisconnected(String participantId) {
Log.d(TAG, "onP2PDisconnected");
}
public int getPartecipantsInRooom(){
if(mRoom != null)
return mRoom.getParticipants().size();
else
return -123456;
}
Note that calling getPartecipantsInRooom() after one of the two devices disconnects always return 2, and updateRoom never get called.
Just to be sure this might not work for you, for my applications I use this to let me know when another Participant has left the Room, and it is called immediately :
#Override
public void onPeerLeft(Room room, final List<String> participantIds) {
this.mRoomCurrent = room;
this.mRoomId = this.mRoomCurrent.getRoomId();
this.mParticipants = this.mRoomCurrent.getParticipants();
int connected = 0;
for (Participant p : room.getParticipants()) {
if(p.getStatus() == Participant.STATUS_JOINED) {
connected += 1;
}
}
final int fconnected = connected;
for (String s : listIgnoreTheseIDs) {
//checkint to see if we care anymore about this ID.. if out of game already.. nope
if(s.equals(participantIds.get(0))){
return;
}
}
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
mGHInterface.onPeerLeft(fconnected, participantIds.size());
}
});
}
No idea why there are two items, but like you, I realized the onPeersDisconnected() isn't that reliable, but onPeerLeft() normally gets back to the other devices in under 1 second.
onPeerDisconnected() handles disconnects. So if somebody is still in the application but the network connection is lost, this is called for him.
onPeerLeft() handles participants who leave a room. This is called when somebody explizit leaves the room in the application or the application is minimized, and the room is left on the androids onStop() or onDestroy() callback.
I'm making two player game. So I use this approach
#Override
public void onPeerLeft(Room room, List<String> peersWhoLeft) {
updateRoom(room);
Toast.makeText(MyLauncherActivity.this, "Other player left the game", Toast.LENGTH_LONG).show();
quitGame();
}