英文:
How to get an actual direction like east - west in unity?
问题
我正在使用Google API在Unity中显示地图,并从玩家位置生成地图上的对象。现在我想知道实际的方向。这意味着从Google地图或Google API中识别方向(东西方向)。
> 我编写了以下代码,但它不会给我实际的方向。
var v = transform.forward;
v.y = 0;
v.Normalize();
if (Vector3.Angle(v, Vector3.forward) <= 45.0) {
Debug.Log("北");
}
else if (Vector3.Angle(v, Vector3.right) <= 45.0) {
Debug.Log("东");
}
else if (Vector3.Angle(v, Vector3.back) <= 45.0) {
Debug.Log("南");
}
else {
Debug.Log("西");
}
英文:
I am using google API to show a map in unity and also generate object on map's location from player position. Now I want to know actual direction. It means identify direction (east-west) from google maps or google API.
> I made a code but it doesn't give me actual direction.
var v = transform.forward;
v.y = 0;
v.Normalize();
if (Vector3.Angle(v, Vector3.forward) <= 45.0) {
Debug.Log("North");
}
else if (Vector3.Angle(v, Vector3.right) <= 45.0) {
Debug.Log("East");
}
else if (Vector3.Angle(v, Vector3.back) <= 45.0) {
Debug.Log("South");
}
else {
Debug.Log("West");
}
答案1
得分: 3
// language-all: lang-c#
using `Vector3.forward`
> 缩写表示`new Vector3(0, 0, 1)`的写法。
返回Unity自身的前向Z轴方向。这完全取决于您启动Unity/您的应用程序时设备的方向,与真实世界坐标无关。
---
您可能更想要的是[`Compass`](https://docs.unity3d.com/ScriptReference/Compass.html),它返回您手机的实际方向,例如使用[`magneticHeading`](https://docs.unity3d.com/ScriptReference/Compass-magneticHeading.html)
> 相对于**磁性**北极的角度。
>
> 此属性中的值始终相对于屏幕顶部在其当前方向上进行测量。磁性北极的方向与真正的地理北极不完全相同 - 要获得精确的方向,请使用[`trueHeading`](https://docs.unity3d.com/ScriptReference/Compass-trueHeading.html)属性。
>
> ```csharp
> public class Example : MonoBehaviour
> {
> void Update()
> {
> // 将对象定向到磁性北方。
> transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);
> }
> }
> ```
或者使用[`trueHeading`](https://docs.unity3d.com/ScriptReference/Compass-trueHeading.html)
> 相对于**地理**北极的角度。
>
> 此属性中的值始终相对于屏幕顶部在其当前方向上进行测量。请注意,如果您想使此属性包含有效值,必须通过调用`Input.location.Start()`启用位置更新。
>
> ```csharp
> using UnityEngine;
>
> public class Example : MonoBehaviour
> {
> void Start()
> {
> Input.location.Start();
> }
>
> void Update()
> {
> // 将对象定向北方。
> transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
> }
> }
> ```
---
因此,对于您的用例,您可以简单地使用:
```csharp
using UnityEngine;
public enum Heading
{
North,
East,
South,
West
}
public class Example : MonoBehaviour
{
[Header("Debug")]
[SerializeField] [Range(0f, 360f)] private float northHeading;
[Header("OutputValues")]
[SerializeField] private float myHeading;
[SerializeField] private float dif;
[SerializeField] private Heading heading;
// 每帧调用一次Update
private void Update()
{
// 仅使用对象方向的Y分量
// 始终返回0到360之间的值
myHeading = transform.eulerAngles.y;
// 这也始终是0到360之间的值
northHeading = Input.compass.magneticHeading;
dif = myHeading - northHeading;
// 将值包装在0到360之间
if (dif < 0) dif += 360f;
if (dif > 45 && dif <= 135)
{
heading = Heading.East;
}
else if (dif > 135 && dif <= 225)
{
heading = Heading.South;
}
else if (dif > 225 && dif <= 315)
{
heading = Heading.West;
}
else
{
heading = Heading.North;
}
}
// 仅用于调试和演示
// 画一个指向北方的指针
private void OnDrawGizmos()
{
var northDirection = (Quaternion.Euler(0, northHeading, 0) * Vector3.forward).normalized;
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, transform.position + northDirection);
var objectDirection = (Quaternion.Euler(0, transform.eulerAngles.y, 0) * Vector3.forward).normalized;
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position, transform.position + objectDirection);
}
}
在这个小演示中,您可以看到对象前方方向的蓝色指针和北方方向的红色矢量。您可以看到Heading
枚举值如何根据对象的方向而变化。
由于我在PC上执行此操作,我必须手动“调整”北方方向,稍后您将从您的手机获得此信息。
<details>
<summary>英文:</summary>
<!-- language-all: lang-c# -->
using `Vector3.forward`
> Shorthand for writing `new Vector3(0, 0, 1)`.
returns you the forward Z axis direction of Unity itself. This depends entirely on the orientation of your device when you started Unity/your app and has nothing to do with real world coordinates.
---
You are probably rather looking for [`Compass`](https://docs.unity3d.com/ScriptReference/Compass.html) which returns the actual orientation of your phone e.g. using [`magneticHeading`](https://docs.unity3d.com/ScriptReference/Compass-magneticHeading.html)
> The heading in degrees relative to the **magnetic** North Pole.
>
> The value in this property is always measured relative to the top of
> the screen in its current orientation. The heading of magnetic north
> is not exactly the same as true geographical north - to get the exact
> heading, use the [`trueHeading`](https://docs.unity3d.com/ScriptReference/Compass-trueHeading.html) property.
>
> public class Example : MonoBehaviour
> {
> void Update()
> {
> // Orient an object to point to magnetic north.
> transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);
> }
> }
or using the [`trueHeading`](https://docs.unity3d.com/ScriptReference/Compass-trueHeading.html)
> The heading in degrees relative to the **geographic** North Pole.
>
> The value in this property is always measured relative to the top of
> the screen in its current orientation. Note, that if you want this
> property to contain a valid value, you must also enable location
> updates by calling `Input.location.Start()`.
>
> using UnityEngine;
>
> public class Example : MonoBehaviour
> {
> void Start()
> {
> Input.location.Start();
> }
>
> void Update()
> {
> // Orient an object to point northward.
> transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
> }
> }
---
So for your use case you would simply use e.g.
using UnityEngine;
public enum Heading
{
North,
East,
South,
West
}
public class Example : MonoBehaviour
{
[Header("Debug")]
[SerializeField] [Range(0f, 360f)] private float northHeading;
[Header("OutputValues")]
[SerializeField] private float myHeading;
[SerializeField] private float dif;
[SerializeField] private Heading heading;
// Update is called once per frame
private void Update()
{
// only use the Y component of the objects orientation
// always returns a value between 0 and 360
myHeading = transform.eulerAngles.y;
// also this is always a value between 0 and 360
northHeading = Input.compass.magneticHeading;
dif = myHeading - northHeading;
// wrap the value so it is always between 0 and 360
if (dif < 0) dif += 360f;
if (dif > 45 && dif <= 135)
{
heading = Heading.East;
}
else if (dif > 135 && dif <= 225)
{
heading = Heading.South;
}
else if (dif > 225 && dif <= 315)
{
heading = Heading.West;
}
else
{
heading = Heading.North;
}
}
// Only for debug and demo
// draw a pointer towards north
private void OnDrawGizmos()
{
var northDirection = (Quaternion.Euler(0, northHeading, 0) * Vector3.forward).normalized;
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, transform.position + northDirection);
var objectDirection = (Quaternion.Euler(0, transform.eulerAngles.y, 0) * Vector3.forward).normalized;
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position, transform.position + objectDirection);
}
}
---
In the little demo you can see the blue pointer for the object's forward direction and the red vector for the north direction. You can see how the `Heading` enum value changes according to the objects orientation.
*Since I did it on a PC I had to manually "adjust" a north direction, later you will get this from your phone.*
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/kAKXh.gif
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论