I want to use the world map in Unity and have been looking at the API of various map services. I need to show a screenshot (a static map with markers) on the screen, and move to the full map view to navigate it after clicking on it.
MapBox managed to display the map with the selected coordinates and add test markers, but that's all I can do with a query like this: https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/url-https%3A%2F%2Fwww.mapbox.com%2Fimg%2Frocket.png(-76.9,38.9)/-76.9,38.9,15/1000x1000?access_token=pk.eyJ1IjoiZGVuZGVhZCIsImEiOiJja2F1dha4egixnnfhmnvtc2u0y3bua2ntin0.GGOyhgN_fEqtPpPc5n6OLg because this request returns a jpg image.
They also have a plugin for Unity, but it's only used in 3d projects and does not allow me to configure the display in 2d.
In MapBox, the mapping I need is implemented using JavaScript for Web and Java for Android. On Android I can do what I need. I can connect to the API on Android, but will I be able to use it in Unity later?
It's the same with Google maps.
Actually, the question is, did someone work with map services in Unity? And how can this be implemented correctly?
I don't know if this is still relevant, but I used Mapbox in Unity (the Mapbox plugin) to create a AR Soundscape by "registering" GameObjects to coordinates and moving them in real-time when the map is moved.
Your problem sounds an awful lot like the one I solved with that.
Basically you provide the Lat/Lon values for your objects and convert them to Unity world space coordinates using the AbstractMap.GeoToWorldPosition() function.
I used a raycast to actually pull that off in-engine, which is quite convenient.
//Edit:
Unity is quite capable of handling 2D projects. You just have to configure it properly and build your project around it.
The following is the class that I use to handle all positioning-related calculations. Maybe it's of some help to you.
namespace TehMightyPotato.Positioning
{
[Serializable]
public class GeoPosition
{
[Tooltip(
"Update frequency of position polling. Update every n-th frame. 1 is every frame, 60 is every 60th frame.")]
[Range(1, 60)]
public int positionUpdateFrequency = 1;
[Tooltip("Should the object have a specified altitude?")]
public bool useYOffset = false;
[Tooltip("If useMeterConversion is activated the yOffsets unit is meters, otherwise its unity units.")]
public bool useMeterConversion = false;
[Tooltip("The actual y position of the object in m or unity units depending on useMeterConversion.")]
public float yOffset = 0;
[Tooltip("X is LAT, Y is LON")]public Vector2d geoVector;
[HideInInspector] public float worldRelativeScale;
// Apply the result of this function to your gameobjects transform.position on every frame to keep them on this position.
public Vector3 GetUnityWorldSpaceCoordinates(AbstractMap map)
{
UpdateWorldRelativeScale(map);
var worldSpaceCoordinates = map.GeoToWorldPosition(geoVector, false);
if (useYOffset)
{
worldSpaceCoordinates.y = yOffset;
}
return worldSpaceCoordinates;
}
public void UpdateWorldRelativeScale(AbstractMap map)
{
worldRelativeScale = map.WorldRelativeScale;
}
public void SetGeoVectorFromRaycast(Vector3 position, AbstractMap map, LayerMask layerMask)
{
var ray = new Ray(position, Vector3.down);
if (Physics.Raycast(ray, out var hitInfo, Mathf.Infinity, layerMask))
{
geoVector = map.WorldToGeoPosition(hitInfo.point);
}
else
{
throw new NullReferenceException("Raycast did not hit the map. Did you turn on map preview?");
}
}
public void SetYOffsetFromRaycast(AbstractMap map, Vector3 position, LayerMask layerMask)
{
UpdateWorldRelativeScale(map);
// using raycast because of possible y-non-zero maps/ terrain etc.
var ray = new Ray(position, Vector3.down);
if (Physics.Raycast(ray, out var hitInfo, Mathf.Infinity, layerMask))
{
var worldSpaceDistance = Vector3.Distance(position, hitInfo.point);
if (useMeterConversion)
{
yOffset = worldSpaceDistance * worldRelativeScale;
}
else
{
yOffset = worldSpaceDistance;
}
}
else
{
throw new NullReferenceException("Could not find map below. Is map preview turned on?");
}
}
}
}
Related
After struggling a few hours on making my app detect this QRCode:
I realized that the problem was the in the QRCode appearance. After inverting the colors, the detection was working perfectly..
Is there a way to make Vision API detect the first QRCode? I tried to enable all symbologies but it did not work. I guess it is possible because the app QR Code Reader detects it.
I improved googles example app "barcode-reader" to detect both inverted colored barcodes and regular ones.
here is a link to googles example app:
https://github.com/googlesamples/android-vision/tree/master/visionSamples/barcode-reader
I did so by editing "CameraSource" class,
package: "com.google.android.gms.samples.vision.barcodereader.ui.camera".
I added a parameter: private boolean isInverted = false;
and changed function void setNextFrame(byte[] data, Camera camera):
void setNextFrame(byte[] data, Camera camera) {
synchronized (mLock) {
if (mPendingFrameData != null) {
camera.addCallbackBuffer(mPendingFrameData.array());
mPendingFrameData = null;
}
if (!mBytesToByteBuffer.containsKey(data)) {
Log.d(TAG,
"Skipping frame. Could not find ByteBuffer associated with the image " +
"data from the camera.");
return;
}
mPendingTimeMillis = SystemClock.elapsedRealtime() - mStartTimeMillis;
mPendingFrameId++;
if (!isInverted){
for (int y = 0; y < data.length; y++) {
data[y] = (byte) ~data[y];
}
isInverted = true;
} else {
isInverted = false;
}
mPendingFrameData = mBytesToByteBuffer.get(data);
// Notify the processor thread if it is waiting on the next frame (see below).
mLock.notifyAll();
}
}
I think this is still an open issue, please see link for details. One workaround for this as stated by a developer:
Right, the barcode API generally doesn't support color-inverted codes. There's no parameter or option to control this at the moment. Though some APIs support them, I don't believe it's a common feature.
For a workaround, you could preprocess the colors in the bitmap before passing them to the barcode API (perhaps inverting colors on alternate frames).
Hope this helps.
everyone! I have trouble with combination in one scene multi touch and one touch with. So let me describe my problem step by step.
I use cocos2dx( for android ), So I have scene, on this scene I add layer Pan Zoom Layer for scroll and zoom. next, I add new layer(Game Layer) on PanZoomLayer. I need catch click on Game Layer(on this layer located my game things) I try to do so, using pattern observer,I have done PanZoom Layer by "Subject" my Game Layer - "Observer", and in PanZoomLayer Have created enum EVENTS, and struct touchEvent
enum EVENTS{
EVENT_ONCE_CLICK,
EVENT_MOVE,
ANOTHER,
};
struct touchEvent {
EVENTS eventName;
};
and created in class PanZoomLayer field m_events :
std::stack<EVENTS> m_events;
and on onTouchesBegan add such code
if (_touches.size() == 1) {
m_events.push(EVENTS::EVENT_ONCE_CLICK);
}
else {
m_events.push(EVENTS::ANOTHER);
}
in onTouchesMoved add such code in branch if _touches.size() == 1:
Vec2 curTouchPosition = Director::getInstance()->convertToGL(touch->getLocationInView());
Vec2 prevTouchPosition = Director::getInstance()->convertToGL(touch->getPreviousLocationInView());
Vec2 deltaPosition = curTouchPosition - prevTouchPosition;
float pos = curTouchPosition.distance(prevTouchPosition);
if (fabs(pos) < 0.5f) {
m_events.push(EVENTS::EVENT_ONCE_CLICK);
}
else {
m_events.push(EVENTS::ANOTHER);
}
an onTouchesEnded, add such code :
if (m_events.empty())
return;
EVENTS ev = m_events.top();
while (!m_events.empty()) {
m_events.pop();
}
if (ev == EVENTS::EVENT_ONCE_CLICK) {
// MessageBox("once click", "title");
Touch *touch = (Touch *)_touches.at(0);
Vec2 position = touch->getLocation();
notifyClick(position);
}
where notifyClick :
std::shared_ptr<CSceneSession> sessionShared = m_session.lock();
if (sessionShared)
sessionShared->clickOnScene(point);
So I enter in game cycle : game scene -> transition on menu scene -> game scene...... in start it great work, but after some time ( on difference devices - different time) game begin strange behavior : buggy,
Could you help me please? Thanks for any idea and suggestions.
I Solved my problem in the following way: I remove scheduleUpdateForTarget in method onEnter and remove unscheduleAllForTarget in method onExit and remove method update.
Thank you for your attention!
I work on project with yandexmapkit-android. Library link is https://github.com/yandexmobile/yandexmapkit-android
Documentation is very weak and github page is not fresh. Last update is 3 years ago.
I wanna draw route between two point but i can't find any function or method for this or example
Can you help me ?
As I can see, there are two ways to do it.
The first is calling Yandex Navigator as external application: https://github.com/yandexmobile/yandexmapkit-android/wiki/%D0%98%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%9C%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8-%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%9A%D0%B0%D1%80%D1%82%D0%B0%D0%BC%D0%B8
The second is using Yandex JS API with WebView: https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/route-docpage/
see yandex mapkit demo
mtRouter = MapKitFactory.getInstance().createMasstransitRouter();
mtRouter.requestRoutes(ROUTE_START_LOCATION, ROUTE_END_LOCATION,
new MasstransitOptions(new ArrayList<String>(), new ArrayList<String>(),
// Specify departure time or arrival time here
new TimeOptions()),
this);
// add points
List<RequestPoint> requestPoints = new ArrayList<>();
DrivingOptions drivingOptions = new DrivingOptions();
DrivingRouter drivingRouter = MapKitFactory.getInstance().createDrivingRouter();
DrivingSession drivingSession = drivingRouter.requestRoutes(
requestPoints, drivingOptions, new DrivingSession.DrivingRouteListener() {
#Override
public void onDrivingRoutes(List<DrivingRoute> routes) {
if (routes != null
&& !routes.isEmpty()) {
DrivingRoute route = routes.get(0);
BoundingBox box = BoundingBoxHelper.getBounds(route.getGeometry());
CameraPosition boundingBoxPosition = yandexMap.getMap()
.cameraPosition(box);
}
}
#Override
public void onDrivingRoutesError(Error error) {
//showErrorMessage }
});
You can easily use this method and set camera position
Hope it works for you
My enemy script is linked to a prefab and being instantiated by my main script.
It kills enemies in a random order (I am jumping on them and some are not dying, not what I want).
(what I am trying to achieve is an enemy to die when I jump on its head and play a death animation.
So from this enemy script I call the other script jump <-- which is linked to my player script and get the jump Boolean value. Could the processing of jump be to slow? I need help
I tried everything)
it works but only on certain enemies any ideas why? Thanks community.
Can anyone help me find a better method?
Could someone help me maybe find if the Players y => an amount to change jump var on the enemy
Just had a perfect run, whats wrong with this its working then not then it is partly working
If I add audio, it doesn't work.
#pragma strict
var enemy : GameObject;
var speed : float = 1.0;
var enemanim : Animator;
var isdying : boolean = false;
private var other : main;
var playerhit: boolean = false;
function Start () {
other = GameObject.FindWithTag("Player").GetComponent("main");
this.transform.position.x = 8.325;
this.transform.position.y = -1.3;
enemanim = GetComponent(Animator);
enemanim.SetFloat("isdead",0);
}
function OnCollisionEnter2D(coll: Collision2D) {
if(coll.gameObject.CompareTag("distroy")){
Destroy(enemy.gameObject);
}
if(coll.gameObject.CompareTag("Player")){
playerhit=true;
}
}
function Update () {
if(other.jumped === true && playerhit==true){ *****the jumped i need
enemanim.SetFloat("isdead",1);
}
}
function FixedUpdate(){
this.transform.Translate(Vector3(Input.GetAxis("Horizontal") * speed * Time.deltaTime, 0, 0));
this.rigidbody2D.velocity = Vector2(-5,0);
}
if(other.jumped === true && playerhit==true)
Is wrong.
It should be:
if(other.jumped == true && playerhit==true)
All 3 languages used by Unity, C#, UnityScript, and Boo, are compiled into the same IL byte code at the end. However, there are cases where UnityScript has some overhead as Unity does things in the background. One of these is that it does wrapping of access to members of built-in struct-properties like transform.position.
I prefer C#, I think it is better.
I'm trying to write an android application that uses google maps api version 2.
In Debug the application crashes when it executes the instruction:
setContentView(R.layout.activity_poi_map);
This is the error:
the source attachment does not contain the source for the file
Layoutinflater.class
I don't understand the reason. In headers I imported the whole class
android.view.*
Thank you in advance for any answer.
This is the code:
public class PoiMap extends FragmentActivity {
private GoogleMap pMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent callerIntent = getIntent();
final LatLng userCoord = callerIntent.getParcelableExtra("userCoord");
final Poi poi = (Poi) callerIntent.getSerializableExtra("poi");
setContentView(R.layout.activity_poi_map);
setUpMapIfNeeded(userCoord);
// Sets a callback that's invoked when the camera changes.
pMap.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
/* Only use the simpler method newLatLngBounds(boundary, padding) to generate
* a CameraUpdate if it is going to be used to move the camera *after* the map
* has undergone layout. During layout, the API calculates the display boundaries
* of the map which are needed to correctly project the bounding box.
* In comparison, you can use the CameraUpdate returned by the more complex method
* newLatLngBounds(boundary, width, height, padding) at any time, even before the
* map has undergone layout, because the API calculates the display boundaries
* from the arguments that you pass.
* #see com.google.android.gms.maps.GoogleMap.OnCameraChangeListener#onCameraChange(com.google.android.gms.maps.model.CameraPosition)
*/
public void onCameraChange(CameraPosition arg0) {
// Move camera.
if (poi != null){
LatLng poiCoord = poi.getLatLng();
pMap.addMarker(new MarkerOptions()
.position(poiCoord)
.title(poi.getName())
.snippet(poi.getCategory())
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_star)));
Log.d("userCoord", userCoord.toString());
Log.d("poiCoord", poiCoord.toString());
double minY = Math.min(userCoord.latitude, poiCoord.latitude);
double minX = Math.min(userCoord.longitude, poiCoord.longitude);
double maxY = Math.max(userCoord.latitude, poiCoord.latitude);
double maxX = Math.max(userCoord.longitude, poiCoord.longitude);
Log.d("minY", " " + minY);
Log.d("minX", " " + minX);
Log.d("maxY", " " + maxY);
Log.d("maxX", " " + maxX);
LatLng northEast = new LatLng(maxY, maxX);
LatLng southWest = new LatLng(minY, minX);
LatLngBounds bounds = new LatLngBounds(southWest, northEast);
// move camera
pMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 40));
// Remove listener to prevent position reset on camera move.
pMap.setOnCameraChangeListener(null);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_poi_map, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded(new LatLng(0.0, 0.0));
}
private void setUpMapIfNeeded(LatLng coord) {
// Do a null check to confirm that we have not already instantiated the map.
if (pMap == null) {
// Try to obtain the map from the SupportMapFragment.
pMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (pMap != null) {
setUpMap(coord);
}
}
}
private void setUpMap(LatLng userCoord) {
pMap.addMarker(new MarkerOptions()
.position(userCoord)
.title("Your location")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_user)));
pMap.animateCamera(CameraUpdateFactory.newLatLng(userCoord));
/* public static CameraUpdate newLatLngZoom (LatLng latLng, float zoom)
* Returns a CameraUpdate that moves the center of the screen to a latitude
* and longitude specified by a LatLng object, and moves to the given zoom
* level.
* Parameters
* latLng a LatLng object containing the desired latitude and longitude.
* zoom the desired zoom level, in the range of 2.0 to 21.0.
* Values below this range are set to 2.0, and values above it are set to 21.0.
* Increase the value to zoom in. Not all areas have tiles at the largest zoom levels.
* Returns
* a CameraUpdate containing the transformation.
*/
pMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userCoord, 15));
}
}
This is a common question and I can never find a good answer for anyone so I'll do my best to help.
This sounds like you are missing the source code for Android. You need to download the Sources for Android SDK in Eclipse with the SDK Manager.
Open the SDK Manager in Eclipse
Find the version of android you want the source for. In this example, Android 4.2 (API17)
Check the box Sources for Android SDK
Click Install # packages
For example
After that, run your program and get to the point that you get that error. Now you will need to attach the documentation you've downloaded
Short
Click the button Edit Source Lookup Path
Click the Default folder
Click Add
Select File System Directory and click OK
Locate your downloaded source code. In this example, look for android-17 for API17. It will be in a directory such as adt-bundle\sdk\sources\android-17
Click OK a few times and your source is now linked.
Long
Click the button Edit Source Lookup Path
Click the Default folder and click Add
Select File System Directory and click OK
Locate your downloaded source code. In this example, look for android-17 for API17. It will be in a directory such as adt-bundle\sdk\sources\android-17
Click OK twice and it should look something like this
Click OK and enjoy your source code
This usually means that you are unable to access the source code whose bytecode is being called. In order to list out the exception you would need the original source which unfortunately is usually unavailable in jar formats.
Your option is to update the .jar file by updating your Android SDK with correct Rev’s and let it compile again to fix the issue.