Bagian 1 Menyiapkan Back4app Parse pada Unity3D Anda.
Pergi ke https://parse.com/docs/downloadsAmbil Unity Proyek Kosong (v1.7.0)
Ambil https://drive.google.com/file/d/0B7k7pGQXUypGTWRqS1BqVDBWQUU/view?usp=sharing untuk diperbarui Parse SDK untuk Unity3D
Terbuka Unity3D Parse Kosong Proyek -> Klik Tingkatkan jika diperlukan.
Ganti Asset / Parse / Parse.Unity.dll dengan yang terbaru.
Pergi ke Asset / Tema
The Parse Initializer GameObject akan kehilangan beberapa script. Tambahkan ParseInitializeBehaviour untuk itu.
Ketik ID Aplikasi Anda, dotnet Key, serverUrl untuk parameter dari dashboard Back4app Anda.
Buat GameObject dan menambahkan komponen script untuk Scene untuk pengujian.
Tambahkan kode berikut ke TestParse.cs
using UnityEngine;
using System.Collections;
using Parse;
using System.Threading.Tasks;
public class TestParse : MonoBehaviour {
// Use this for initialization
void Start () {
ParseObject testObj = new ParseObject("TestObject");
testObj["a"] = "HI";
testObj["b"] = "Back4app";
Task saveTask = testObj.SaveAsync();
}
// Update is called once per frame
void Update () {
}
}using UnityEngine;
using System.Collections;
public class GoogleMap : MonoBehaviour
{
public enum MapType
{
RoadMap,
Satellite,
Terrain,
Hybrid
}
public bool loadOnStart = true;
public bool autoLocateCenter = true;
public GoogleMapLocation centerLocation;
public int zoom = 13;
public MapType mapType;
public int size = 512;
public bool doubleResolution = false;
public GoogleMapMarker[] markers;
public GoogleMapPath[] paths;
void Start() {
if(loadOnStart) Refresh();
}
public void Refresh() {
if(autoLocateCenter && (markers.Length == 0 && paths.Length == 0)) {
Debug.LogError("Auto Center will only work if paths or markers are used.");
}
StartCoroutine(_Refresh());
}
IEnumerator _Refresh ()
{
var url = "http://maps.googleapis.com/maps/api/staticmap";
var qs = "";
if (!autoLocateCenter) {
if (centerLocation.address != "")
qs += "center=" + WWW.UnEscapeURL (centerLocation.address);
else {
qs += "center=" + WWW.UnEscapeURL (string.Format ("{0},{1}", centerLocation.latitude, centerLocation.longitude));
}
qs += "&zoom=" + zoom.ToString ();
}
qs += "&size=" + WWW.UnEscapeURL (string.Format ("{0}x{0}", size));
qs += "&scale=" + (doubleResolution ? "2" : "1");
qs += "&maptype=" + mapType.ToString ().ToLower ();
var usingSensor = false;
#if UNITY_IPHONE
usingSensor = Input.location.isEnabledByUser && Input.location.status == LocationServiceStatus.Running;
#endif
qs += "&sensor=" + (usingSensor ? "true" : "false");
foreach (var i in markers) {
qs += "&markers=" + string.Format ("size:{0}|color:{1}|label:{2}", i.size.ToString ().ToLower (), i.color, i.label);
foreach (var loc in i.locations) {
if (loc.address != "")
qs += "|" + WWW.UnEscapeURL (loc.address);
else
qs += "|" + WWW.UnEscapeURL (string.Format ("{0},{1}", loc.latitude, loc.longitude));
}
}
foreach (var i in paths) {
qs += "&path=" + string.Format ("weight:{0}|color:{1}", i.weight, i.color);
if(i.fill) qs += "|fillcolor:" + i.fillColor;
foreach (var loc in i.locations) {
if (loc.address != "")
qs += "|" + WWW.UnEscapeURL (loc.address);
else
qs += "|" + WWW.UnEscapeURL (string.Format ("{0},{1}", loc.latitude, loc.longitude));
}
}
var req = new WWW (url + "?" + qs);
yield return req;
GetComponent().material.mainTexture = req.texture;
}
}
public enum GoogleMapColor
{
black,
brown,
green,
purple,
yellow,
blue,
gray,
orange,
red,
white
}
[System.Serializable]
public class GoogleMapLocation
{
public string address;
public float latitude;
public float longitude;
}
[System.Serializable]
public class GoogleMapMarker
{
public enum GoogleMapMarkerSize
{
Tiny,
Small,
Mid
}
public GoogleMapMarkerSize size;
public GoogleMapColor color;
public string label;
public GoogleMapLocation[] locations;
}
[System.Serializable]
public class GoogleMapPath
{
public int weight = 5;
public GoogleMapColor color;
public bool fill = false;
public GoogleMapColor fillColor;
public GoogleMapLocation[] locations;
}
Untick AutoLocateCenter.
Ketik beberapa parameter dummy untuk mencoba Google Map.
Jika pesawat menunjukkan lokasi yang benar sebagai parameter Anda, peta Google berhasil terintegrasi. Anda dapat menggunakan metode Refresh untuk me-refresh peta Google untuk mengubah lokasi.
Bagian 3 Mengintegrasikan Karakter dan Berinteraksi dengan data GPS
Buat LocationManager GameObject dan tambahkan kode berikut.Kode ini adalah mendapatkan data GPS dan memperbarui Peta Google ketika data GPS berubah.
using UnityEngine;Mari menguji peta Google lagi.
using System.Collections;
using UnityEngine.UI;
public class LocationManager : MonoBehaviour {
public GameObject map;
public GameObject spawn;
public float lat=0;
public float lon=0;
float lastlat=0,lastlon=0;
public GameObject latText;
public GameObject lonText;
// Use this for initialization
void Start () {
Input.location.Start (); // enable the mobile device GPS
if (Input.location.isEnabledByUser) { // if mobile device GPS is enabled
lat = Input.location.lastData.latitude; //get GPS Data
lon = Input.location.lastData.longitude;
map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
}
}
// Update is called once per frame
void Update () {
// <---------Mobile Device Code----------->
if (Input.location.isEnabledByUser) {
lat = Input.location.lastData.latitude;
lon = Input.location.lastData.longitude;
if (lastlat != lat || lastlon != lon) {
map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
latText.GetComponent<Text> ().text = "Lat" + lat.ToString ();
lonText.GetComponent<Text> ().text = "Lon" + lon.ToString ();
//spawn.GetComponent<Spawn> ().updateMonstersPosition (lon, lat);
//Add above after you complete spawn part
map.GetComponent<GoogleMap> ().Refresh ();
}
lastlat = lat;
lastlon = lon;
}
// <---------Mobile Device Code----------->
// <---------PC Test Code----------->
// if (lastlat != lat || lastlon != lon) {
// map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
// map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
// latText.GetComponent<Text> ().text = "Lat" + lat.ToString ();
// lonText.GetComponent<Text> ().text = "Lon" + lon.ToString ();
// spawn.GetComponent<Spawn> ().updateMonstersPosition (lon, lat);
// map.GetComponent<GoogleMap> ().Refresh ();
// }
// lastlat = lat;
// lastlon = lon;
// <---------PC Test Code----------->
}
public float getLon(){
return lon;
}
public float getLat(){
return lat;
}
}
Hal ini berhasil jika perubahan peta Google ketika Anda mengubah data GPS di Runtime.
Setelah itu, buat Capsule sebagai karakter dan Cube sebagai Arah karakter di atas Google Map. (Bagi saya, saya menempatkan karakter di X: 0 Y: 0,07 Z: 0)
Menambahkan kompas untuk karakter Anda ketika Anda menguji dengan perangkat mobile Anda.
Pastikan karakter Anda berada dengan benar dengan memeriksa Latitude dan Longitude di Google Map.
Bagian 4 Membangkitkan Monsters pada Peta (bagian A)
Foe Membangkitkan Monsters, kita perlu melakukan beberapa perhitungan menempatkan rakasa dengan bujur dan lintang lokasi. Karena rasio antara peta Google, realitas dan Unity3D XYZ-dunia yang berbeda.Untuk mengetahui bagaimana menghitung hubungan antara mereka, kita perlu data dummy.
Untuk detail lebih lanjut: bagaimana menghitung.
http://www.movable-type.co.uk/scripts/latlong.html
Pertama-tama, kita perlu mengatur lintang awal dan bujur di Google Map pertama (Anda dapat memilih di mana Anda ingin) dan mengatur Penanda di Google Map.
Tekan Run, Anda akan menemukan label pada peta Google Anda.
PS: Alasan mengapa kita tidak bisa menggunakan penanda menjadi rakasa karena dikombinasikan dengan tekstur. Penanda itu sendiri adalah bagian dari tekstur tapi tidak Gmeobject sehingga kami tidak dapat melakukan implementasi apapun pada itu.
Selain itu, kita akan membuat beberapa data GPS boneka dari rakasa di server Parse, nanti, jadi kita perlu tahu yang sesuai rasio pada posisi objek rakasa game.
Setelah itu, kita membuat kubus dan menempatkan di atas label.
Merekam posisi ini.
Sekarang, kita perlu mencari jarak yang tepat antara lokasi pemain GPS dan lokasi penanda GPS.
Jarak antara start (37,38373, -122,0133) dan penanda (37,384782, -122,012893) dapat dihitung dengan script ini.
public static double DistanceBetweenPlaces(double lon1, double lat1, double lon2, double lat2)
{
float R = 6371000; // m
double sLat1 = Math.Sin(deg2rad(lat1));
double sLat2 = Math.Sin(deg2rad(lat2));
double cLat1 = Math.Cos(deg2rad(lat1));
double cLat2 = Math.Cos(deg2rad(lat2));
double cLon = Math.Cos(deg2rad(lon1) - deg2rad(lon2));
double cosD = sLat1*sLat2 + cLat1*cLat2*cLon;
double d = Math.Acos(cosD);
double dist = R * d;
return dist;
}
dan kemudian menghitung XYZ jarak dunia antara pembuat CUBE dan Player Kapsul. (-0.563,0.07, -1,915) Dan (0,0.07,0). Ini adalah perhitungan sederhana, jadi saya tidak daftar bagaimana melakukannya.
Setelah itu, rasio tersebut akan ditemukan oleh persamaan ini
Rasio = XYZ jarak dunia / Jarak Exact.
Setelah kita memiliki rasio ini, kita dapat menghitung seberapa jauh rakasa harus ditempatkan sesuai dengan lokasi Player. Namun, lokasi mungkin masih terdefinisi karena kita tidak memiliki bantalan antara pemain dan rakasa.
Untuk menghitung bantalan. Kita dapat menggunakan kode ini.
public static double BearingBetweenPlaces(double lon1,double lat1,double lon2,double lat2){
double y = Math.Sin (deg2rad (lon2) - deg2rad (lon1)) * Math.Cos (deg2rad (lat2));
double x = Math.Cos (deg2rad (lat1)) * Math.Sin (deg2rad (lat2)) - Math.Sin (deg2rad (lat1)) * Math.Cos (deg2rad (lat2)) * Math.Cos (deg2rad (lon2) - deg2rad (lon1));
double bearing = Math.Atan2 (y, x);
return bearing;
}
Setelah kita mendapatkan rasio dan bantalan, adalah mungkin untuk mengkonversi Bujur Latitude lokasi menjadi koordinasi XYZ-dunia, yang berarti kita dapat menempatkan monster dengan lokasi bujur lintang untuk memperbaiki permainan lokasi dunia.
public static double[] convertXZ(double lon1,double lat1,double lon2,double lat2){
double ratio = 0.0162626572;
double bearing = BearingBetweenPlaces (lon1, lat1, lon2, lat2);
double distance = DistanceBetweenPlaces(lon1, lat1, lon2, lat2);
double x = Math.Sin (-bearing) * distance * ratio;
double z = -Math.Cos (bearing) * distance * ratio;
Debug.Log ("X" + x.ToString () + "Z" + z.ToString ());
double[] xz = { x, z };
return xz;
}
Dengan kode di atas, kita tahu koordinasi XYZ yang benar untuk bertelur rakasa.
Bagian 5 Membangkitkan Monsters pada Peta (bagian B)
Sementara kita mampu mengkonversi data Bujur dan Lintang ke dunia game, saatnya sekarang untuk membuat beberapa data rakasa boneka di Back4app parse Server.Pergi ke Parse back4app dashboard Anda dan membuat Rakasa panggilan kelas.
Menambahkan kolom: Lokasi dengan tipe data Geopoint.
Menyisipkan beberapa baris rakasa dummy yang di sekitar Anda.
Monster boneka ditetapkan, mereka menunggu Anda untuk menelepon.
Lalu aku membuat MonsterSpawn GameObject dengan script Bibit.
Drop LocationManager GameObject untuk itu (Untuk Data GPS semakin diperbarui)
M rakasa prefab untuk pemijahan rakasa.
Ini adalah waktu untuk mengambil data rakasa boneka dari back4app untuk program anda.
void Start () {
monsterXZCoordination = new List<double[]>();
monsterLL = new List<double[]> ();
var query = ParseObject.GetQuery ("Monster");
//you can use WhereWithinGeoBox or WhereNear or WhereWithinDistance to simulate pkmgo serach range
playerlon = locationManager.GetComponent<LocationManager>().getLon();
playerlat = locationManager.GetComponent<LocationManager>().getLat();
query.FindAsync ().ContinueWith (t => {
IEnumerable<ParseObject> results = t.Result;
foreach (var result in results) {
ParseGeoPoint temp = result.Get<ParseGeoPoint>("Location");
double[] tempxz = GeoDistance.convertXZ(playerlon,playerlat,temp.Longitude,temp.Latitude);
double[] trueLL = {temp.Longitude,temp.Latitude};
monsterLL.Add(trueLL);
monsterXZCoordination.Add(tempxz);
}
spawn = true;
});
}
Kode di atas mendapat hasilnya satu per satu dan mengkonversi data GeoPoint menjadi koordinasi XYZ-dunia, dan kemudian mendorong hasilnya ke Daftar. Setelah menambahkan hasilnya diambil, bibit menjadi benar untuk memungkinkan program menumbuhkan rakasa.
void Update () {
playerlon = locationManager.GetComponent<LocationManager>().getLon();
playerlat = locationManager.GetComponent<LocationManager> ().getLat ();
if (spawn == true) {
monsterSpawn ();
}
if (monster.Count != 0) {
if (lastlon != playerlon || lastlat != playerlat) {
//DebugConsole.Log ("Changing");
updateMonstersPosition ();
}
}
lastlat = playerlat;
lastlon = playerlon;
}
void monsterSpawn(){
//DebugConsole.Log ("HIHIHI");
for (int i = 0; i < monsterXZCoordination.Count; i++) {
GameObject temp = Instantiate (m, new Vector3 ((float)monsterXZCoordination [i][0], 0.07f, (float)monsterXZCoordination [i][1]), new Quaternion (0, 0, 0, 0)) as GameObject;
//DebugConsole.Log (temp.transform.position.ToString());
monster.Add (temp);
}
spawn = false;
}
void updateMonstersPosition(){
timeOfupdate++;
for (int i = 0; i < monster.Count; i++) {
double[] tempxz = GeoDistance.convertXZ(playerlon,playerlat,monsterLL[i][0],monsterLL[i][1]);
monster [i].gameObject.transform.position = new Vector3 ((float)tempxz[0],0.07f,(float)tempxz[1]);
//DebugConsole.Log (timeOfupdate.ToString()+"th update:"+i.ToString()+" "+monster [i].gameObject.transform.position.ToString ());
}
}
public void updateMonstersPosition(double lon,double lat){
timeOfupdate++;
for (int i = 0; i < monster.Count; i++) {
double[] tempxz = GeoDistance.convertXZ(lon,lat,monsterLL[i][0],monsterLL[i][1]);
monster [i].gameObject.transform.position = new Vector3 ((float)tempxz[0],0.07f,(float)tempxz[1]);
//DebugConsole.Log (timeOfupdate.ToString()+"th update:"+i.ToString()+" "+monster [i].gameObject.transform.position.ToString ());
}
}
Setelah Monster yang melahirkan, monster akan terus memperbarui ketika data pemain GPS telah diperbarui.
Pengujian. rakasa tersebut menelurkan di koordinasi XYZ yang benar dengan data Bujur Latitude mereka.
Bagian 6 Cara memindahkan Player (memecahkan google peta tekstur masalah lambat!)
Sampai Bagian 5, pergerakan pemain yang mengandalkan Google Map tekstur memperbarui. Namun, hal ini tidak efektif untuk memainkannya. Pengalaman pengguna tidak baik.Untuk mengatasi masalah ini, kita "membuka" pemain. Membuat pemain bergerak pada peta.
Algoritma belakang mirip memperbarui rakasa. kita menerapkan pada kapsul. membandingkan data GPS terakhir dan data GPS baru untuk menghitung bagaimana seharusnya pemain bergerak dalam dunia game. Seperti kita memperbarui posisi pemain, karena itu kita tidak perlu pembaruan rakasa dan fungsi refresh peta google lagi.
apa yang perlu Anda lakukan: Ubah Modify LocationMaganger.cs
Add GameObject playerCapsule : Drag your capsule to this
comment or delete monster update and google map refresh in update()
Add player movement logic
if (lastlon != 0 && lastlat != 0) {//skip at move player at the first update of GPS
double[] tempXZ = GeoDistance.convertXZ (lastlon, lastlat, lon, lat);
Debug.Log (“Last lon:“ + lastlon.ToString () + “lastlat:“ + lastlat.ToString () + “lon:“ + lon.ToString () + “lat:“ + lat.ToString ());
Debug.Log (“Player should move to X:“ + tempXZ [0].ToString () + “ Z:“ + tempXZ [1].ToString ());
Vector3 newPositionTarget = new Vector3 (playerCapsule.transform.position.x+(float)tempXZ [0], 0.07f, playerCapsule.transform.position.z+(float)tempXZ [1]);
playerCapsule.transform.position = newPositionTarget;
}else map.GetComponent<GoogleMap> ().Refresh ();
***** Ini google peta penyegaran tidak perlu dikomentari, karena kami membutuhkannya untuk init tekstur dan pertama kalinyausing UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LocationManager : MonoBehaviour {
public GameObject map;
public GameObject spawn;
public GameObject playerCapsule;
public float lat=0;
public float lon=0;
float lastlat=0,lastlon=0;
public GameObject latText;
public GameObject lonText;
// Use this for initialization
void Start () {
Input.location.Start (); // enable the mobile device GPS
if (Input.location.isEnabledByUser) { // if mobile device GPS is enabled
lat = Input.location.lastData.latitude; //get GPS Data
lon = Input.location.lastData.longitude;
map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
}
}
// Update is called once per frame
void Update () {
// <–––––––––Mobile Device Code–––––––––––>
if (Input.location.isEnabledByUser) {
lat = Input.location.lastData.latitude;
lon = Input.location.lastData.longitude;
if (lastlat != lat || lastlon != lon) {
map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
latText.GetComponent<Text> ().text = “Lat“ + lat.ToString ();
lonText.GetComponent<Text> ().text = “Lon“ + lon.ToString ();
//spawn.GetComponent<Spawn> ().updateMonstersPosition (lon, lat);
if (lastlon != 0 && lastlat != 0) {//skip at move player at the first update of GPS
double[] tempXZ = GeoDistance.convertXZ (lastlon, lastlat, lon, lat);
Debug.Log (“Last lon:“ + lastlon.ToString () + “lastlat:“ + lastlat.ToString () + “lon:“ + lon.ToString () + “lat:“ + lat.ToString ());
Debug.Log (“Player should move to X:“ + tempXZ [0].ToString () + “ Z:“ + tempXZ [1].ToString ());
Vector3 newPositionTarget = new Vector3 (playerCapsule.transform.position.x+(float)tempXZ [0], 0.07f, playerCapsule.transform.position.z+(float)tempXZ [1]);
playerCapsule.transform.position = newPositionTarget;
}else map.GetComponent<GoogleMap> ().Refresh ();
//map.GetComponent<GoogleMap> ().Refresh ();
}
lastlat = lat;
lastlon = lon;}
// <–––––––––Mobile Device Code–––––––––––>
// <–––––––––PC Test Code–––––––––––>
// if (lastlat != lat || lastlon != lon) {
// map.GetComponent<GoogleMap> ().centerLocation.latitude = lat;
// map.GetComponent<GoogleMap> ().centerLocation.longitude = lon;
// latText.GetComponent<Text> ().text = “Lat“ + lat.ToString ();
// lonText.GetComponent<Text> ().text = “Lon“ + lon.ToString ();
// //spawn.GetComponent<Spawn> ().updateMonstersPosition (lon, lat);
// if (lastlon != 0 && lastlat != 0) {//skip at move player at the first update of GPS
// double[] tempXZ = GeoDistance.convertXZ (lastlon, lastlat, lon, lat);
// Debug.Log (“Last lon:“ + lastlon.ToString () + “lastlat:“ + lastlat.ToString () + “lon:“ + lon.ToString () + “lat:“ + lat.ToString ());
// Debug.Log (“Player should move to X:“ + tempXZ [0].ToString () + “ Z:“ + tempXZ [1].ToString ());
// Vector3 newPositionTarget = new Vector3 (playerCapsule.transform.position.x+(float)tempXZ [0], 0.07f, playerCapsule.transform.position.z+(float)tempXZ [1]);
// playerCapsule.transform.position = newPositionTarget;
// }else map.GetComponent<GoogleMap> ().Refresh ();
// }
// lastlat = lat;
// lastlon = lon;
// <–––––––––PC Test Code–––––––––––>
}
public float getLon(){
return lon;
}
public float getLat(){
return lat;
}
// public IEnumerator WaitForRequest(WWW www){
// yield return www;
// if (www.error == null)
// {
// Debug.Log(“WWW Ok!: “ + www.data);
// } else {
// Debug.Log(“WWW Error: “+ www.error);
// }
// }
}
Komentar di Spawn.cs jika Anda tidak
Kedua, melampirkan kode untuk Anda kamera berikut membuat cam Anda mengikuti Anda karakter (Jangan lupa untuk menyeret kapsul untuk inspektur.
// if (monster.Count != 0) {
// if (lastlon != playerlon || lastlat != playerlat) {
// DebugConsole.Log (“Changing“);
// updateMonstersPosition ();
// }
// }
using UnityEngine;
using System.Collections;
public class follow : MonoBehaviour {
public GameObject player; //Public variable to store a reference to the player game object
private Vector3 offset; //Private variable to store the offset distance between the player and camera
// Use this for initialization
void Start ()
{
//Calculate and store the offset value by getting the distance between the player‘s position and camera‘s position.
offset = transform.position – player.transform.position;
}
// LateUpdate is called after Update each frame
void LateUpdate ()
{
// Set the position of the camera‘s transform to be the same as the player‘s, but offset by the calculated offset distance.
transform.position = player.transform.position + offset;
}
}