我有一个游戏对象列表添加到了如图所示的区域内。我需要一个方向输入来选择从原点开始的目标。我已经成功获取了这个原点。
我的第一次尝试是通过 rayCast 来获取它,但是这样做有时候需要直接用射线命中目标对象。如果输入像情况 #1 那就没有问题。
然而,我真正需要的是当输入方向像情况 #2 或 #3 时,输入仍将获得目标。我的第二次尝试是使用 sphereCast 来实现这一点,但仍需要在球体范围内有目标,并且由 sphereCast 击中的多个目标仍需要通过输入选择一个更准确的目标。
既然我拥有所有可能目标的 transform.position,以及原点,我想知道是否有一种更优雅的方法,通过比较这些坐标(原点和目标)的 vector3 来解决这个问题。
以下是我的最新方法:
一般来说,我试图将方向输入的归一化向量与从原点到每个目标的归一化向量在SwitchTarget()之前进行比较。这里的输入方法是游戏手柄轴x和y作为水平和垂直方向。
由于提供的答案与问题相差甚远并被标记为重复发布,因此再次发布此问题(给出的答案仅关于仅按距离查找gameObject,而此问题涉及方向,并且当在方向上发现多个物品时,需要进行二次比较距离部分)。
编辑
经过一些点积试验,现在我确定这更有可能是我想要的方向。尽管还有很多不一致之处需要解决。 以下是我最近的尝试:
我的第一次尝试是通过 rayCast 来获取它,但是这样做有时候需要直接用射线命中目标对象。如果输入像情况 #1 那就没有问题。
然而,我真正需要的是当输入方向像情况 #2 或 #3 时,输入仍将获得目标。我的第二次尝试是使用 sphereCast 来实现这一点,但仍需要在球体范围内有目标,并且由 sphereCast 击中的多个目标仍需要通过输入选择一个更准确的目标。
既然我拥有所有可能目标的 transform.position,以及原点,我想知道是否有一种更优雅的方法,通过比较这些坐标(原点和目标)的 vector3 来解决这个问题。
以下是我的最新方法:
//
// m_targetList is the list containing all GameObjects as GameObjects in other script m_collector. All m_collector does is this.
//
using System.Collections.Generic;
using UnityEngine;
public class TargetSwitcher : MonoBehaviour
{
private TargetCollector m_collector;
private Transform m_origin;
public bool m_targetChanged = false;
public GameObject m_target;
public LayerMask m_targetMask;
private Dictionary<Vector3, float> m_targetInfo = new Dictionary<Vector3, float>();
private void Awake()
{
m_collector = GetComponent<TargetCollector>();
m_origin = GameObject.Find("TargetOrigin").transform;
m_tracker = GameObject.Find("TargetTracker").transform;
m_bound = GetComponent<BoxCollider>();
}
public void UpdateBearing(GameObject origin)
{
m_origin = origin.transform;
foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized
float dist = Vector3.Distance(origin.transform.position, target.transform.position);
m_targetInfo.Add(dir, dist);
}
}
public void SwitchTarget()
{
if (!m_targetChanged)
{
Vector2 dir = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).normalized;
// Find closest direction value from Dictionary to dir of here
// Compare distance from origin if multiple targets and choose the nearest
}
}
public void ReturnToIdle()
{
m_origin.position = m_target.transform.position;
m_targetChanged = false;
m_targetInfo.Clear();
}
public struct TargetInfo
{
public Vector3 bearing;
public float distance;
public TargetInfo(Vector3 bearing, float distance)
{
this.bearing = bearing;
this.distance = distance;
}
}
}
一般来说,我试图将方向输入的归一化向量与从原点到每个目标的归一化向量在SwitchTarget()之前进行比较。这里的输入方法是游戏手柄轴x和y作为水平和垂直方向。
由于提供的答案与问题相差甚远并被标记为重复发布,因此再次发布此问题(给出的答案仅关于仅按距离查找gameObject,而此问题涉及方向,并且当在方向上发现多个物品时,需要进行二次比较距离部分)。
编辑
经过一些点积试验,现在我确定这更有可能是我想要的方向。尽管还有很多不一致之处需要解决。 以下是我最近的尝试:
private void Update()
{
UpdateBearing();
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
if (input != Vector3.zero)
{
SwitchTarget();
}
}
public void UpdateBearing(GameObject origin)
{
m_origin.position = origin.transform.position;
foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized;
if (!m_targetInfo.ContainsKey(target))
{
m_targetInfo.Add(target, dir);
}
}
}
public void SwitchTarget()
{
GameObject oldTarget = m_collector.m_target;
if (!m_targetChanged)
{
Vector3 dir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0).normalized;
Debug.DrawRay(m_origin.position, dir * 100, Color.yellow, 0.5f);
foreach (KeyValuePair<GameObject, Vector3> possibleTarget in m_targetInfo)
{
float dot = Vector3.Dot(dir, possibleTarget.Value);
if (dot > 0.5f) // Compare DP difference of added dot and input dot
{
GameObject newTarget = possibleTarget.Key;
if (oldTarget != newTarget)
{
Debug.Log(possibleTarget.Value + " // " + dot);
m_target = newTarget;
m_collector.m_target = newTarget;
m_targetChanged = true;
}
}
}
}
}
这样,我有点像是在没有使用光线投射并且不错过任何目标的情况下获取了gameObject选择。但是,我确定我需要更好的情况比较而不是if(dot > 0.5f)。此外,我的粗略假设是,如果我不为每个Key更新字典m_targetInfo的值,如果那些目标移动,我会有另一个不一致性。无论如何,我仍然困惑如何正确利用这个来实现我的最终目标。